render.c (3982B)
1 #include <math.h> 2 3 #include "xdraw.h" 4 #include "common.h" 5 #define PI 3.141592654 6 7 //Our rendered pixel layout, to be processed by the front end 8 uint8_t PixBuffer[XREZ * YREZ]; 9 10 extern uint32_t Palette[16]; 11 12 extern uint8_t spritedata[504]; 13 extern uint8_t frame_honey_run_1[1444]; 14 15 typedef struct 16 { 17 uint8_t width, height; 18 uint8_t *pixels; 19 } frame; 20 21 //TODO: Need to initialize these in a way that uses the enum 22 frame Frames[F_TOTAL] = { 23 {28, 18, spritedata}, 24 {28, 18, spritedata}, 25 }; 26 27 uint32_t camX, camY, camZ; 28 29 typedef struct 30 { 31 double x, y; 32 } vec2; 33 34 typedef struct 35 { 36 //relative to actor origin 37 vec2 loc; 38 uint32_t u, v; 39 } vert; 40 41 uint32_t *GetPalette() 42 { 43 return Palette; 44 } 45 46 uint8_t *GetPixBuf() 47 { 48 return PixBuffer; 49 } 50 51 void InitRender() 52 { 53 camZ = 1; 54 } 55 56 void ClearScreen() 57 { 58 for (int i = 0; i < XREZ * YREZ; i++) 59 { 60 PixBuffer[i] = 1; 61 } 62 } 63 64 void PlotPix(int x, int y, uint8_t color) 65 { 66 PixBuffer[XREZ * y + x] = color; 67 } 68 69 //cross product 70 float EdgeFunc( vec2 v1, vec2 v2, vec2 v3) 71 { 72 return (v3.x - v1.x) * 73 (v2.y - v1.y) - 74 (v3.y - v1.y) * 75 (v2.x - v1.x); 76 } 77 78 uint8_t GetColor(uint32_t sp_in, uint32_t u, uint32_t v) 79 { 80 uint8_t *sppixels = Frames[sp_in].pixels; 81 uint32_t spritewidth = Frames[sp_in].width; 82 return *(sppixels + ( v * spritewidth + u)); 83 } 84 85 void DrawTri ( uint32_t sp_in, 86 vert p1, 87 vert p2, 88 vert p3 ) 89 { 90 for (int y = 0; y < YREZ; ++y) 91 { 92 for (int x = 0; x < XREZ; ++x) 93 { 94 int u, v; 95 vec2 point; 96 point.x = x; 97 point.y = y; 98 float area = EdgeFunc(p1.loc, p2.loc, p3.loc); 99 float w1 = EdgeFunc(p2.loc, p3.loc, point); 100 float w2 = EdgeFunc(p3.loc, p1.loc, point); 101 float w3 = EdgeFunc(p1.loc, p2.loc, point); 102 if (w1 >= 0 && w2 >= 0 && w3 >= 0) 103 { 104 // barycentric coordinates 105 w1 /= area; 106 w2 /= area; 107 w3 /= area; 108 //calculate UV data from them 109 u = w1 * p1.u + w2 * p2.u + w3 * p3.u; 110 v = w1 * p1.v + w2 * p2.v + w3 * p3.v; 111 uint8_t color = GetColor(sp_in, u, v); 112 if (color) //0 is transparency 113 { 114 PlotPix(x, y, GetColor(sp_in, u, v)); 115 } 116 } 117 } 118 } 119 120 } 121 122 vec2 RotateVec(vec2 in, double angle) 123 { 124 vec2 out; 125 out.x = cos(angle) * in.x - sin(angle) * in.y; 126 out.y = sin(angle) * in.x + cos(angle) * in.y; 127 return out; 128 } 129 130 void DrawSprite( uint32_t sp_in, 131 double posx, 132 double posy, 133 double angle, 134 uint8_t distance ) 135 { 136 uint8_t spritewidth = Frames[sp_in].width; 137 uint8_t spriteheight = Frames[sp_in].height; 138 139 vert p1, p2, p3; 140 p1.loc.x = -(float)(spritewidth / 2) / distance; 141 p1.loc.y = -(float)(spriteheight / 2) / distance; 142 143 p2.loc.x = -(float)(spritewidth / 2) / distance; 144 p2.loc.y = (float)(spriteheight / 2) / distance; 145 146 p3.loc.x = (float)(spritewidth / 2) / distance; 147 p3.loc.y = -(float)(spriteheight / 2) / distance; 148 149 //WINDING ORDER IS IMPORTANT! 150 //Tris must be wound counter-clackwise 151 p1.u = 0; 152 p1.v = 0; 153 154 p2.u = 0; 155 p2.v = spriteheight; 156 157 p3.u = spritewidth; 158 p3.v = 0; 159 160 vert z1, z2, z3; 161 z1.loc.x = (float)(spritewidth / 2) / distance; 162 z1.loc.y = (float)(spriteheight / 2) / distance; 163 z2.loc.x = (float)(spritewidth / 2) / distance; 164 z2.loc.y = -(float)(spriteheight / 2) / distance; 165 z3.loc.x = -(float)(spritewidth / 2) / distance; 166 z3.loc.y = (float)(spriteheight / 2) / distance; 167 168 z1.u = spritewidth; 169 z1.v = spriteheight; 170 171 z2.u = spritewidth; 172 z2.v = 0; 173 174 z3.u = 0; 175 z3.v = spriteheight; 176 177 p1.loc = RotateVec(p1.loc, angle); 178 p2.loc = RotateVec(p2.loc, angle); 179 p3.loc = RotateVec(p3.loc, angle); 180 z1.loc = RotateVec(z1.loc, angle); 181 z2.loc = RotateVec(z2.loc, angle); 182 z3.loc = RotateVec(z3.loc, angle); 183 184 p1.loc.x += posx; 185 p1.loc.y += posy; 186 p2.loc.x += posx; 187 p2.loc.y += posy; 188 p3.loc.x += posx; 189 p3.loc.y += posy; 190 191 z1.loc.x += posx; 192 z1.loc.y += posy; 193 z2.loc.x += posx; 194 z2.loc.y += posy; 195 z3.loc.x += posx; 196 z3.loc.y += posy; 197 198 DrawTri(sp_in, z1, z2, z3); 199 DrawTri(sp_in, p1, p2, p3); 200 } 201 202 void DrawFrame(uint32_t frameno, double angle) 203 { 204 ClearScreen(); 205 DrawSprite(frameno, XREZ / 2, YREZ / 2, angle, camZ); 206 }