aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile17
-rw-r--r--README.md41
-rw-r--r--config.mk4
-rw-r--r--draw.c340
-rw-r--r--draw.h6
-rw-r--r--obj/car.obj108
-rw-r--r--obj/cube.obj25
-rw-r--r--obj/smth.obj22
-rw-r--r--sim.c199
-rw-r--r--sim.h25
-rw-r--r--types.h4
11 files changed, 791 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2553325
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+include config.mk
+
+OBJ = draw.o
+
+all: build run
+
+build: ${OBJ} sim.c
+ ${CC} ${CFLAGS} ${LIBS} ${OBJ} sim.c -o sim
+
+run:
+ ./sim
+
+%.o: %.c
+ ${CC} ${CFLAGS} $< -c
+
+clean:
+ rm *.o sim
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0c5108a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,41 @@
+# 3D triangle renderer
+
+Short interactive C program for rendering 3D triangles.
+
+## Compiling
+
+The only requirement are the SDL2 devel files.
+
+```sh
+make
+```
+
+## Controls
+
+- **W,A,S,D** for moving.
+- **M** for toggling mouse-lock.
+- **arrows** for rotating camera.
+- **J,K** for moving vertically.
+- **I** for object importing.
+- **=/-** for increasing/decreasing speed.
+
+## Object files
+
+Object files are a modified/simplified version of standard .obj files.
+Available potions are the following:
+
+1. **M** *factor* - multiply factor. Vertices added will have their coordinates multiplied.
+2. **v** *x* *y* *z* - add vertex.
+3. **f** *v1* *v2* *v3* - add triangle face with following vertices.
+4. **F** *v1* *v2* *v3* *color* - add triangle face with color and following vertices.
+
+Lines that start with any other character will be ignored.
+
+## TO-DO List
+
+- use matrix math instead of trigonometric formulas.
+- crop triangles close to screen.
+- fix Z depth.
+- faster drawing.
+- config file with controls and defines.
+- organize functions in files properly.
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..1b416d4
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,4 @@
+CFLAGS = -std=c89 -DSDL_DISABLE_IMMINTRIN_H -w -I.
+LIBS = -lm -lSDL2
+
+CC = cc
diff --git a/draw.c b/draw.c
new file mode 100644
index 0000000..9e79b93
--- /dev/null
+++ b/draw.c
@@ -0,0 +1,340 @@
+#include <SDL2/SDL.h>
+#include <math.h>
+/* #include <SDL2/SDL_render.h> */
+
+#include "draw.h"
+#include "sim.h"
+
+/*#define SHADOW*/
+#define TRIANGLELINES
+#define MAXTRIANGLE 2048
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define INTTOCOL(C) (C>>16), ((C>>8)%256), (C%256)
+#define P(a,b,c) ((Point){a, b, c})
+
+const int shadowcol = 0x191919ff;
+
+int w, h;
+SDL_Point *pts_queue;
+int pts_queue_cnt;
+float *pts_depth;
+
+Triangle tgs[MAXTRIANGLE];
+int tgs_cnt;
+
+typedef struct {
+ int x, y;
+} Point2d;
+
+void add_triangle(Point, Point, Point, unsigned int);
+
+void
+add_obj(const char *path, Point off)
+{
+ char s[1024];
+ FILE *f;
+ /* CAP of 1024 vertecies */
+ Point v[1024];
+ Point t[3];
+ int pc = 0;
+ int a, b, c;
+ float mult = 1;
+ unsigned int col;
+
+ if ((f = fopen(path, "r")) == NULL) {
+ printf("%s:%d add_obj(...): Error opening file %s\n", __FILE__, __LINE__, path);
+ return;
+ }
+
+ while (fgets(s, 1024, f) != NULL) {
+ switch (s[0]) {
+ case 'M':
+ sscanf(s, "%*c %f", &mult);
+ break;
+ case 'v':
+ sscanf(s, "%*c %f%f%f", &v[pc].x, &v[pc].y, &v[pc].z);
+ v[pc].x = v[pc].x * mult + off.x;
+ v[pc].y = v[pc].y * mult + off.y;
+ v[pc].z = v[pc].z * mult + off.z;
+ ++pc;
+ break;
+ case 'f':
+ sscanf(s, "%*c %d%d%d", &a, &b, &c);
+ add_triangle(v[a-1], v[b-1], v[c-1], 0x808080ff);
+ t[0] = v[a-1]; t[0].y = 0;
+ t[1] = v[b-1]; t[1].y = 0;
+ t[2] = v[c-1]; t[2].y = 0;
+#ifdef SHADOW
+ add_triangle(t[0], t[1], t[2], shadowcol);
+#endif
+ break;
+ case 'F':
+ sscanf(s, "%*c %d%d%d%x", &a, &b, &c, &col);
+ add_triangle(v[a-1], v[b-1], v[c-1], col);
+ t[0] = v[a-1]; t[0].y = 0;
+ t[1] = v[b-1]; t[1].y = 0;
+ t[2] = v[c-1]; t[2].y = 0;
+#ifdef SHADOW
+ add_triangle(t[0], t[1], t[2], shadowcol);
+#endif
+ break;
+ }
+ }
+
+ fclose(f);
+}
+
+void
+add_obj_interactive()
+{
+ char path[1024];
+ int i;
+ Point offset;
+ printf("PATH: ");
+ fflush(stdout);
+
+ do
+ fgets(path, 1024, stdin);
+ while (path[0] == '\n');
+ printf("OFFSET X Y Z: ");
+ fflush(stdout);
+ scanf("%f%f%f", &offset.x, &offset.y, &offset.z);
+
+ for (i = 0; i < 1024; ++i)
+ if (path[i] == '\n')
+ path[i] = '\0';
+
+ add_obj(path, offset);
+}
+
+void
+redo_obj()
+{
+ tgs_cnt = 0;
+ add_obj("obj/car.obj", P(0,0,0));
+}
+
+void
+make_point_relative(Point *a)
+{
+ double x, y, z;
+ double b, c;
+ x = a->x - cam.pos.x;
+ y = a->y - cam.pos.y;
+ z = a->z - cam.pos.z;
+
+ b = cos(cam.rad) * x + sin(cam.rad) * z;
+ c = cos(cam.rad) * z - sin(cam.rad) * x;
+
+ x = b;
+ z = c;
+
+
+ b = cos(cam.azim) * x + sin(cam.azim) * y;
+ c = cos(cam.azim) * y - sin(cam.azim) * x;
+
+ x = b;
+ y = c;
+
+ a->x = x;
+ a->y = y;
+ a->z = z;
+}
+
+Point2d
+get_point(Point a)
+{
+ Point2d r;
+
+ if (a.x > 0) {
+ if (a.x < 0.01)
+ a.x = 0.01;
+ } else if (a.x > -0.01)
+ a.x = -0.01;
+ r.x = ((float) w) * a.z / (a.x * 2.0 * hfov);
+ r.x += w/2;
+ r.y = ((float) h) * a.y / (a.x * 2.0 * vfov);
+ r.y = h/2 - r.y;
+ return r;
+}
+
+int
+det(Point2d a, Point2d b, Point2d c)
+{
+ /* TODO Better */
+ int d = 0;
+ int L = 3200;
+
+ d = MAX(-L, MIN(L, a.x)) * MAX(-L, MIN(L, b.y - c.y));
+ d += MAX(-L, MIN(L, a.y)) * MAX(-L, MIN(L, c.x - b.x));
+ d += MAX(-L, MIN(L, b.x)) * MAX(-L, MIN(L, c.y));
+ d -= MAX(-L, MIN(L, b.y)) * MAX(-L, MIN(L, c.x));
+ return a.x * (b.y - c.y) - a.y * (b.x - c.x) + b.x * c.y - b.y * c.x;
+}
+
+void
+draw_point2d(Point2d a, int d)
+{
+ SDL_Rect r;
+
+ if (a.x < 0 || a.x > w) return;
+ if (a.y < 0 || a.y > h) return;
+
+ r.x = a.x - d;
+ r.y = a.y - d;
+ r.w = 2 * d + 1;
+ r.h = 2 * d + 1;
+/* SDL_RenderDrawPoint(ren, a.x, a.y);*/
+ SDL_RenderFillRect(ren, &r);
+}
+
+float
+getdep(Point a, Point b, Point c, Point d)
+{
+ Point cp;
+ float r;
+ b.x -= a.x; c.x -= a.x;
+ b.y -= a.y; c.y -= a.y;
+ b.z -= a.z; c.z -= a.z;
+
+ b.z = -b.z;
+ a.z = -a.z;
+ c.z = -c.z;
+ d.z = -d.z;
+
+ cp.x = - ( - b.y * c.z + b.z * c.y );
+ cp.y = - ( - b.z * c.x + b.x * c.z );
+ cp.z = - ( - b.x * c.y + b.y * c.x );
+ r = cp.x * a.x + cp.y * a.y + cp.z * a.z;
+ r = r / (cp.x * d.x + cp.y * d.y + cp.z * d.z);
+
+ return r;
+}
+
+void
+draw_triangle(Point x, Point y, Point z)
+{
+ int i, j;
+ int mnx, mny, mxx, mxy;
+ float d;
+
+ Point2d a, b, c;
+ a = get_point(x);
+ b = get_point(y);
+ c = get_point(z);
+
+ if (det(a, b, c) >= 0) return;
+ mnx = MIN(a.x, MIN(b.x, c.x));
+ mxx = MAX(a.x, MAX(b.x, c.x));
+ mny = MIN(a.y, MIN(b.y, c.y));
+ mxy = MAX(a.y, MAX(b.y, c.y));
+
+ /* Fake depth :> */
+
+ for(i = MAX(mnx, 0); i <= MIN(mxx, w-1); ++i) {
+ for (j = MAX(mny, 0); j <= MIN(mxy, h-1); ++j) {
+ if (det(a, b, (Point2d){i, j}) <= 0 &&
+ det(b, c, (Point2d){i, j}) <= 0 &&
+ det(c, a, (Point2d){i, j}) <= 0) {
+ d = getdep(x, y, z, P(((float)w)/(2.0*hfov), h/2 - j, i - w/2));
+ if (d < pts_depth[j*w+i]) {
+ pts_queue[pts_queue_cnt++] = (SDL_Point){i, j};
+ pts_depth[j*w+i] = d;
+ }
+ }
+ }
+ }
+
+ SDL_RenderDrawPoints(ren, pts_queue, pts_queue_cnt);
+#ifdef TRIANGLELINES
+ SDL_SetRenderDrawColor(ren, 0xff, 0xff, 0xff, 0xff);
+ SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0xff);
+ SDL_RenderDrawLine(ren, a.x, a.y, b.x, b.y);
+ SDL_RenderDrawLine(ren, c.x, c.y, b.x, b.y);
+ SDL_RenderDrawLine(ren, a.x, a.y, c.x, c.y);
+#endif
+}
+
+void
+draw_triangle3d(Point a, Point b, Point c)
+{
+ int x, y, z;
+ int i, j;
+ pts_queue_cnt = 0;
+ Point2d m, n, o;
+ make_point_relative(&a);
+ make_point_relative(&b);
+ make_point_relative(&c);
+
+ if (a.x < 0 && b.x < 0 && c.x < 0) return;
+ if (a.x >= 0 && b.x >= 0 && c.x >= 0) return draw_triangle(a, b, c);
+ return;
+
+ x = (a.x >= 0) ? 1 : -1; m = get_point(a);
+ y = (b.x >= 0) ? 1 : -1; n = get_point(b);
+ z = (c.x >= 0) ? 1 : -1; o = get_point(c);
+
+ /* TODO: Better, not entire screen */
+ if (x * y * z * det(m,n,o) >= 0) return;
+
+ for(i = 0; i <= w; ++i) {
+ for (j = 0; j <= h; ++j) {
+ if ((x * y * det(m, n, (Point2d){i, j}) <= 0) &&
+ (z * y * det(n, o, (Point2d){i, j}) <= 0) &&
+ (z * x * det(o, m, (Point2d){i, j}) <= 0))
+ SDL_RenderDrawPoint(ren, i, j);
+ }
+ }
+}
+
+void
+add_triangle(Point a, Point b, Point c, unsigned int col)
+{
+ tgs[tgs_cnt].p[0] = a;
+ tgs[tgs_cnt].p[1] = b;
+ tgs[tgs_cnt].p[2] = c;
+ tgs[tgs_cnt].col = col;
+ tgs_cnt++;
+}
+
+int
+draw_init()
+{
+ /* TODO: error handling */
+ pts_queue = malloc(w * h * (sizeof *pts_queue));
+ pts_depth = malloc(w * h * (sizeof *pts_depth));
+
+ tgs_cnt = 0;
+ add_triangle((Point){3,16,2}, (Point){10,8,-5}, (Point){10,6,6}, 0xff0040ff);
+ add_triangle((Point){10,8,-5}, (Point){5,4,2}, (Point){10,6,6}, 0xff0040ff);
+ add_triangle((Point){10,0,-5}, (Point){5,0,2}, (Point){10,0,6}, shadowcol);
+
+ int u = 7;
+
+ return 0;
+}
+
+int
+draw_screen()
+{
+ int i;
+ for (i = 0; i < w*h; ++i) {
+ pts_depth[i] = 250000.0;
+ }
+ /* Background */
+ SDL_SetRenderDrawColor(ren, INTTOCOL(0x404040), 255);
+ SDL_RenderClear(ren);
+
+ /* SDL_SetRenderDrawColor(ren, 25, 25, 25, 255);
+ draw_triangle3d((Point){cam.pos.x-1.5,0,cam.pos.z-1.5}, (Point){cam.pos.x-1.5,0,cam.pos.z+1.5}, (Point){cam.pos.x+2.0,0,cam.pos.z}); */
+
+ for (i = 0; i < tgs_cnt; ++i) {
+ SDL_SetRenderDrawColor(ren, INTTOCOL((tgs[i].col)>>8), tgs[i].col%256);
+ draw_triangle3d(tgs[i].p[0], tgs[i].p[1], tgs[i].p[2]);
+ }
+
+ SDL_RenderPresent(ren);
+
+ return 0;
+}
diff --git a/draw.h b/draw.h
new file mode 100644
index 0000000..779f23e
--- /dev/null
+++ b/draw.h
@@ -0,0 +1,6 @@
+int draw_screen();
+int draw_init();
+void add_obj_interactive();
+void redo_obj();
+
+extern int w, h;
diff --git a/obj/car.obj b/obj/car.obj
new file mode 100644
index 0000000..97a8235
--- /dev/null
+++ b/obj/car.obj
@@ -0,0 +1,108 @@
+M 3.0
+
+v 0.2 0.6 1.1
+v 0 0.9 1.4
+v 0 1.4 1.4
+v 2 1.6 1.4
+v 6.8 0.7 1.1
+v 7.2 1.1 1.4
+v 7.2 1.6 1.4
+v 6.1 1.8 1.4
+v 0.2 0.6 -1.1
+v 0 0.9 -1.4
+v 0 1.4 -1.4
+v 2 1.6 -1.4
+v 6.8 0.7 -1.1
+v 7.2 1.1 -1.4
+v 7.2 1.6 -1.4
+v 6.1 1.8 -1.4
+v 3.0 2.5 1
+v 5.1 2.5 1
+v 3.0 2.5 -1
+v 5.1 2.5 -1
+v 2.1 1.8 1.4
+v 3.1 2.4 1
+v 3.7 2.4 1
+v 3.6 1.8 1.4
+
+# Front Lights 25-32
+v -0.01 0.95 0.95
+v -0.01 0.95 1.35
+v -0.01 1.35 1.35
+v -0.01 1.35 0.95
+v -0.01 0.95 -0.95
+v -0.01 0.95 -1.35
+v -0.01 1.35 -1.35
+v -0.01 1.35 -0.95
+
+# License Plate 33-
+v -0.01 0.95 -0.4
+v -0.01 0.95 0.4
+v -0.01 1.25 0.4
+v -0.01 1.25 -0.4
+v -0.02 1.00 -0.3
+v -0.02 1.00 0.3
+v -0.02 1.07 0.3
+v -0.02 1.07 -0.3
+v -0.02 1.13 -0.3
+v -0.02 1.13 0.3
+v -0.02 1.20 0.3
+v -0.02 1.20 -0.3
+
+
+# X Y Z
+# Left side
+F 2 1 6 0x424c6eff
+F 1 5 6 0x424c6eff
+F 2 6 7 0x657392ff
+F 2 7 3 0x657392ff
+F 3 7 8 0x657392ff
+F 3 8 4 0x657392ff
+F 4 8 18 0x0e071bff
+F 4 18 17 0x0e071bff
+
+# Right side
+F 10 14 9 0x424c6eff
+F 9 14 13 0x424c6eff
+F 10 15 14 0x657392ff
+F 10 11 15 0x657392ff
+F 11 16 15 0x657392ff
+F 11 12 16 0x657392ff
+F 12 20 16 0x0e071bff
+F 12 19 20 0x0e071bff
+
+# Front
+F 1 2 10 0x424c6eff
+F 1 10 9 0x424c6eff
+F 2 3 11 0x657392ff
+F 2 11 10 0x657392ff
+F 3 4 12 0x728199ff
+F 3 12 11 0x728199ff
+F 4 17 19 0x0e071bff
+F 4 19 12 0x0e071bff
+F 17 18 20 0x728199ff
+F 17 20 19 0x728199ff
+
+# Back
+F 6 5 13 0x424c6eff
+F 6 13 14 0x424c6eff
+F 7 6 14 0x657392ff
+F 7 14 15 0x657392ff
+F 8 7 15 0x728199ff
+F 8 15 16 0x728199ff
+F 8 16 20 0x0e071bff
+F 8 20 18 0x0e071bff
+
+# Front Lights
+F 25 26 27 0xf0c674ff
+F 25 27 28 0xf0c674ff
+F 29 31 30 0xf0c674ff
+F 29 32 31 0xf0c674ff
+
+# License Plate Front
+F 33 34 35 0xc5c8c6ff
+F 33 35 36 0xc5c8c6ff
+# F 37 38 39 0x1d1f21ff
+# F 37 39 40 0x1f1f21ff
+# F 41 42 43 0x1d1f21ff
+# F 41 43 44 0x1f1f21ff
diff --git a/obj/cube.obj b/obj/cube.obj
new file mode 100644
index 0000000..7faca9b
--- /dev/null
+++ b/obj/cube.obj
@@ -0,0 +1,25 @@
+v 0 0 0
+v 0 0 8
+v 0 8 0
+v 0 8 8
+v 8 0 0
+v 8 0 8
+v 8 8 0
+v 8 8 8
+F 1 4 3 0xd75f5fff
+F 1 2 4 0xd75f5fff
+
+F 4 2 8 0x87af5fff
+F 2 6 8 0x87af5fff
+
+F 5 7 8 0xffaf5fff
+F 6 5 8 0xffaf5fff
+
+F 1 3 7 0x87afd7ff
+F 1 7 5 0x87afd7ff
+
+F 1 6 2 0x69b2b2ff
+F 1 5 6 0x69b2b2ff
+
+F 4 8 3 0x8787afff
+F 3 8 7 0x8787afff
diff --git a/obj/smth.obj b/obj/smth.obj
new file mode 100644
index 0000000..9a12225
--- /dev/null
+++ b/obj/smth.obj
@@ -0,0 +1,22 @@
+v 0 0 0
+v 0 0 5
+v 0 4.33 2.5
+v 20 0 0
+v 20 0 5
+v 20 4.33 2.5
+F 1 2 3 0xd75f5f88
+F 1 3 2 0xd75f5f88
+F 6 4 5 0xd75f5f88
+F 6 5 4 0xd75f5f88
+F 1 2 4 0xd75f5f88
+F 1 4 2 0xd75f5f88
+F 2 5 4 0xd75f5f88
+F 2 4 5 0xd75f5f88
+F 2 5 6 0xd75f5f88
+F 2 6 5 0xd75f5f88
+F 3 2 6 0xd75f5f88
+F 3 6 2 0xd75f5f88
+F 3 1 6 0xd75f5f88
+F 3 6 1 0xd75f5f88
+F 4 1 6 0xd75f5f88
+F 4 6 1 0xd75f5f88
diff --git a/sim.c b/sim.c
new file mode 100644
index 0000000..638571d
--- /dev/null
+++ b/sim.c
@@ -0,0 +1,199 @@
+/* #include <stdio.h> */
+#include <math.h>
+#include <SDL2/SDL.h>
+
+#include "sim.h"
+#include "draw.h"
+#include "types.h"
+
+#define MOUSE_LOCK 1
+
+float hfov, vfov;
+float PI;
+Camera cam;
+uint fps = 30;
+
+SDL_Window *win;
+void *ren;
+
+typedef struct{
+ SDL_Keymod mod;
+ SDL_Keycode sym;
+ void (*func)(const Arg *);
+ const Arg arg;
+} Key;
+
+int
+main_init()
+{
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ fprintf(stderr, "%s:%d:main_init() error %s", __FILE__, __LINE__, SDL_GetError());
+ return 1;
+ }
+
+ win = SDL_CreateWindow("3D Sim",
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ 2*w, 2*h, SDL_WINDOW_RESIZABLE);
+ if (win == NULL) {
+ fprintf(stderr, "%s:%d:main_init() error %s", __FILE__, __LINE__, SDL_GetError());
+ return 1;
+ }
+
+ ren = SDL_CreateRenderer(win, -1, 0);
+ if (ren == NULL) {
+ fprintf(stderr, "%s:%d:main_init() error %s", __FILE__, __LINE__, SDL_GetError());
+ return 1;
+ }
+ SDL_RenderSetLogicalSize(ren, w, h);
+ /* SDL_RenderSetScale(ren, 2, 2); */
+
+ if (draw_init())
+ return 1;
+
+ return 0;
+}
+
+int
+main_quit()
+{
+ SDL_DestroyWindow(win);
+ SDL_Quit();
+ return 1;
+}
+
+int
+main_event()
+{
+ static SDL_Event event;
+ static uint inp = MOUSE_LOCK * 1024;
+ static double s = 0.5;
+ uint8 q;
+
+ while(SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ q = 1;
+ break;
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_q)
+ q = 1;
+ switch (event.key.keysym.sym) {
+ case SDLK_w: inp |= 1; break;
+ case SDLK_s: inp |= 2; break;
+ case SDLK_a: inp |= 4; break;
+ case SDLK_d: inp |= 8; break;
+ case SDLK_RIGHT: inp |= 16; break;
+ case SDLK_LEFT: inp |= 32; break;
+ case SDLK_UP: inp |= 64; break;
+ case SDLK_DOWN: inp |= 128; break;
+ case SDLK_j: inp |= 256; break;
+ case SDLK_k: inp |= 512; break;
+ case SDLK_m: inp ^= 1024; break;
+ case SDLK_i: add_obj_interactive(); break;
+ case SDLK_r: redo_obj(); break;
+ case SDLK_EQUALS: s += 0.1; break;
+ case SDLK_MINUS: s -= 0.1; break;
+ }
+ break;
+ case SDL_KEYUP:
+ switch (event.key.keysym.sym) {
+ case SDLK_w: inp &= (inp^1); break;
+ case SDLK_s: inp &= (inp^2); break;
+ case SDLK_a: inp &= (inp^4); break;
+ case SDLK_d: inp &= (inp^8); break;
+ case SDLK_RIGHT: inp &= (inp^16); break;
+ case SDLK_LEFT: inp &= (inp^32); break;
+ case SDLK_UP: inp &= (inp^64); break;
+ case SDLK_DOWN: inp &= (inp^128); break;
+ case SDLK_j: inp &= (inp^256); break;
+ case SDLK_k: inp &= (inp^512); break;
+ }
+ break;
+ case SDL_MOUSEMOTION:
+ if (~inp & 1024) break;
+ cam.azim -= ((float)event.motion.yrel)/25.0;
+ cam.rad += ((float)event.motion.xrel)/25.0;
+ break;
+ }
+ }
+
+ if (inp&1024)
+ SDL_SetRelativeMouseMode(SDL_TRUE);
+ else
+ SDL_SetRelativeMouseMode(SDL_FALSE);
+
+ if (inp&1) {
+ cam.pos.x += cos(cam.rad) * s;
+ cam.pos.z += sin(cam.rad) * s;
+ }
+ if (inp&2) {
+ cam.pos.x -= cos(cam.rad) * s;
+ cam.pos.z -= sin(cam.rad) * s;
+ }
+ if (inp&4) {
+ cam.pos.x += sin(cam.rad) * s;
+ cam.pos.z -= cos(cam.rad) * s;
+ }
+ if (inp&8) {
+ cam.pos.x -= sin(cam.rad) * s;
+ cam.pos.z += cos(cam.rad) * s;
+ }
+
+ if (inp&256) cam.pos.y -= s;
+ if (inp&512) cam.pos.y += s;
+ if (inp&16)
+ cam.rad += 0.05;
+ if (inp&32)
+ cam.rad -= 0.05;
+
+ if (inp&64)
+ cam.azim += 0.05;
+ if (inp&128)
+ cam.azim -= 0.05;
+
+ if (cam.azim < 0)
+ cam.azim += 2.0 * PI;
+ if (cam.azim > 2.0 * PI)
+ cam.azim -= 2.0 * PI;
+
+ if (cam.rad < 0)
+ cam.rad += 2.0 * PI;
+ if (cam.rad > 2.0 * PI)
+ cam.rad -= 2.0 * PI;
+
+ if (q)
+ return main_quit();
+
+ if (draw_screen())
+ return 1;
+
+ return 0;
+}
+
+int main()
+{
+ Uint32 ltick, fdif;
+ cam.pos.x = cam.pos.z = 0;
+ cam.pos.y = 10;
+ cam.rad = cam.azim = 0;
+ PI = 4.0 * atan(1);
+ h = 288;
+ w = 384;
+ hfov = 1;
+
+ if (main_init())
+ return 1;
+
+ vfov = 0.75;
+
+ fdif = 1000 / fps;
+ while (1) {
+ ltick = SDL_GetTicks();
+ if (main_event())
+ break;
+ ltick = SDL_GetTicks() - ltick;
+
+ if (ltick < fdif)
+ SDL_Delay(fdif - ltick);
+ }
+}
diff --git a/sim.h b/sim.h
new file mode 100644
index 0000000..b1a00e6
--- /dev/null
+++ b/sim.h
@@ -0,0 +1,25 @@
+typedef union {
+ int i;
+ unsigned int u;
+ float f;
+ const void *v;
+ const char *s;
+} Arg;
+
+typedef struct {
+ float x, y, z;
+} Point;
+
+typedef struct {
+ Point pos;
+ float azim, rad;
+} Camera;
+
+typedef struct {
+ Point p[3];
+ unsigned int col;
+} Triangle;
+
+extern Camera cam;
+extern float hfov, vfov;
+extern void *ren;
diff --git a/types.h b/types.h
new file mode 100644
index 0000000..ba72484
--- /dev/null
+++ b/types.h
@@ -0,0 +1,4 @@
+#define uint unsigned int
+#define uint8 unsigned char
+#define uint16 uint16_t
+#define uint32 unsigned int