aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile3
-rw-r--r--cube.fmdbin0 -> 948 bytes
-rw-r--r--faqe.c96
-rw-r--r--fmd.c113
-rw-r--r--fmd.h32
-rw-r--r--gl.h7
-rw-r--r--glfunc.h3
-rw-r--r--ieee754.c39
-rw-r--r--ieee754.h6
-rw-r--r--model.c60
-rw-r--r--model.h30
-rw-r--r--test_ieee754.c38
-rw-r--r--vert.glsl9
-rw-r--r--vertex.h16
15 files changed, 404 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore
index ad9f5de..dbb5cfe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
*.o
faqe
+test_ieee754
*.exe
*.dll
diff --git a/Makefile b/Makefile
index 004053e..5ceed54 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBS)) -std=c11 -MMD -MP
LDFLAGS += -Wl,--as-needed
LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBS)) -lm
-OBJ := faqe.o gl.o eprintf.o glprog.o
+OBJ := faqe.o eprintf.o fmd.o gl.o glprog.o ieee754.o model.o
all: $(PROG)
@@ -24,6 +24,7 @@ include $(EPRINTF_PATH)/module.mk
include $(LINMATH_PATH)/module.mk
$(PROG): $(OBJ)
+test_ieee754: ieee754.o
faqe.o: assets.h
deplinks: $(EPRINTF_FILES) $(LINMATH_FILES)
diff --git a/cube.fmd b/cube.fmd
new file mode 100644
index 0000000..6177d5d
--- /dev/null
+++ b/cube.fmd
Binary files differ
diff --git a/faqe.c b/faqe.c
index ddcff69..bc5bd2f 100644
--- a/faqe.c
+++ b/faqe.c
@@ -11,33 +11,37 @@
#include "glprog.h"
#include "linmath.h"
#include "nelem.h"
+#include "model.h"
enum {
WIDTH = 800,
HEIGHT = 600,
};
+# define PI 3.14159265358979323846
+#define FOV (PI * 0.5)
+
+void viewport(GLuint proj, int width, int height)
+{
+ mat4x4 pers;
+ gl_viewport(0, 0, width, height);
+ mat4x4_perspective(pers, FOV, (float)width / (float)height, 0.1, 100);
+ gl_uni_setm4fv(proj, 1, GL_FALSE, pers[0]);
+}
+
int main(int argc, char **argv)
{
bool running = true;
SDL_Window *win;
SDL_GLContext *glc;
- GLuint ebo, vbo, vao, prog;
- GLint ucolor;
- struct vertex {
- vec3 pos;
- vec3 col;
- vec2 uv;
- } verts[] = {
- {{ 0.5, 0.5, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 1.0 }},
- {{ 0.5, -0.5, 0.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 0.0 }},
- {{ -0.5, -0.5, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0 }},
- {{ -0.5, 0.5, 0.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 1.0 }},
- };
- GLuint idxs[] = {
- 0, 1, 3,
- 1, 2, 3,
- };
+ GLuint prog;
+ struct {
+ GLint model, view, proj;
+ } uni;
+ mat4x4 view;
+ FILE *cube_file;
+ struct fmd cube_fmd;
+ struct model cube_model;
setprogname(argc >= 1 && argv[0] != NULL ? argv[0] : "faqe");
@@ -62,37 +66,37 @@ int main(int argc, char **argv)
gl_load((gl_loadfunc *)SDL_GL_GetProcAddress);
- gl_viewport(0, 0, WIDTH, HEIGHT);
-
- gl_buf_gen(1, &vbo);
- gl_buf_gen(1, &ebo);
- gl_va_gen(1, &vao);
-
- gl_va_bind(vao);
-
- gl_buf_bind(GL_ARRAY_BUFFER, vbo);
- gl_buf_data(GL_ARRAY_BUFFER, sizeof verts, verts, GL_STATIC_DRAW);
-
- gl_buf_bind(GL_ELEMENT_ARRAY_BUFFER, ebo);
- gl_buf_data(GL_ELEMENT_ARRAY_BUFFER, sizeof idxs, idxs, GL_STATIC_DRAW);
-
- gl_va_define(0, NELEM(verts[0].pos), GL_FLOAT, GL_FALSE, sizeof *verts, (void *)offsetof(struct vertex, pos));
- gl_va_enable(0);
- gl_va_define(1, NELEM(verts[0].col), GL_FLOAT, GL_FALSE, sizeof *verts, (void *)offsetof(struct vertex, col));
- gl_va_enable(1);
- gl_va_define(2, NELEM(verts[0].uv), GL_FLOAT, GL_FALSE, sizeof *verts, (void *)offsetof(struct vertex, uv));
- gl_va_enable(2);
+ cube_file = fopen("cube.fmd", "rb");
+ if (cube_file == NULL)
+ eprintf("Could not open 'cube.fmd':");
+ fmd_load(&cube_fmd, cube_file);
+ model_load(&cube_model, &cube_fmd);
+ fmd_free(&cube_fmd);
+ fclose(cube_file);
prog = glprog_load(2, (struct shdrdat []){
{ GL_VERTEX_SHADER, vert_glsl.data, vert_glsl.size },
{ GL_FRAGMENT_SHADER, frag_glsl.data, frag_glsl.size },
},
- 1, &(struct unidat){ "ucolor", &ucolor });
+ 3, (struct unidat []){
+ { "model", &uni.model },
+ { "view", &uni.view },
+ { "proj", &uni.proj },
+ });
- gl_poly_mode(GL_FRONT_AND_BACK, GL_LINE);
+ viewport(uni.proj, WIDTH, HEIGHT);
+
+ gl_enable(GL_DEPTH_TEST);
while (running) {
+ mat4x4 model;
SDL_Event ev;
+ float secs;
+
+ secs = SDL_GetTicks() * 0.0001;
+
+ mat4x4_look_at(view, (vec3){ 0, 0, 3 }, (vec3){ 0, 0, 0 }, (vec3){ 0, 1, 0 });
+ gl_uni_setm4fv(uni.view, 1, GL_FALSE, view[0]);
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
@@ -108,19 +112,23 @@ int main(int argc, char **argv)
case SDL_WINDOWEVENT:
switch (ev.window.event) {
case SDL_WINDOWEVENT_SIZE_CHANGED:
- gl_viewport(0, 0,
- ev.window.data1,
- ev.window.data2);
+ viewport(uni.proj,
+ ev.window.data1,
+ ev.window.data2);
}
break;
}
}
gl_clearcolor(0.2, 0.3, 0.3, 1.0);
- gl_clear(GL_COLOR_BUFFER_BIT);
+ gl_clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl_prog_use(prog);
- gl_va_bind(vao);
- gl_draw_elems(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
+ mat4x4_identity(model);
+ mat4x4_rotate_X(model, model, secs * 3);
+ mat4x4_rotate_Y(model, model, secs * 2);
+ mat4x4_rotate_Z(model, model, secs * 4);
+ gl_uni_setm4fv(uni.model, 1, GL_TRUE, model[0]);
+ model_render(&cube_model);
gl_va_bind(0);
SDL_GL_SwapWindow(win);
diff --git a/fmd.c b/fmd.c
new file mode 100644
index 0000000..4d71f0d
--- /dev/null
+++ b/fmd.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eprintf.h"
+#include "fmd.h"
+#include "ieee754.h"
+#include "nelem.h"
+
+static const char *MAGIC = "FMD001\r\n";
+
+static void checkmagic(FILE *f)
+{
+ for (size_t i = 0; i < strlen(MAGIC); i++)
+ assert(fgetc(f) == MAGIC[i]);
+}
+
+static inline unsigned long betoul(FILE *src)
+{
+ unsigned long ret = 0;
+
+ assert(src != NULL);
+
+ for (int i = 0; i < 4; i++) {
+ int c = fgetc(src);
+ assert(c != EOF);
+ ret += (unsigned long)(c & 0xff) << (3 - i) * 8;
+ }
+
+ return ret;
+}
+
+void readfloats(float *dest, int count, FILE *src)
+{
+ assert(dest != NULL);
+ assert(src != NULL);
+
+ for (int i = 0; i < count; i++)
+ dest[i] = ieee754f(betoul(src));
+}
+
+void fmd_load(struct fmd *fmd, FILE *f)
+{
+ assert(fmd != NULL);
+ assert(f != NULL);
+
+ checkmagic(f);
+
+ fmd->nverts = betoul(f);
+ if (fmd->nverts > 0)
+ fmd->verts = emalloc(fmd->nverts * sizeof *fmd->verts);
+ else
+ fmd->verts = NULL;
+ for (int i = 0; i < fmd->nverts; i++) {
+ struct vertex *v = &fmd->verts[i];
+ readfloats(v->pos, 3, f);
+ readfloats(v->norm, 3, f);
+ readfloats(v->uv, 2, f);
+ }
+ fmd->ntris = betoul(f);
+ if (fmd->ntris > 0)
+ fmd->tris = emalloc(fmd->ntris * sizeof *fmd->tris);
+ else
+ fmd->tris = NULL;
+ for (int i = 0; i < fmd->ntris; i++)
+ for (size_t j = 0; j < NELEM(fmd->tris[j]); j++)
+ fmd->tris[i][j] = betoul(f);
+
+ fmd->nmtls = betoul(f);
+ if (fmd->nmtls > 0)
+ fmd->mtls = emalloc(fmd->nmtls * sizeof *fmd->mtls);
+ else
+ fmd->mtls = NULL;
+ for (int i = 0; i < fmd->nmtls; i++) {
+ unsigned long len = betoul(f);
+ char **m = &fmd->mtls[i];
+ size_t ret;
+
+ *m = emalloc(len + 1);
+
+ ret = fread(*m, len, 1, f);
+ assert(ret == 1);
+ *m[len] = '\0';
+ }
+
+ fmd->nmeshes = betoul(f);
+ if (fmd->nmeshes > 0)
+ fmd->meshes = emalloc(fmd->nmeshes * sizeof *fmd->meshes);
+ else
+ fmd->meshes = NULL;
+ for (int i = 0; i < fmd->nmeshes; i++) {
+ struct fmd_mesh *m = &fmd->meshes[i];
+ m->midx = betoul(f);
+ m->tidx = betoul(f);
+ m->tcnt = betoul(f);
+ }
+}
+
+void fmd_free(struct fmd *fmd)
+{
+ assert(fmd);
+
+ free(fmd->verts);
+ free(fmd->tris);
+ for (int i = 0; i < fmd->nmtls; i++)
+ free(fmd->mtls[i]);
+ free(fmd->mtls);
+ free(fmd->meshes);
+}
diff --git a/fmd.h b/fmd.h
new file mode 100644
index 0000000..af562f9
--- /dev/null
+++ b/fmd.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef FMD_H
+#define FMD_H
+
+#include <stdio.h>
+
+#include "gl.h"
+#include "vertex.h"
+
+typedef GLuint tri[3];
+struct fmd {
+ int nverts;
+ struct vertex *verts;
+ int ntris;
+ tri *tris;
+ int nmtls;
+ char **mtls;
+ int nmeshes;
+ struct fmd_mesh {
+ int midx;
+ int tidx;
+ int tcnt;
+ } *meshes;
+};
+
+void fmd_load(struct fmd *fmd, FILE *f);
+void fmd_free(struct fmd *fmd);
+
+#endif // FMD_H
diff --git a/gl.h b/gl.h
index 30e7862..112fc82 100644
--- a/gl.h
+++ b/gl.h
@@ -32,6 +32,11 @@ typedef double GLdouble;
typedef double GLclampd;
enum {
+ GL_DEPTH_BUFFER_BIT = 0x100,
+ GL_COLOR_BUFFER_BIT = 0x4000,
+};
+
+enum {
GL_NO_ERROR = 0,
GL_FALSE = 0,
GL_TRUE = 1,
@@ -45,10 +50,10 @@ enum {
GL_OUT_OF_MEMORY = 0x0505,
GL_INVALID_FRAMEBUFFER_OPERATION = 0x0506,
GL_CONTEXT_LOST = 0x0507,
+ GL_DEPTH_TEST = 0x0b71,
GL_UNSIGNED_INT = 0x1405,
GL_FLOAT = 0x1406,
GL_LINE = 0x1B01,
- GL_COLOR_BUFFER_BIT = 0x4000,
GL_ARRAY_BUFFER = 0x8892,
GL_ELEMENT_ARRAY_BUFFER = 0x8893,
GL_STREAM_DRAW = 0x88e0,
diff --git a/glfunc.h b/glfunc.h
index 8b5776b..6722567 100644
--- a/glfunc.h
+++ b/glfunc.h
@@ -43,3 +43,6 @@ GL_FUNC(glUniform3fv, void, gl_uni_set3fv, GLint location, GLsizei count, const
GL_FUNC(glUniform4fv, void, gl_uni_set4fv, GLint location, GLsizei count, const GLfloat *value)
GL_FUNC(glUniformMatrix3fv, void, gl_uni_setm3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
GL_FUNC(glUniformMatrix4fv, void, gl_uni_setm4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_FUNC(glGetIntegerv, void, gl_geti, GLenum pname, GLint *data)
+GL_FUNC(glEnable, void, gl_enable, GLenum cap)
+GL_FUNC(glDisable, void, gl_disable, GLenum cap)
diff --git a/ieee754.c b/ieee754.c
new file mode 100644
index 0000000..3b21351
--- /dev/null
+++ b/ieee754.c
@@ -0,0 +1,39 @@
+#include <assert.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "ieee754.h"
+
+// ieee754f: convert f32 to float
+float ieee754f(unsigned long b)
+{
+ bool isneg;
+ int exp;
+ float n;
+
+ isneg = (b >> 31) & 0x1;
+ exp = (b >> 23) & 0xff;
+ n = b & 0x7fffff;
+
+ if (exp == 0xff) {
+ if (n) {
+ /* TODO: work out what a negative NaN means */
+ assert(!isneg);
+ return NAN;
+ } else {
+ return isneg ? -INFINITY : INFINITY;
+ }
+ } else if (exp == 0) {
+ if (n == 0)
+ return isneg ? -0 : 0;
+ exp = -126;
+ } else {
+ n += 0x1p23f;
+ exp -= 127;
+ }
+
+ n = ldexpf(n, exp - 23);
+
+ return isneg ? -n : n;
+}
diff --git a/ieee754.h b/ieee754.h
new file mode 100644
index 0000000..58f886d
--- /dev/null
+++ b/ieee754.h
@@ -0,0 +1,6 @@
+#ifndef IEEE754_H
+#define IEEE754_H
+
+float ieee754f(unsigned long l);
+
+#endif // IEEE754_H
diff --git a/model.c b/model.c
new file mode 100644
index 0000000..7a6a256
--- /dev/null
+++ b/model.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#include <assert.h>
+
+#include "eprintf.h"
+#include "linmath.h"
+#include "model.h"
+#include "nelem.h"
+#include "vertex.h"
+
+void model_load(struct model *mdl, const struct fmd *fmd)
+{
+ GLuint vbo, ebo;
+ struct vertex *v;
+
+ assert(mdl != NULL);
+ assert(fmd != NULL);
+
+ gl_va_gen(1, &mdl->vao);
+ gl_va_bind(mdl->vao);
+
+ gl_buf_gen(1, &vbo);
+ gl_buf_bind(GL_ARRAY_BUFFER, vbo);
+ gl_buf_data(GL_ARRAY_BUFFER, fmd->nverts * sizeof *fmd->verts, fmd->verts, GL_STATIC_DRAW);
+
+ gl_buf_gen(1, &ebo);
+ gl_buf_bind(GL_ELEMENT_ARRAY_BUFFER, ebo);
+ gl_buf_data(GL_ELEMENT_ARRAY_BUFFER, fmd->ntris * sizeof *fmd->tris, fmd->tris, GL_STATIC_DRAW);
+
+ v = &fmd->verts[0];
+ gl_va_define(0, NELEM(v->pos), GL_FLOAT, GL_FALSE, sizeof *v, (void *)offsetof(struct vertex, pos));
+ gl_va_enable(0);
+ gl_va_define(1, NELEM(v->norm), GL_FLOAT, GL_FALSE, sizeof *v, (void *)offsetof(struct vertex, norm));
+ gl_va_enable(1);
+ gl_va_define(2, NELEM(v->uv), GL_FLOAT, GL_FALSE, sizeof *v, (void *)offsetof(struct vertex, uv));
+ gl_va_enable(2);
+
+ // TODO: materials, use a shared material set
+
+ mdl->nmeshes = fmd->nmeshes;
+ mdl->meshes = emalloc(mdl->nmeshes * sizeof *mdl->meshes);
+ for (int i = 0; i < fmd->nmeshes; i++) {
+ struct mesh *m = &mdl->meshes[i];
+ struct fmd_mesh *fm = &fmd->meshes[i];
+ m->mtl = NULL;
+ m->elems.idx = fm->tidx * NELEM(*fmd->tris);
+ m->elems.cnt = fm->tcnt * NELEM(*fmd->tris);
+ }
+}
+
+void model_render(struct model *mdl)
+{
+ gl_va_bind(mdl->vao);
+ for (int i = 0; i < mdl->nmeshes; i++) {
+ struct mesh *m = &mdl->meshes[i];
+ gl_draw_elems(GL_TRIANGLES, m->elems.cnt, GL_UNSIGNED_INT, &((GLuint *)NULL)[m->elems.idx]);
+ }
+}
diff --git a/model.h b/model.h
new file mode 100644
index 0000000..33db3b4
--- /dev/null
+++ b/model.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef MODEL_H
+#define MODEL_H
+
+#include "gl.h"
+#include "fmd.h"
+
+struct mesh {
+ struct material {
+ GLuint diffuse;
+ } *mtl;
+ struct {
+ GLuint idx;
+ GLuint cnt;
+ } elems;
+};
+
+struct model {
+ struct mesh *meshes;
+ int nmeshes;
+ GLuint vao;
+};
+
+void model_load(struct model *mdl, const struct fmd *fmd);
+void model_render(struct model *mdl);
+
+#endif // MODEL_H
diff --git a/test_ieee754.c b/test_ieee754.c
new file mode 100644
index 0000000..44873c9
--- /dev/null
+++ b/test_ieee754.c
@@ -0,0 +1,38 @@
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ieee754.h"
+
+static unsigned long naiive(float n)
+{
+ union {
+ float f;
+ uint32_t u;
+ } u = { .f = n };
+
+ return u.u;
+}
+
+void test(float a)
+{
+ float b = ieee754f(naiive(a));
+
+ if (!((isnan(a) && isnan(b)) || a == b)) {
+ fprintf(stderr, "%lu: %.40f != %.40f\n", naiive(a), a, b);
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(void)
+{
+ test(NAN);
+ test(+INFINITY);
+ test(-INFINITY);
+ test(0x1p127f);
+ test(0x7fffffp-149f);
+
+ for (float n = -0.000000001; n <= 1; n = nextafterf(n, 2))
+ test(n);
+}
diff --git a/vert.glsl b/vert.glsl
index 2ee78d0..d33cc47 100644
--- a/vert.glsl
+++ b/vert.glsl
@@ -2,13 +2,16 @@
// SPDX-License-Identifier: MIT
#version 330 core
layout (location = 0) in vec3 pos;
-layout (location = 1) in vec3 color;
+layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 uv;
out vec3 vcolor;
+uniform mat4 model;
+uniform mat4 view;
+uniform mat4 proj;
void main()
{
- gl_Position = vec4(pos, 1.0);
- vcolor = color;
+ gl_Position = proj * view * model * vec4(pos, 1.0);
+ vcolor = normal;
}
diff --git a/vertex.h b/vertex.h
new file mode 100644
index 0000000..7f58ee9
--- /dev/null
+++ b/vertex.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com>
+ * SPDX-License-Identifier: MIT
+ */
+#ifndef VERTEX_H
+#define VERTEX_H
+
+#include "linmath.h"
+
+struct vertex {
+ vec3 pos;
+ vec3 norm;
+ vec2 uv;
+};
+
+#endif // VERTEX_H