Skip to content

Instantly share code, notes, and snippets.

@zid

zid/cube.c Secret

Last active December 1, 2022 07:47
Show Gist options
  • Save zid/01054569dea724a527ba0c9fb989634e to your computer and use it in GitHub Desktop.
Save zid/01054569dea724a527ba0c9fb989634e to your computer and use it in GitHub Desktop.
#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