Skip to content

Instantly share code, notes, and snippets.

@shonumi
Created September 4, 2016 21:58
Show Gist options
  • Save shonumi/b3db730d5c9c2b6e90340f4a2817adb7 to your computer and use it in GitHub Desktop.
Save shonumi/b3db730d5c9c2b6e90340f4a2817adb7 to your computer and use it in GitHub Desktop.
Don't lose this.
#include <iostream>
#include <string>
#include <cmath>
#include <SDL2/SDL.h>
#include "common.h"
u32 get_pixel_pos(int x, int y)
{
u32 result_pos = (y * 640) + x;
return result_pos;
}
int main(int argc, char* args[])
{
//Initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
std::cout<<"Error - Could not init SDL\n";
return -1;
}
//Grab texture file name and open it as a BMP
//Make sure this is 640x480
std::string texture_file = args[1];
SDL_Surface* texture = NULL;
texture = SDL_LoadBMP(texture_file.c_str());
if(texture == NULL)
{
std::cout<<"Error - Failed to load texture file " << texture_file << "\n";
return -1;
}
//Setup window + final screen texture
SDL_Window* window = SDL_CreateWindow("Affine Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
SDL_Surface* final_screen = SDL_GetWindowSurface(window);
//Set up screen buffer
u32 screen_buffer[0x4B000];
for(u32 x = 0; x < 0x4B000; x++) { screen_buffer[x] = 0xFF000000; }
//Set up texture buffer
u32 texture_buffer[0x4B000];
if(SDL_MUSTLOCK(texture)){ SDL_LockSurface(texture); }
u8* in_pixel_data = (u8*)texture->pixels;
for(u32 x = 0, y = 0; x < 0x4B000; x++, y+=3)
{
u32 temp = (0xFF000000 | (in_pixel_data[y+2] << 16) | (in_pixel_data[y+1] << 8) | (in_pixel_data[y]));
texture_buffer[x] = temp;
}
if(SDL_MUSTLOCK(texture)){ SDL_UnlockSurface(texture); }
//Set up affine coordinate buffer
double affine_coords[640][2];
for(u32 x = 0; x < 640; x++) { affine_coords[x][0] = affine_coords[x][1] = 0.0; }
//Setup affine matrix
double dx = 0.50;
double dy = 0.0;
double dmx = 0.1;
double dmy = 0.50;
double xref = 100.0;
double yref = -200.0;
bool wrap = true;
//For each scanline calculate affine coordinates
for(u32 y = 0; y < 480; y++)
{
double tx_0, tx_1 = 0.0;
double sy = double(y);
//Find the intercepts of Line 0 and Line 1 with the current screen scanline
double ty_0 = 0;
double ty_1 = 1;
//Use this formulate to find TX -> TX = ((SY) - (DMY*TY)) / DY
if(dy != 0)
{
tx_0 = ((sy - yref) - (dmy * ty_0)) / dy;
tx_1 = ((sy - yref) - (dmy * ty_1)) / dy;
}
//If DY and/or DMY are both zero, there are no intercepts
else if(dy == 0)
{
if(dmy != 0)
{
ty_0 = (sy - yref) / dmy;
ty_1 = (sy - yref) / dmy;
}
else
{
ty_0 = 479 + sy;
ty_1 = 479 + sy;
}
tx_0 = 0;
tx_1 = 1;
}
//std::cout<<"TX_0 -> " << tx_0 << "\n";
//std::cout<<"TX_1 -> " << tx_1 << "\n";
//Find the slope between these points
double unit_slope_x = tx_0 - tx_1;
double unit_slope_y = ty_0 - ty_1;
std::cout<<"UNIT SLOPE X -> " << unit_slope_x << "\n";
std::cout<<"UNIT SLOPE Y -> " << unit_slope_y << "\n";
//Calculate screen X coordinates for the above points from the BG2
//Use this formula SX = (DX*TX) + (DMX*TY)
double sx_0 = (dx * tx_0) + (dmx * ty_0) + xref;
double sx_1 = (dx * tx_1) + (dmx * ty_1) + xref;
//std::cout<<"SX 0 Coords -> (" << sx_0 << ", " << sy << ")\n";
//std::cout<<"SX 1 Coords -> (" << sx_1 << ", " << sy << ")\n";
//Find the distance between these two screen coordinates, divide the slope by them
double x_dist = sx_0 - sx_1;
if(x_dist != 0)
{
unit_slope_x /= x_dist;
unit_slope_y /= x_dist;
}
//std::cout<<"X DIST -> " << x_dist << "\n";
//std::cout<<"NEW UNIT SLOPE X -> " << unit_slope_x << "\n";
//std::cout<<"NEW UNIT SLOPE Y -> " << unit_slope_y << "\n";
double temp_tx = 0.0;
double temp_ty = 0.0;
//Find the BG2 coordinate for S(0, sy)
if(sx_0 > 0)
{
temp_tx = tx_0 - (unit_slope_x * sx_0);
temp_ty = ty_0 - (unit_slope_y * sx_0);
//std::cout<<"CASE 1\n";
//std::cout<<tx_0 << " - (" << sx_0 << " * " << unit_slope_x << ")\n";
//std::cout<<ty_0 << " - (" << sx_0 << " * " << unit_slope_y << ")\n";
}
else if(sx_0 <= 0)
{
temp_tx = tx_0 + (unit_slope_x * sx_0);
temp_ty = ty_0 + (unit_slope_y * sx_0);
//std::cout<<"CASE 2\n";
//std::cout<<tx_0 << " - (" << sx_0 << " * " << unit_slope_x << ")\n";
//std::cout<<ty_0 << " - (" << sx_0 << " * " << unit_slope_y << ")\n";
}
//std::cout<<"START TX -> " << temp_tx << "\n";
//std::cout<<"START TY -> " << temp_ty << "\n";
//Save affine coordinates
for(u32 x = 0; x < 640; x++)
{
affine_coords[x][0] = temp_tx;
affine_coords[x][1] = temp_ty;
temp_tx += unit_slope_x;
temp_ty += unit_slope_y;
}
//Wrap-around correction
double x_correction = 0.0;
double y_correction = 0.0;
if(dmy != 0) { x_correction = ((480.0 * dmx) / dmy) / dmy; }
if(x_correction < 0) { x_correction *= -1; }
//Apply affine transformation to final buffer
for(u32 x = 0; x < 640; x++)
{
u32 final_pos = get_pixel_pos(x, sy);
u32 tex_pos;
s32 new_x = affine_coords[x][0];
s32 new_y = affine_coords[x][1];
if(wrap)
{
while((new_y >= 480) && (dmy != 0))
{
if(dmy > 0)
{
new_y -= (480.0 / dmy);
new_x += x_correction;
}
if(dmy < 0)
{
new_y += (480.0 / dmy);
new_x -= x_correction;
}
}
while((new_y < 0) && (dmy != 0))
{
if(dmy > 0)
{
new_y += (480.0 / dmy);
new_x -= x_correction;
}
if(dmy < 0)
{
new_y -= (480.0 / dmy);
new_x += x_correction;
}
}
while((new_x >= 640) && (dx != 0))
{
if(dx > 0) { new_x -= (640.0 / dx); }
if(dx < 0) { new_x += (640.0 / dx); }
}
while((new_x < 0) && (dx != 0))
{
if(dx > 0) { new_x += (640.0 / dx); }
if(dx < 0) { new_x -= (640.0 / dx); }
}
}
if((new_x >= 0) && (new_x < 640) && (new_y >= 0) && (new_y < 480))
{
tex_pos = get_pixel_pos(new_x, new_y);
screen_buffer[final_pos] = texture_buffer[tex_pos];
}
}
std::cout<<"LINE " << y << " START COORDS -> (" << affine_coords[0][0] << ", " << affine_coords[0][1] << ")\n\n\n";
}
//Copy buffer to final screen
if(SDL_MUSTLOCK(final_screen)){ SDL_LockSurface(final_screen); }
u32* out_pixel_data = (u32*)final_screen->pixels;
for(u32 x = 0; x < 0x4B000; x++) { out_pixel_data[x] = screen_buffer[x]; }
if(SDL_MUSTLOCK(final_screen)){ SDL_UnlockSurface(final_screen); }
//Draw window
if(SDL_UpdateWindowSurface(window) != 0)
{
std::cout<<"Error - Could not blit\n";
return -1;
}
SDL_SaveBMP(final_screen, "pp.bmp");
SDL_Delay(2000);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment