Skip to content

Instantly share code, notes, and snippets.

@shonumi
Created September 25, 2016 13:44
Show Gist options
  • Save shonumi/288947e6173bfb41989b8fa8ad042cd8 to your computer and use it in GitHub Desktop.
Save shonumi/288947e6173bfb41989b8fa8ad042cd8 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"
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