starting a new 3d engine
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 30 Mar 2024 07:39:00 +0000 (09:39 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 30 Mar 2024 07:39:00 +0000 (09:39 +0200)
15 files changed:
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/cgmath2/cgmath2.h [new file with mode: 0644]
src/cgmath2/cgmvec3.inl [new file with mode: 0644]
src/gfx.h [new file with mode: 0644]
src/gl/gfx_gl.c [new file with mode: 0644]
src/gl/opengl.c [new file with mode: 0644]
src/gl/opengl.h [new file with mode: 0644]
src/nexus3d.c [new file with mode: 0644]
src/nexus3d.h [new file with mode: 0644]
src/nexus3d_impl.h [new file with mode: 0644]
src/wsys/wsys.c [new file with mode: 0644]
src/wsys/wsys.h [new file with mode: 0644]
src/wsys/wsys_fglut.c [new file with mode: 0644]
test.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..0497878
--- /dev/null
@@ -0,0 +1,7 @@
+*.o
+*.d
+*.swp
+*.a
+test
+compile_commands.json
+.cache/
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..27ec497
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,31 @@
+src = $(wildcard src/*.c) $(wildcard src/gl/*.c) $(wildcard src/wsys/*.c) \
+         $(wildcard src/unix/*.c)
+obj = $(src:.c=.o)
+dep = $(src:.c=.d)
+
+name = nexus3d
+liba = lib$(name).a
+
+warn = -pedantic -Wall
+dbg = -g
+#opt = -O3 -ffast-math
+inc = -Isrc
+
+CFLAGS = $(warn) $(dbg) $(opt) $(inc) $(def) -MMD
+LDFLAGS = -lGL -lglut -lm
+
+test: test.o $(liba)
+       $(CC) -o $@ test.o $(obj) $(liba) $(LDFLAGS)
+
+$(liba): $(obj)
+       $(AR) rcs $@ $(obj)
+
+-include $(dep)
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(liba) test test.o
+
+.PHONY: cleandep
+cleandep:
+       rm -f $(dep)
diff --git a/src/cgmath2/cgmath2.h b/src/cgmath2/cgmath2.h
new file mode 100644 (file)
index 0000000..0e34f38
--- /dev/null
@@ -0,0 +1,196 @@
+#ifndef NEXUS3D_CGMATH2_H_
+#define NEXUS3D_CGMATH2_H_
+
+#include <math.h>
+#include <string.h>
+
+#define CGM_PI 3.141592653589793
+
+typedef struct {
+       float x, y;
+} cgm_vec2;
+
+typedef struct {
+       float x, y, z;
+} cgm_vec3;
+
+typedef struct {
+       float x, y, z, w;
+} cgm_vec4, cgm_quat;
+
+typedef struct {
+       cgm_vec3 origin, dir;
+} cgm_ray;
+
+typedef enum cgm_euler_mode {
+       CGM_EULER_XYZ,
+       CGM_EULER_XZY,
+       CGM_EULER_YXZ,
+       CGM_EULER_YZX,
+       CGM_EULER_ZXY,
+       CGM_EULER_ZYX,
+       CGM_EULER_ZXZ,
+       CGM_EULER_ZYZ,
+       CGM_EULER_YXY,
+       CGM_EULER_YZY,
+       CGM_EULER_XYX,
+       CGM_EULER_XZX
+} cgm_euler_mode;
+
+#ifdef __cplusplus
+#define CGM_INLINE inline
+
+extern "C" {
+#else
+
+#if (__STDC_VERSION__ >= 199901) || defined(__GNUC__)
+#define CGM_INLINE inline
+#else
+#define CGM_INLINE __inline
+#endif
+
+#endif
+
+/* --- operations on cgm_vec3 --- */
+static CGM_INLINE cgm_vec3 cgm_vcons(float x, float y, float z);
+
+static CGM_INLINE cgm_vec3 cgm_vadd(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vsub(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vmul(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vscale(cgm_vec3 v, float s);
+
+static CGM_INLINE cgm_vec3 cgm_vmul_m4v3(const float *m, cgm_vec3 v);  /* m4x4 * v */
+static CGM_INLINE cgm_vec3 cgm_vmul_v3m4(cgm_vec3 v, const float *m);  /* v * m4x4 */
+static CGM_INLINE cgm_vec3 cgm_vmul_m3v3(const float *m, cgm_vec3 v);  /* m3x3 * v (m still 16 floats) */
+static CGM_INLINE cgm_vec3 cgm_vmul_v3m3(cgm_vec3 v, const float *m);  /* v * m3x3 (m still 16 floats) */
+
+static CGM_INLINE float cgm_vdot(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE cgm_vec3 cgm_vcross(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE float cgm_vlength(cgm_vec3 v);
+static CGM_INLINE float cgm_vlength_sq(cgm_vec3 v);
+static CGM_INLINE float cgm_vdist(cgm_vec3 a, cgm_vec3 b);
+static CGM_INLINE float cgm_vdist_sq(cgm_vec3 a, cgm_vec3 b);
+
+static CGM_INLINE cgm_vec3 cgm_normalize(cgm_vec3 v);
+
+static CGM_INLINE cgm_vec3 cgm_vreflect(cgm_vec3 v, cgm_vec3 n);
+static CGM_INLINE cgm_vec3 cgm_vrefract(cgm_vec3 v, cgm_vec3 n, float ior);
+
+static CGM_INLINE cgm_vec3 cgm_vrotate_quat(cgm_vec3 v, cgm_quat q);
+static CGM_INLINE cgm_vec3 cgm_vrotate_axis(cgm_vec3 v, int axis, float angle);
+static CGM_INLINE cgm_vec3 cgm_vrotate(cgm_vec3 v, float angle, float x, float y, float z);
+static CGM_INLINE cgm_vec3 cgm_vrotate_euler(cgm_vec3 v, float a, float b, float c, enum cgm_euler_mode mode);
+
+static CGM_INLINE cgm_vec3 cgm_vlerp(cgm_vec3 a, cgm_vec3 b, float t);
+static CGM_INLINE cgm_vec3 cgm_vblend(cgm_vec3 a, float fa, cgm_vec3 b, float fb);
+
+#define cgm_velem(v, idx)      ((&(v).x)[idx])
+
+/* --- operations on matrices --- */
+static CGM_INLINE void cgm_mcopy(float *dest, const float *src);
+static CGM_INLINE void cgm_mzero(float *m);
+static CGM_INLINE void cgm_midentity(float *m);
+
+static CGM_INLINE void cgm_mmul(float *a, const float *b);
+static CGM_INLINE void cgm_mpremul(float *a, const float *b);
+
+static CGM_INLINE void cgm_msubmatrix(float *m, int row, int col);
+static CGM_INLINE void cgm_mupper3(float *m);
+static CGM_INLINE float cgm_msubdet(const float *m, int row, int col);
+static CGM_INLINE float cgm_mcofactor(const float *m, int row, int col);
+static CGM_INLINE float cgm_mdet(const float *m);
+static CGM_INLINE void cgm_mtranspose(float *m);
+static CGM_INLINE void cgm_mcofmatrix(float *m);
+static CGM_INLINE int cgm_minverse(float *m);  /* returns 0 on success, -1 for singular */
+
+static CGM_INLINE void cgm_mtranslation(float *m, float x, float y, float z);
+static CGM_INLINE void cgm_mscaling(float *m, float sx, float sy, float sz);
+static CGM_INLINE void cgm_mrotation_x(float *m, float angle);
+static CGM_INLINE void cgm_mrotation_y(float *m, float angle);
+static CGM_INLINE void cgm_mrotation_z(float *m, float angle);
+static CGM_INLINE void cgm_mrotation_axis(float *m, int idx, float angle);
+static CGM_INLINE void cgm_mrotation(float *m, float angle, float x, float y, float z);
+static CGM_INLINE void cgm_mrotation_euler(float *m, float a, float b, float c, int mode);
+static CGM_INLINE void cgm_mrotation_quat(float *m, cgm_quat q);
+
+static CGM_INLINE void cgm_mtranslate(float *m, float x, float y, float z);
+static CGM_INLINE void cgm_mscale(float *m, float sx, float sy, float sz);
+static CGM_INLINE void cgm_mrotate_x(float *m, float angle);
+static CGM_INLINE void cgm_mrotate_y(float *m, float angle);
+static CGM_INLINE void cgm_mrotate_z(float *m, float angle);
+static CGM_INLINE void cgm_mrotate_axis(float *m, int idx, float angle);
+static CGM_INLINE void cgm_mrotate(float *m, float angle, float x, float y, float z);
+static CGM_INLINE void cgm_mrotate_euler(float *m, float a, float b, float c, int mode);
+static CGM_INLINE void cgm_mrotate_quat(float *m, cgm_quat q);
+
+static CGM_INLINE void cgm_mpretranslate(float *m, float x, float y, float z);
+static CGM_INLINE void cgm_mprescale(float *m, float sx, float sy, float sz);
+static CGM_INLINE void cgm_mprerotate_x(float *m, float angle);
+static CGM_INLINE void cgm_mprerotate_y(float *m, float angle);
+static CGM_INLINE void cgm_mprerotate_z(float *m, float angle);
+static CGM_INLINE void cgm_mprerotate_axis(float *m, int idx, float angle);
+static CGM_INLINE void cgm_mprerotate(float *m, float angle, float x, float y, float z);
+static CGM_INLINE void cgm_mprerotate_euler(float *m, float a, float b, float c, int mode);
+static CGM_INLINE void cgm_mprerotate_quat(float *m, cgm_quat q);
+
+static CGM_INLINE cgm_vec3 cgm_mget_translation(const float *m);
+static CGM_INLINE cgm_quat cgm_mget_rotation(const float *m);
+static CGM_INLINE cgm_vec3 cgm_mget_scaling(const float *m);
+static CGM_INLINE cgm_vec4 cgm_mget_frustum_plane(const float *m, int p);
+
+static CGM_INLINE cgm_vec4 cgm_normalize_plane(cgm_vec4 p);
+
+static CGM_INLINE void cgm_mlookat(float *m, cgm_vec3 pos, cgm_vec3 targ, cgm_vec3 up);
+static CGM_INLINE void cgm_minv_lookat(float *m, cgm_vec3 pos, cgm_vec3 targ, cgm_vec3 up);
+static CGM_INLINE void cgm_mortho(float *m, float left, float right, float bot, float top,
+               float znear, float zfar);
+static CGM_INLINE void cgm_mfrustum(float *m, float left, float right, float bot, float top,
+               float znear, float zfar);
+static CGM_INLINE void cgm_mperspective(float *m, float vfov, float aspect, float znear, float zfar);
+
+static CGM_INLINE void cgm_mmirror(float *m, float a, float b, float c, float d);
+
+/* --- miscellaneous utility functions --- */
+static CGM_INLINE float cgm_deg_to_rad(float deg);
+static CGM_INLINE float cgm_rad_to_deg(float rad);
+
+static CGM_INLINE float cgm_smoothstep(float a, float b, float x);
+static CGM_INLINE float cgm_lerp(float a, float b, float t);
+static CGM_INLINE float cgm_logerp(float a, float b, float t);
+static CGM_INLINE float cgm_bezier(float a, float b, float c, float d, float t);
+static CGM_INLINE float cgm_bspline(float a, float b, float c, float d, float t);
+static CGM_INLINE float cgm_spline(float a, float b, float c, float d, float t);
+
+static CGM_INLINE cgm_vec3 cgm_discrand(float rad);
+static CGM_INLINE cgm_vec3 cgm_sphrand(float rad);
+
+static CGM_INLINE cgm_vec3 cgm_unproject(cgm_vec3 norm_scrpos, const float *inv_viewproj);
+static CGM_INLINE void cgm_glu_unproject(float winx, float winy, float winz,
+               const float *view, const float *proj, const int *vp,
+               float *objx, float *objy, float *objz);
+
+static CGM_INLINE cgm_ray cgm_pick_ray(float nx, float ny, const float *viewmat,
+               const float *projmat);
+
+static CGM_INLINE cgm_vec3 cgm_raypos(cgm_ray ray, float t);
+
+/* calculate barycentric coordinates of point pt in triangle (a, b, c) */
+static CGM_INLINE cgm_vec3 cgm_bary(cgm_vec3 a, cgm_vec3 b, cgm_vec3 c, cgm_vec3 pt);
+
+/* convert between unit vectors and spherical coordinates */
+static CGM_INLINE cgm_vec3 cgm_uvec_to_sph(cgm_vec3 v);
+static CGM_INLINE cgm_vec3 cgm_sph_to_uvec(float theta, float phi);
+
+#include "cgmvec3.inl"
+/*#include "cgmvec4.inl"
+#include "cgmquat.inl"*/
+#include "cgmmat.inl"
+/*#include "cgmray.inl"*/
+#include "cgmmisc.inl"
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NEXUS3D_CGMATH2_H_ */
diff --git a/src/cgmath2/cgmvec3.inl b/src/cgmath2/cgmvec3.inl
new file mode 100644 (file)
index 0000000..d6a50f2
--- /dev/null
@@ -0,0 +1,197 @@
+static CGM_INLINE cgm_vec3 cgm_vcons(float x, float y, float z)
+{
+       cgm_vec3 v;
+       v.x = x;
+       v.y = y;
+       v.z = z;
+       return v;
+}
+
+static CGM_INLINE cgm_vec3 cgm_vadd(cgm_vec3 a, cgm_vec3 b)
+{
+       return cgm_vcons(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vsub(cgm_vec3 a, cgm_vec3 b)
+{
+       return cgm_vcons(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vmul(cgm_vec3 a, cgm_vec3 b)
+{
+       return cgm_vcons(a.x * b.x, a.y * b.y, a.z * b.z);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vscale(cgm_vec3 v, float s)
+{
+       return cgm_vcons(a.x * s, a.y * s, a.z * s);
+}
+
+
+static CGM_INLINE cgm_vec3 cgm_vmul_m4v3(const float *m, cgm_vec3 v)
+{
+       cgm_vec3 res;
+       res.x = v.x * m[0] + v.y * m[4] + v.z * m[8] + m[12];
+       res.y = v.x * m[1] + v.y * m[5] + v.z * m[9] + m[13];
+       res.z = v.x * m[2] + v.y * m[6] + v.z * m[10] + m[14];
+       return res;
+}
+
+static CGM_INLINE cgm_vec3 cgm_vmul_v3m4(cgm_vec3 v, const float *m)
+{
+       cgm_vec3 res;
+       res.x = v.x * m[0] + v.y * m[1] + v.z * m[2] + m[3];
+       res.y = v.x * m[4] + v.y * m[5] + v.z * m[6] + m[7];
+       res.z = v.x * m[8] + v.y * m[9] + v.z * m[10] + m[11];
+       return res;
+}
+
+static CGM_INLINE cgm_vec3 cgm_vmul_m3v3(const float *m, cgm_vec3 v)
+{
+       cgm_vec3 res;
+       res.x = v.x * m[0] + v.y * m[4] + v.z * m[8];
+       res.y = v.x * m[1] + v.y * m[5] + v.z * m[9];
+       res.z = v.x * m[2] + v.y * m[6] + v.z * m[10];
+       return res;
+}
+
+static CGM_INLINE cgm_vec3 cgm_vmul_v3m3(cgm_vec3 v, const float *m)
+{
+       cgm_vec3 res;
+       res.x = v.x * m[0] + v.y * m[1] + v.z * m[2];
+       res.y = v.x * m[4] + v.y * m[5] + v.z * m[6];
+       res.z = v.x * m[8] + v.y * m[9] + v.z * m[10];
+       return res;
+}
+
+
+static CGM_INLINE float cgm_vdot(cgm_vec3 a, cgm_vec3 b)
+{
+       return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+static CGM_INLINE cgm_vec3 cgm_vcross(cgm_vec3 a, cgm_vec3 b)
+{
+       cgm_vec3 res;
+       res.x = a.y * b.z - a.z * b.y;
+       res.y = a.z * b.x - a.x * b.z;
+       res.z = a.x * b.y - a.y * b.x;
+       return res;
+}
+
+static CGM_INLINE float cgm_vlength(cgm_vec3 v)
+{
+       return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+}
+
+static CGM_INLINE float cgm_vlength_sq(cgm_vec3 v)
+{
+       return v.x * v.x + v.y * v.y + v.z * v.z;
+}
+
+static CGM_INLINE float cgm_vdist(cgm_vec3 a, cgm_vec3 b)
+{
+       float dx = a.x - b.x;
+       float dy = a.y - b.y;
+       float dz = a.z - b.z;
+       return sqrt(dx * dx + dy * dy + dz * dz);
+}
+
+static CGM_INLINE float cgm_vdist_sq(cgm_vec3 a, cgm_vec3 b)
+{
+       float dx = a.x - b.x;
+       float dy = a.y - b.y;
+       float dz = a.z - b.z;
+       return dx * dx + dy * dy + dz * dz;
+}
+
+
+static CGM_INLINE cgm_vec3 cgm_normalize(cgm_vec3 v)
+{
+       cgm_vec3 res;
+       float len = cgm_vlength(v);
+       if(len != 0.0f) {
+               float s = 1.0f / len;
+               res.x = v.x * s;
+               res.y = v.y * s;
+               res.z = v.z * s;
+       } else {
+               res = v;
+       }
+       return res;
+}
+
+
+static CGM_INLINE cgm_vec3 cgm_vreflect(cgm_vec3 v, cgm_vec3 n)
+{
+       float ndotv2 = cgm_vdot(v, n) * 2.0f;
+       return cgm_vcons(v.x - n.x * ndotv2, v.y - n.y * ndotv2, v.z - n.z * ndotv2);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vrefract(cgm_vec3 v, cgm_vec3 n, float ior)
+{
+       float ndotv = cgm_vdot(v, n);
+       float k = 1.0f - ior * ior * (1.0f - ndotv * ndotv);
+       if(k < 0.0f) {
+               return cgm_vreflect(v, n);      /* TIR */
+       } else {
+               cgm_vec3 res;
+               float sqrt_k = sqrt(k);
+               res.x = ior * v.x - (ior * ndotv + sqrt_k) * n.x;
+               res.y = ior * v.y - (ior * ndotv + sqrt_k) * n.y;
+               res.z = ior * v.z - (ior * ndotv + sqrt_k) * n.z;
+               return res;
+       }
+}
+
+
+static CGM_INLINE cgm_vec3 cgm_vrotate_quat(cgm_vec3 v, cgm_quat q)
+{
+       cgm_quat vq, inv_q, tmp_q;
+
+       vq = cgm_qcons(v->x, v->y, v->z, 0.0f);
+       inv_q = cgm_qinvert(q);
+       tmp_q = cgm_qmul(q, vq);
+       tmp_q = cgm_qmul(tmp_q, inv_q);
+       return cgm_vcons(tmp_q.x, tmp_q.y, tmp_q.z);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vrotate_axis(cgm_vec3 v, int axis, float angle)
+{
+       float m[16];
+       cgm_mrotation_axis(m, axis, angle);
+       cgm_vmul_m3v3(v, m);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vrotate(cgm_vec3 v, float angle, float x, float y, float z)
+{
+       float m[16];
+       cgm_mrotation(m, angle, x, y, z);
+       cgm_vmul_m3v3(v, m);
+}
+
+static CGM_INLINE cgm_vec3 cgm_vrotate_euler(cgm_vec3 v, float a, float b, float c, enum cgm_euler_mode mode)
+{
+       float m[16];
+       cgm_mrotation_euler(m, a, b, c, mode);
+       cgm_vmul_m3v3(v, m);
+}
+
+
+static CGM_INLINE cgm_vec3 cgm_vlerp(cgm_vec3 a, cgm_vec3 b, float t)
+{
+       cgm_vec3 res;
+       res.x = a.x + (b.x - a.x) * t;
+       res.y = a.y + (b.y - a.y) * t;
+       res.z = a.z + (b.z - a.z) * t;
+       return res;
+}
+
+static CGM_INLINE cgm_vec3 cgm_vblend(cgm_vec3 a, float fa, cgm_vec3 b, float fb)
+{
+       cgm_vec3 res;
+       res.x = a.x * fa + b.x * fb;
+       res.y = a.y * fa + b.y * fb;
+       res.z = a.z * fa + b.z * fb;
+       return res;
+}
diff --git a/src/gfx.h b/src/gfx.h
new file mode 100644 (file)
index 0000000..beac8c1
--- /dev/null
+++ b/src/gfx.h
@@ -0,0 +1,7 @@
+#ifndef NEXUS3D_GFX_H_
+#define NEXUS3D_GFX_H_
+
+void nex_clear(void);
+void nex_viewport(int x, int y, int w, int h);
+
+#endif /* NEXUS3D_GFX_H_ */
diff --git a/src/gl/gfx_gl.c b/src/gl/gfx_gl.c
new file mode 100644 (file)
index 0000000..4156368
--- /dev/null
@@ -0,0 +1,12 @@
+#include "opengl.h"
+#include "nexus3d_impl.h"
+
+void nex_clear(void)
+{
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+}
+
+void nex_viewport(int x, int y, int w, int h)
+{
+       glViewport(x, y, w, h);
+}
diff --git a/src/gl/opengl.c b/src/gl/opengl.c
new file mode 100644 (file)
index 0000000..ca7fb6b
--- /dev/null
@@ -0,0 +1,6 @@
+#include "opengl.h"
+
+int init_gl(void)
+{
+       return 0;
+}
diff --git a/src/gl/opengl.h b/src/gl/opengl.h
new file mode 100644 (file)
index 0000000..4723efc
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef NEXUS3D_OPENGL_H_
+#define NEXUS3D_OPENGL_H_
+
+#include <GL/gl.h>
+
+int init_gl(void);
+
+#endif /* NEXUS3D_OPENGL_H_ */
diff --git a/src/nexus3d.c b/src/nexus3d.c
new file mode 100644 (file)
index 0000000..a4e8f1e
--- /dev/null
@@ -0,0 +1,13 @@
+#include "nexus3d_impl.h"
+
+union nex_gfxapi nex_apicfg = {{NEX_OPENGL, 3, 3, 0}};
+enum nex_gfxflags nex_gfxflags;
+
+
+void nex_gfxapi_opengl(int vmaj, int vmin, enum nex_apiflags_gl flags)
+{
+       nex_apicfg.api = NEX_OPENGL;
+       nex_apicfg.gl.ver_major = vmaj;
+       nex_apicfg.gl.ver_minor = vmin;
+       nex_apicfg.gl.flags = flags;
+}
diff --git a/src/nexus3d.h b/src/nexus3d.h
new file mode 100644 (file)
index 0000000..1de3560
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef NEXUS3D_H_
+#define NEXUS3D_H_
+
+#include "gfx.h"
+#include "wsys/wsys.h"
+/*#include "cgmath2/cgmath2.h"*/
+
+enum nex_apiflags_gl {
+       NEX_OPENGL_COMPAT       = 1,
+       NEX_OPENGL_DEBUG        = 2
+};
+
+void nex_gfxapi_opengl(int vmaj, int vmin, enum nex_apiflags_gl flags);
+
+#endif /* NEXUS3D_H_ */
diff --git a/src/nexus3d_impl.h b/src/nexus3d_impl.h
new file mode 100644 (file)
index 0000000..288badc
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef NEXUS3D_IMPL_H_
+#define NEXUS3D_IMPL_H_
+
+#include "nexus3d.h"
+
+struct nex_callbacks {
+       nex_cbdisplay_type display;
+       nex_cbreshape_type reshape;
+       nex_cbkey_type key;
+       nex_cbmousebn_type mousebn;
+       nex_cbmousemove_type mousemove;
+
+       void *display_cls, *reshape_cls, *key_cls, *mousebn_cls, *mousemove_cls;
+};
+
+enum nex_gfxapi_type { NEX_OPENGL };
+
+struct nex_gfxapi_opengl {
+       enum nex_gfxapi_type api;
+       int ver_major, ver_minor;
+       enum nex_apiflags_gl flags;
+};
+
+union nex_gfxapi {
+       struct nex_gfxapi_opengl gl;
+       enum nex_gfxapi_type api;
+};
+
+extern struct nex_callbacks nex_cb;                    /* defined in wsys/wsys.c */
+extern union nex_gfxapi nex_apicfg;                    /* defined in nexus3d.c */
+extern enum nex_gfxflags nex_gfxflags;         /* defined in nexus3d.c */
+
+#endif /* NEXUS3D_IMPL_H_ */
diff --git a/src/wsys/wsys.c b/src/wsys/wsys.c
new file mode 100644 (file)
index 0000000..f5c1f77
--- /dev/null
@@ -0,0 +1,34 @@
+#include "nexus3d_impl.h"
+
+struct nex_callbacks nex_cb;
+
+void nex_cbdisplay(nex_cbdisplay_type func, void *cls)
+{
+       nex_cb.display = func;
+       nex_cb.display_cls = cls;
+}
+
+void nex_cbreshape(nex_cbreshape_type func, void *cls)
+{
+       nex_cb.reshape = func;
+       nex_cb.reshape_cls = cls;
+}
+
+void nex_cbkey(nex_cbkey_type func, void *cls)
+{
+       nex_cb.key = func;
+       nex_cb.key_cls = cls;
+}
+
+void nex_cbmousebn(nex_cbmousebn_type func, void *cls)
+{
+       nex_cb.mousebn = func;
+       nex_cb.mousebn_cls = cls;
+}
+
+void nex_cbmousemove(nex_cbmousemove_type func, void *cls)
+{
+       nex_cb.mousemove = func;
+       nex_cb.mousemove_cls = cls;
+}
+
diff --git a/src/wsys/wsys.h b/src/wsys/wsys.h
new file mode 100644 (file)
index 0000000..6a5fa05
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef NEXUS3D_WSYS_H_
+#define NEXUS3D_WSYS_H_
+
+enum nex_key {
+       NEX_KEY_ESC             = 27,
+       NEX_KEY_DEL             = 127,
+       NEX_KEY_HOME    = 0xff50,
+       NEX_KEY_LEFT    = 0xff51,
+       NEX_KEY_UP              = 0xff52,
+       NEX_KEY_RIGHT   = 0xff53,
+       NEX_KEY_DOWN    = 0xff54,
+       NEX_KEY_PGUP    = 0xff55,
+       NEX_KEY_PGDOWN  = 0xff56,
+       NEX_KEY_END             = 0xff57,
+       NEX_KEY_INS             = 0xff63,
+       NEX_KEY_F1              = 0xffbe,
+       NEX_KEY_F2              = 0xffbf,
+       NEX_KEY_F3              = 0xffc0,
+       NEX_KEY_F4              = 0xffc1,
+       NEX_KEY_F5              = 0xffc2,
+       NEX_KEY_F6              = 0xffc3,
+       NEX_KEY_F7              = 0xffc4,
+       NEX_KEY_F8              = 0xffc5,
+       NEX_KEY_F9              = 0xffc6,
+       NEX_KEY_F10             = 0xffc7,
+       NEX_KEY_F11             = 0xffc8,
+       NEX_KEY_F12             = 0xffc9
+};
+
+enum nex_gfxflags {
+       NEX_GFX_STENCIL = 1,
+       NEX_GFX_FSAA    = 2,
+       NEX_GFX_STEREO  = 4,
+       NEX_GFX_DEBUG   = 0x100
+};
+
+/* callback function types */
+typedef void (*nex_cbdisplay_type)(void *cls);
+typedef void (*nex_cbreshape_type)(int x, int y, void *cls);
+typedef void (*nex_cbkey_type)(int key, int pressed, void *cls);
+typedef void (*nex_cbmousebn_type)(int bn, int pressed, int x, int y, void *cls);
+typedef void (*nex_cbmousemove_type)(int x, int y, void *cls);
+
+int nex_initgfx(int xsz, int ysz, enum nex_gfxflags flags);
+void nex_closegfx(void);
+
+int nex_evloop_wait(void);
+int nex_evloop_poll(void);
+
+void nex_swap_buffers(void);
+void nex_redisplay(void);
+
+/* callback registration */
+void nex_cbdisplay(nex_cbdisplay_type func, void *cls);
+void nex_cbreshape(nex_cbreshape_type func, void *cls);
+void nex_cbkey(nex_cbkey_type func, void *cls);
+void nex_cbmousebn(nex_cbmousebn_type func, void *cls);
+void nex_cbmousemove(nex_cbmousemove_type func, void *cls);
+
+#endif /* NEXUS3D_WSYS_H_ */
diff --git a/src/wsys/wsys_fglut.c b/src/wsys/wsys_fglut.c
new file mode 100644 (file)
index 0000000..8194813
--- /dev/null
@@ -0,0 +1,209 @@
+#include <GL/freeglut.h>
+#include "nexus3d_impl.h"
+#include "gl/opengl.h"
+
+static void winclose(void);
+static void display(void);
+static void idle(void);
+static void reshape(int x, int y);
+static void keydown(unsigned char key, int x, int y);
+static void keyup(unsigned char key, int x, int y);
+static void skeydown(int key, int x, int y);
+static void skeyup(int key, int x, int y);
+static void mouse(int bn, int st, int x, int y);
+static void motion(int x, int y);
+
+static int quit, have_idle;
+
+
+int nex_initgfx(int xsz, int ysz, enum nex_gfxflags flags)
+{
+       static char *fake_argv[] = {"nexus3d", 0};
+       static int fake_argc = 1;
+       unsigned int glut_flags;
+
+       if(flags & NEX_GFX_DEBUG) {
+               nex_apicfg.gl.flags |= NEX_OPENGL_DEBUG;
+       }
+
+       glut_flags = GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_SRGB;
+       if(flags & NEX_GFX_STENCIL) {
+               glut_flags |= GLUT_STENCIL;
+       }
+       if(flags & NEX_GFX_FSAA) {
+               glut_flags |= GLUT_MULTISAMPLE;
+       }
+       if(flags & NEX_GFX_STEREO) {
+               glut_flags |= GLUT_STEREO;
+       }
+
+       glutInit(&fake_argc, fake_argv);
+       glutInitWindowSize(xsz, ysz);
+       glutInitDisplayMode(glut_flags);
+
+       if(nex_apicfg.gl.flags & NEX_OPENGL_DEBUG) {
+               glutInitContextFlags(GLUT_DEBUG);
+       }
+       if(nex_apicfg.gl.ver_major > 1) {
+               glutInitContextVersion(3, 3);
+               if(nex_apicfg.gl.flags & NEX_OPENGL_COMPAT) {
+                       glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
+               } else {
+                       glutInitContextProfile(GLUT_CORE_PROFILE);
+               }
+       }
+
+       glutCreateWindow("nexus3d engine");
+
+       glutCloseFunc(winclose);
+       glutDisplayFunc(display);
+       glutReshapeFunc(reshape);
+       glutKeyboardFunc(keydown);
+       glutKeyboardUpFunc(keyup);
+       glutSpecialFunc(skeydown);
+       glutSpecialUpFunc(skeyup);
+       glutMouseFunc(mouse);
+       glutMotionFunc(motion);
+
+       nex_gfxflags = flags;
+       quit = 0;
+       have_idle = 0;
+
+       if(init_gl() == -1) {
+               return -1;
+       }
+       return 0;
+}
+
+void nex_closegfx(void)
+{
+}
+
+int nex_evloop_wait(void)
+{
+       if(have_idle) {
+               glutIdleFunc(0);
+               have_idle = 0;
+       }
+
+       glutMainLoopEvent();
+       return quit ? 0 : 1;
+}
+
+int nex_evloop_poll(void)
+{
+       if(!have_idle) {
+               glutIdleFunc(idle);
+               have_idle = 1;
+       }
+
+       glutMainLoopEvent();
+       return quit ? 0 : 1;
+}
+
+void nex_swap_buffers(void)
+{
+       glutSwapBuffers();
+}
+
+void nex_redisplay(void)
+{
+       glutPostRedisplay();
+}
+
+static void winclose(void)
+{
+       quit = 1;
+}
+
+static void display(void)
+{
+       if(nex_cb.display) {
+               nex_cb.display(nex_cb.display_cls);
+       }
+}
+
+static void idle(void)
+{
+       glutPostRedisplay();
+}
+
+static void reshape(int x, int y)
+{
+       if(nex_cb.reshape) {
+               nex_cb.reshape(x, y, nex_cb.reshape_cls);
+       }
+}
+
+static void keydown(unsigned char key, int x, int y)
+{
+       if(nex_cb.key) {
+               nex_cb.key(key, 1, nex_cb.key_cls);
+       }
+}
+
+static void keyup(unsigned char key, int x, int y)
+{
+       if(nex_cb.key) {
+               nex_cb.key(key, 0, nex_cb.key_cls);
+       }
+}
+
+static int translate_skey(int key)
+{
+       switch(key) {
+       case GLUT_KEY_LEFT:
+               return NEX_KEY_LEFT;
+       case GLUT_KEY_UP:
+               return NEX_KEY_UP;
+       case GLUT_KEY_RIGHT:
+               return NEX_KEY_RIGHT;
+       case GLUT_KEY_DOWN:
+               return NEX_KEY_DOWN;
+       case GLUT_KEY_PAGE_UP:
+               return NEX_KEY_PGUP;
+       case GLUT_KEY_PAGE_DOWN:
+               return NEX_KEY_PGDOWN;
+       case GLUT_KEY_HOME:
+               return NEX_KEY_HOME;
+       case GLUT_KEY_END:
+               return NEX_KEY_END;
+       case GLUT_KEY_INSERT:
+               return NEX_KEY_INS;
+       default:
+               if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
+                       return NEX_KEY_F1 + (key - GLUT_KEY_F1);
+               }
+       }
+       return -1;
+}
+
+static void skeydown(int key, int x, int y)
+{
+       if(nex_cb.key && (key = translate_skey(key)) > 0) {
+               nex_cb.key(key, 1, nex_cb.key_cls);
+       }
+}
+
+static void skeyup(int key, int x, int y)
+{
+       if(nex_cb.key && (key = translate_skey(key)) > 0) {
+               nex_cb.key(key, 0, nex_cb.key_cls);
+       }
+}
+
+static void mouse(int bn, int st, int x, int y)
+{
+       if(nex_cb.mousebn) {
+               int idx = bn - GLUT_LEFT_BUTTON;
+               int press = bn == GLUT_DOWN;
+               nex_cb.mousebn(idx, press, x, y, nex_cb.mousebn_cls);
+       }
+}
+
+static void motion(int x, int y)
+{
+       if(nex_cb.mousemove) {
+               nex_cb.mousemove(x, y, nex_cb.mousemove_cls);
+       }
+}
diff --git a/test.c b/test.c
new file mode 100644 (file)
index 0000000..e38d66f
--- /dev/null
+++ b/test.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include "nexus3d.h"
+
+
+static void display(void *cls);
+static void reshape(int x, int y, void *cls);
+static void keyb(int key, int pressed, void *cls);
+static void mbutton(int bn, int pressed, int x, int y, void *cls);
+static void mmove(int x, int y, void *cls);
+
+
+static int quit;
+
+int main(void)
+{
+       nex_gfxapi_opengl(3, 3, NEX_OPENGL_DEBUG);
+       if(nex_initgfx(1280, 800, 0) == -1) {
+               return 1;
+       }
+
+       nex_cbdisplay(display, 0);
+       nex_cbreshape(reshape, 0);
+       nex_cbkey(keyb, 0);
+       nex_cbmousebn(mbutton, 0);
+       nex_cbmousemove(mmove, 0);
+
+       while(nex_evloop_wait() && !quit);
+
+       nex_closegfx();
+       return 0;
+}
+
+
+static void display(void *cls)
+{
+       nex_clear();
+
+       nex_swap_buffers();
+}
+
+static void reshape(int x, int y, void *cls)
+{
+       nex_viewport(0, 0, x, y);
+}
+
+static void keyb(int key, int pressed, void *cls)
+{
+       if(!pressed) return;
+
+       switch(key) {
+       case 27:
+               quit = 1;
+               break;
+       }
+}
+
+static void mbutton(int bn, int pressed, int x, int y, void *cls)
+{
+}
+
+static void mmove(int x, int y, void *cls)
+{
+}