Created
September 4, 2016 21:58
-
-
Save shonumi/b3db730d5c9c2b6e90340f4a2817adb7 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" | |
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