Created
September 25, 2016 13:44
-
-
Save shonumi/288947e6173bfb41989b8fa8ad042cd8 to your computer and use it in GitHub Desktop.
Don't lose this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <cmath> | |
#include <SDL2/SDL.h> | |
#include "common.h" | |
struct affine_data | |
{ | |
double dx; | |
double dy; | |
double dmx; | |
double dmy; | |
double xref; | |
double yref; | |
}; | |
u32 get_pixel_pos(int x, int y) | |
{ | |
u32 result_pos = (y * 640) + x; | |
return result_pos; | |
} | |
void get_texel_pos(affine_data& matrix, double screen_x, double screen_y, double& tx, double& ty) | |
{ | |
if((matrix.dx == 0) || (matrix.dmy == 0)) { tx = -1.0; ty = -1.0; return; } | |
double tx_comp, ty_comp = 0.0; | |
//Shift by SX and SY before doing anything else | |
screen_x -= matrix.xref; | |
screen_y -= matrix.yref; | |
//Solve for TX first | |
if(matrix.dmx == 0) | |
{ | |
tx = screen_x * (1 / matrix.dx); | |
ty_comp = (matrix.dmy); | |
ty = (screen_y - (matrix.dy * tx)) / ty_comp; | |
} | |
//Solve for TY first | |
else if(matrix.dy == 0) | |
{ | |
ty = screen_y * (1 / matrix.dmy); | |
tx_comp = matrix.dx; | |
tx = (screen_x - (matrix.dmx * ty)) / tx_comp; | |
} | |
//Solve for TY first (system of equations) | |
else | |
{ | |
tx_comp = (screen_x - matrix.dmx) * (1 / matrix.dx); | |
ty_comp = (matrix.dy * tx_comp) + (matrix.dmy); | |
ty = screen_y / ty_comp; | |
tx = ty * tx_comp; | |
} | |
} | |
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 | |
affine_data m_matrix; | |
m_matrix.dx = 0.50; | |
m_matrix.dy = 0.0; | |
m_matrix.dmx = 0; | |
m_matrix.dmy = 0.50; | |
m_matrix.xref = 160.0; | |
m_matrix.yref = 120.0; | |
bool wrap = false; | |
//For each scanline calculate affine coordinates | |
for(u32 y = 0; y < 480; y++) | |
{ | |
double tx_0, tx_1 = 0.0; | |
double ty_0, ty_1 = 0.0; | |
//Calculate first and second left-most pixels on this scanline | |
get_texel_pos(m_matrix, 0, y, tx_0, ty_0); | |
get_texel_pos(m_matrix, 1, y, tx_1, ty_1); | |
//Calculate the slope | |
double x_diff = tx_1 - tx_0; | |
double y_diff = ty_1 - ty_0; | |
//Save affine coordinates | |
for(u32 x = 0; x < 640; x++) | |
{ | |
affine_coords[x][0] = tx_0; | |
affine_coords[x][1] = ty_0; | |
tx_0 += x_diff; | |
ty_0 += y_diff; | |
} | |
//Apply affine transformation to final buffer | |
for(u32 x = 0; x < 640; x++) | |
{ | |
u32 final_pos = get_pixel_pos(x, y); | |
u32 tex_pos; | |
s32 new_x = affine_coords[x][0]; | |
s32 new_y = affine_coords[x][1]; | |
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