-
-
Save zid/01054569dea724a527ba0c9fb989634e to your computer and use it in GitHub Desktop.
This file contains 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 <stdio.h> | |
#include <math.h> | |
#include <stdlib.h> | |
#include "sdl.h" | |
#define W 640 | |
#define H 512 | |
#define RED 0xFF0000 | |
#define GREEN 0xFF00 | |
#define BLUE 0xFF | |
#define ORANGE 0xFF8040 | |
#define CYAN 0xFFFF | |
#define WHITE 0xFFFFFF | |
struct uv | |
{ | |
float x, y; | |
}; | |
struct v3 | |
{ | |
union { | |
struct { | |
int x, y, z; | |
}; | |
int v[3]; | |
}; | |
struct uv uv[2]; | |
}; | |
struct f3 | |
{ | |
union { | |
struct { | |
float x, y, z; | |
}; | |
float v[3]; | |
}; | |
}; | |
struct triangle { | |
struct f3 p[3]; | |
}; | |
static struct v3 cube[8] = | |
{ | |
{ 1, 1, 1}, | |
{ 1, 1, -1}, | |
{ 1, -1, -1}, | |
{ 1, -1, 1}, | |
{-1, 1, 1}, | |
{-1, 1, -1}, | |
{-1, -1, -1}, | |
{-1, -1, 1} | |
}; | |
static struct f3 m_rot_xyz(int x, int y, int z, float xa, float ya, float za) | |
{ | |
struct f3 v; | |
float f[8]; | |
f[0] = cos(ya)*cos(za); | |
f[3] = cos(ya)*sin(za); | |
f[6] = -sin(ya); | |
f[1] = cos(za)*sin(xa)*sin(ya)-cos(xa)*sin(za); | |
f[4] = cos(xa)*cos(za)+sin(xa)*sin(ya)*sin(za); | |
f[7] = cos(ya)*sin(xa); | |
f[2] = cos(xa)*cos(za)*sin(ya)+sin(xa)*sin(za); | |
f[5] = cos(xa)*sin(ya)*sin(za)-cos(za)*sin(xa); | |
f[8] = cos(xa)*cos(ya); | |
v.x = (f[0] * x) + (f[1] * y) + (f[2] * z); | |
v.y = (f[3] * x) + (f[4] * y) + (f[5] * z); | |
v.z = (f[6] * x) + (f[7] * y) + (f[8] * z); | |
return v; | |
} | |
static void pset(unsigned int *fb, int x, int y, uint32_t c) | |
{ | |
if(x < 0 || y < 0 || x >= W || y >= H) | |
{ | |
printf("Draw to pixel %d,%d\n", x, y); | |
exit(0); | |
} | |
fb[(y*2+0)*W*2+x*2+0] = c; | |
fb[(y*2+0)*W*2+x*2+1] = c; | |
fb[(y*2+1)*W*2+x*2+0] = c; | |
fb[(y*2+1)*W*2+x*2+1] = c; | |
} | |
static void pline(unsigned int *fb, uint32_t x, uint32_t x2, uint32_t y, uint32_t c) | |
{ | |
uint32_t l, r; | |
if(x2 > x) | |
{ | |
l = x; | |
r = x2; | |
} else | |
{ | |
l = x2; | |
r = x; | |
} | |
for(; l <= r; l++) | |
pset(fb, l, y, c); | |
} | |
static void swap_point(struct f3 *p1, struct f3 *p2) | |
{ | |
struct f3 t = *p1; | |
*p1 = *p2; | |
*p2 = t; | |
} | |
static void sort_triangle(struct triangle *t) | |
{ | |
if(t->p[0].y > t->p[1].y) | |
swap_point(&t->p[0], &t->p[1]); | |
if(t->p[1].y > t->p[2].y) | |
swap_point(&t->p[1], &t->p[2]); | |
if(t->p[0].y > t->p[1].y) | |
swap_point(&t->p[0], &t->p[1]); | |
} | |
static void draw_triangle(unsigned int *fb, struct triangle *t, int col) | |
{ | |
#define Ax (t->p[0].x) | |
#define Ay (t->p[0].y) | |
#define Bx (t->p[1].x) | |
#define By (t->p[1].y) | |
#define Cx (t->p[2].x) | |
#define Cy (t->p[2].y) | |
float x, x2, y, ACxs, Bxs; | |
if(Cx == Ax) | |
ACxs = 0; | |
else | |
ACxs = (Cx - Ax)/(float)(Cy - Ay); | |
Bxs = (Bx-Ax)/(float)(By-Ay+1); | |
x = Ax; | |
y = Ay; | |
x2 = Ax; | |
while(y <= By) | |
{ | |
pline(fb, x, x2, y++, col); | |
x += ACxs; | |
x2 += Bxs; | |
} | |
/* Draw bottom triangle [B,C,(midpoint of AC)] */ | |
x2 = Bx; | |
if(Cx == Bx) | |
Bxs = 0.0f; | |
else | |
Bxs = (Cx-Bx)/(float)(Cy-By); | |
while(y <= Cy) | |
{ | |
pline(fb, x, x2, y++, col); | |
x += ACxs; | |
x2 += Bxs; | |
} | |
} | |
static float backface(struct triangle *t) | |
{ | |
struct f3 v1, v2, cp; | |
v1.x = t->p[2].x - t->p[0].x; | |
v1.y = t->p[2].y - t->p[0].y; | |
v1.z = t->p[2].z - t->p[0].z; | |
v2.x = t->p[1].x - t->p[0].x; | |
v2.y = t->p[1].y - t->p[0].y; | |
v2.z = t->p[1].z - t->p[0].z; | |
cp.x = (v1.y * v2.z) - (v1.z * v2.y); | |
cp.y = (v1.z * v2.x) - (v1.x * v2.z); | |
cp.z = (v1.x * v2.y) - (v1.y * v2.x); | |
return ((cp.x * 0) + (cp.y * 0) + (cp.z * -1)); | |
} | |
static void tri(unsigned int *fb, struct f3 *p, int a, int b, int c, int col) | |
{ | |
struct triangle t; | |
float bf; | |
t.p[0] = p[a]; | |
t.p[1] = p[b]; | |
t.p[2] = p[c]; | |
bf = backface(&t); | |
printf("Triangle: (%.0f,%.0f)-(%.0f,%.0f)-(%.0f,%.0f): bf: %f\n", | |
t.p[0].x, t.p[0].y, | |
t.p[1].x, t.p[1].y, | |
t.p[2].x, t.p[2].y, | |
bf | |
); | |
if(bf < 0.0f) | |
return; | |
sort_triangle(&t); | |
draw_triangle(fb, &t, col); | |
} | |
static float xangle, yangle, zangle; | |
static void draw(unsigned int *fb) | |
{ | |
struct f3 p[8] = {0}; | |
for(int i = 0; i < sizeof cube / sizeof cube[0]; i++) | |
{ | |
struct f3 v; | |
int x, y; | |
v = m_rot_xyz( | |
cube[i].x * 200, cube[i].y * 200, cube[i].z * 200, | |
xangle, yangle, zangle | |
); | |
x = v.x / ((v.z+1600)/1000.0); | |
y = v.y / ((v.z+1600)/1000.0); | |
x += W/2; | |
y += H/2; | |
p[i].x = x; | |
p[i].y = y; | |
p[i].z = v.z; | |
xangle += 0.002f; | |
yangle += 0.00013f; | |
zangle += 0.0007f; | |
} | |
tri(fb, p, 0, 1, 2, RED); | |
tri(fb, p, 3, 0, 2, RED); | |
tri(fb, p, 0, 5, 1, GREEN); | |
tri(fb, p, 0, 4, 5, GREEN); | |
tri(fb, p, 1, 5, 6, BLUE); | |
tri(fb, p, 2, 1, 6, BLUE); | |
tri(fb, p, 6, 3, 2, WHITE); | |
tri(fb, p, 7, 3, 6, WHITE); | |
tri(fb, p, 5, 7, 6, ORANGE); | |
tri(fb, p, 7, 5, 4, ORANGE); | |
tri(fb, p, 0, 7, 4, CYAN); | |
tri(fb, p, 7, 0, 3, CYAN); | |
Sleep(10); | |
} | |
int main(void) | |
{ | |
unsigned int *fb; | |
sdl_init(); | |
fb = sdl_get_framebuffer(); | |
while(!sdl_update()) | |
{ | |
printf("Frame\n"); | |
draw(fb); | |
} | |
printf("%f %f %f\n", xangle, yangle, zangle); | |
sdl_quit(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment