More build massage
[dormin.git] / skin.c
blob678746186a65e6d4a35b28718e8ef3f9ca3db05c
1 #define GL_GLEXT_PROTOTYPES
2 #ifdef _WIN32
3 #define WIN32_LEAN_AND_MEAN
4 #include <windows.h>
5 #endif
6 #ifdef __APPLE__
7 #include <OpenGL/gl.h>
8 #else
9 #include <GL/gl.h>
10 #endif
12 #ifndef GL_VERSION_1_5
13 #define GL_ARRAY_BUFFER 0x8892
14 #define GL_DYNAMIC_DRAW 0x88E8
15 #define GL_STATIC_DRAW 0x88E4
16 #define GL_WRITE_ONLY 0x88B9
17 #ifndef APIENTRYP
18 #define APIENTRYP APIENTRY *
19 #endif
20 typedef ptrdiff_t GLintptr;
21 typedef ptrdiff_t GLsizeiptr;
22 typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
23 typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
24 typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
25 typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
26 typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
27 static PFNGLBINDBUFFERPROC glBindBuffer;
28 static PFNGLGENBUFFERSPROC glGenBuffers;
29 static PFNGLBUFFERDATAPROC glBufferData;
30 static PFNGLMAPBUFFERPROC glMapBuffer;
31 static PFNGLUNMAPBUFFERPROC glUnmapBuffer;
32 #define GETPA(name) for (;;) { \
33 *(PROC *) &gl##name = wglGetProcAddress ("gl" # name); \
34 if (!gl##name) { \
35 fprintf (stderr, "could not get address of gl"#name"\n"); \
36 exit (EXIT_FAILURE); \
37 } \
38 break; \
40 #endif
42 #include <math.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
47 #include <caml/fail.h>
48 #include <caml/alloc.h>
49 #include <caml/memory.h>
51 #include "vec.c"
53 enum {V_IDX, N_IDX, UV_IDX, C_IDX, COUNT};
55 struct skin {
56 int boneindices[3];
57 float weights[3];
58 int num_bones;
61 struct bone {
62 int parent;
63 float v[3];
64 float q[4];
66 float mv[3];
67 float mq[4];
69 float aq[4];
70 float amq[4];
71 float amv[3];
73 float am[12];
74 float im[12];
77 typedef struct {
78 int num_bones;
79 int num_vertices;
80 GLuint bufid[COUNT];
81 float *ptrs[COUNT];
82 struct skin *skin;
83 struct bone *bones;
84 } State;
86 static State glob_state;
88 static void skin_init (State *s, value vertexa_v, value normala_v,
89 value uva_v, value skin_v, value colors_v)
91 int i;
92 GLsizei size;
93 float *p;
94 struct skin *skin;
95 s->num_vertices = Wosize_val (vertexa_v) / (Double_wosize * 3);
97 glGenBuffers (COUNT, s->bufid);
99 size = s->num_vertices * sizeof (GLfloat) * 3;
100 p = s->ptrs[V_IDX] = stat_alloc (size);
101 for (i = 0; i < s->num_vertices * 3; ++i) {
102 p[i] = Double_field (vertexa_v, i);
104 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
105 glBufferData (GL_ARRAY_BUFFER, size, p, GL_DYNAMIC_DRAW);
107 p = s->ptrs[N_IDX] = stat_alloc (size);
108 for (i = 0; i < s->num_vertices * 3; ++i) {
109 p[i] = Double_field (normala_v, i);
111 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
112 glBufferData (GL_ARRAY_BUFFER, size, p, GL_DYNAMIC_DRAW);
114 size = s->num_vertices * sizeof (GLfloat) * 2;
115 p = s->ptrs[UV_IDX] = stat_alloc (size);
116 for (i = 0; i < s->num_vertices * 2; ++i) {
117 p[i] = Double_field (uva_v, i);
119 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[UV_IDX]);
120 glBufferData (GL_ARRAY_BUFFER, size, p, GL_STATIC_DRAW);
121 stat_free (p);
123 size = s->num_vertices * 4;
124 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[C_IDX]);
125 glBufferData (GL_ARRAY_BUFFER, size, String_val (colors_v), GL_STATIC_DRAW);
127 s->skin = skin = stat_alloc (s->num_vertices * sizeof (struct skin));
128 for (i = 0; i < s->num_vertices; ++i) {
129 int j;
130 value v;
132 v = Field (skin_v, i);
133 skin[i].num_bones = Int_val (Field (v, 3));
135 for (j = 0; j < skin[i].num_bones; ++j) {
136 double val;
138 val = Double_val (Bp_val (Field (v, j)));
139 skin[i].boneindices[j] = (int) val;
140 skin[i].weights[j] = val - skin[i].boneindices[j];
141 skin[i].boneindices[j] += 1;
146 CAMLprim value ml_skin_draw_begin (value unit_v)
148 State *s = &glob_state;
150 (void) unit_v;
151 glEnableClientState (GL_VERTEX_ARRAY);
152 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
153 glVertexPointer (3, GL_FLOAT, 0, NULL);
155 glEnableClientState (GL_NORMAL_ARRAY);
156 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
157 glNormalPointer (GL_FLOAT, 0, NULL);
159 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
160 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[UV_IDX]);
161 glTexCoordPointer (2, GL_FLOAT, 0, NULL);
163 glEnableClientState (GL_COLOR_ARRAY);
164 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[C_IDX]);
165 glColorPointer (4, GL_UNSIGNED_BYTE, 0, NULL);
167 return Val_unit;
170 CAMLprim value ml_skin_draw_end (value unit_v)
172 (void) unit_v;
173 glDisableClientState (GL_VERTEX_ARRAY);
174 glDisableClientState (GL_NORMAL_ARRAY);
175 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
176 glDisableClientState (GL_COLOR_ARRAY);
177 glBindBuffer (GL_ARRAY_BUFFER, 0);
179 #if 0
180 glDisable (GL_TEXTURE_2D);
181 glDisable (GL_LIGHTING);
182 glColor3f (1.0, 0.0, 0.0);
183 glDisable (GL_DEPTH_TEST);
184 glLineWidth (4.0);
186 glBegin (GL_LINES);
188 int i;
189 State *s = &glob_state;
190 struct bone *b = s->bones + 1;
192 for (i = 0; i < s->num_bones; ++i, ++b) {
193 struct bone *p = &s->bones[b->parent];
195 glVertex3fv (p->amv);
196 glVertex3fv (b->amv);
199 glEnd ();
200 #endif
201 return Val_unit;
204 CAMLprim value ml_skin_init (value geom_v)
206 CAMLparam1 (geom_v);
207 CAMLlocal5 (vertexa_v, normala_v, uva_v, skin_v, colors_v);
208 State *s = &glob_state;
210 #ifdef _WIN32
211 GETPA (BindBuffer);
212 GETPA (GenBuffers);
213 GETPA (BufferData);
214 GETPA (MapBuffer);
215 GETPA (UnmapBuffer);
216 #endif
217 vertexa_v = Field (geom_v, 0);
218 normala_v = Field (geom_v, 1);
219 uva_v = Field (geom_v, 2);
220 skin_v = Field (geom_v, 3);
221 colors_v = Field (geom_v, 4);
223 skin_init (s, vertexa_v, normala_v, uva_v, skin_v, colors_v);
224 CAMLreturn (Val_unit);
227 static void translate (State *s, float *dst)
229 int i, j;
230 struct bone *b;
231 float *curvert = s->ptrs[V_IDX];
232 struct skin *skin = s->skin;
234 for (i = 0; i < s->num_vertices; ++i, curvert += 3, dst += 3, ++skin)
236 float v[3] = {0,0,0}, v0[3], v1[3], v2[3], w, m[12];
238 for (j = 0; j < skin->num_bones; ++j) {
239 w = skin->weights[j] + 0.000011;
240 b = &s->bones[skin->boneindices[j]];
242 vsub (v0, curvert, b->mv);
243 mapply_to_vector (v1, b->im, v0);
245 mscale (m, b->am, w);
246 mapply_to_point (v2, m, v1);
248 vaddto (v, v2);
250 vcopy (dst, v);
255 CAMLprim value ml_skin_set_skel (value skel_v)
257 int i;
258 size_t size;
259 struct bone *b;
260 CAMLparam1 (skel_v);
261 CAMLlocal2 (v, floats_v);
262 State *s = &glob_state;
264 s->num_bones = Wosize_val (skel_v);
265 size = (s->num_bones + 1) * sizeof (struct bone);
266 s->bones = b = stat_alloc (size);
268 memset (b, 0, size);
269 b->parent = -1;
270 b->q[3] = 1.0;
271 b->mq[3] = 1.0;
272 b->aq[3] = 1.0;
273 b->amq[3] = 1.0;
274 b++;
276 for (i = 0; i < s->num_bones; ++i, ++b) {
277 v = Field (skel_v, i);
278 floats_v = Field (v, 1);
280 b->parent = Int_val (Field (v, 0)) + 1;
282 b->v[0] = Double_field (floats_v, 1);
283 b->v[1] = Double_field (floats_v, 2);
284 b->v[2] = Double_field (floats_v, 3);
286 b->q[0] = Double_field (floats_v, 5);
287 b->q[1] = Double_field (floats_v, 6);
288 b->q[2] = Double_field (floats_v, 7);
289 b->q[3] = Double_field (floats_v, 8);
292 b = s->bones + 1;
293 for (i = 0; i < s->num_bones; ++i, ++b) {
294 float v[3], q[4], q1[4], z[3] = {0,0,0};
295 struct bone *parent = &s->bones[b->parent];
297 qapply (v, parent->mq, b->v);
298 qcompose (b->mq, b->q, parent->mq);
299 vadd (b->mv, v, parent->mv);
301 qconjugate (q, b->mq);
302 qscale (q1, q, 1.0 / qmagnitude (q));
303 q2matrix (b->im, q1, z);
306 CAMLreturn (Val_unit);
309 CAMLprim value ml_skin_set_anim (value anim_v)
311 int i;
312 CAMLparam1 (anim_v);
313 CAMLlocal1 (floats_v);
314 State *s = &glob_state;
315 struct bone *b = s->bones + 1;
317 for (i = 0; i < s->num_bones; ++i, ++b) {
318 floats_v = Field (anim_v, i);
319 b->aq[0] = Double_field (floats_v, 0);
320 b->aq[1] = Double_field (floats_v, 1);
321 b->aq[2] = Double_field (floats_v, 2);
322 b->aq[3] = Double_field (floats_v, 3);
325 b = s->bones + 1;
326 for (i = 0; i < s->num_bones; ++i, ++b) {
327 float v[3];
328 struct bone *parent = &s->bones[b->parent];
330 qapply (v, parent->amq, b->v);
331 qcompose (b->amq, b->aq, parent->amq);
332 vadd (b->amv, v, parent->amv);
334 q2matrix (b->am, b->amq, b->amv);
337 CAMLreturn (Val_unit);
340 CAMLprim value ml_skin_anim (value unit_v)
342 GLboolean ret;
343 CAMLparam1 (unit_v);
344 float *vdst, *vsrc, *ndst, *nsrc;
345 State *s = &glob_state;
347 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
348 vdst = glMapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
349 if (!vdst) {
350 fprintf (stderr, "glMapBuffer for vertices failed\n");
351 exit (EXIT_FAILURE);
354 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
355 ndst = glMapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
356 if (!ndst) {
357 fprintf (stderr, "glMapBuffer for normals failed\n");
358 exit (EXIT_FAILURE);
361 vsrc = s->ptrs[V_IDX];
362 nsrc = s->ptrs[N_IDX];
364 translate (s, vdst);
365 #if 0
367 int i;
368 for (i = 0; i < s->num_vertices; ++i) {
369 struct skin *skin;
370 struct bone *bone, *parent;
371 float v[3], v1[3], *v2;
372 float q[4];
374 skin = &s->skin[i];
375 bone = &s->bones[skin->boneindices[0]];
376 parent = &s->bones[bone->parent];
378 vdst += 3;
379 vsrc += 3;
381 *ndst++ = *nsrc++;
382 *ndst++ = *nsrc++;
383 *ndst++ = *nsrc++;
386 #endif
388 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
389 ret = glUnmapBuffer (GL_ARRAY_BUFFER);
390 if (ret == GL_FALSE) {
391 fprintf (stderr, "glUnmapBuffer for vertices failed\n");
392 exit (EXIT_FAILURE);
395 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
396 ret = glUnmapBuffer (GL_ARRAY_BUFFER);
397 if (ret == GL_FALSE) {
398 fprintf (stderr, "glUnmapBuffer for normals failed\n");
399 exit (EXIT_FAILURE);
402 CAMLreturn (Val_unit);