Initial
[dormin.git] / skin.c
blobc162c538c93a1b64a59b2a170c9ffdceb8d65cf1
1 #define GL_GLEXT_PROTOTYPES
2 #ifdef _WIN32
3 #define WIN32_LEAN_AND_MEAN
4 #include <windows.h>
5 #endif
6 #include <GL/gl.h>
8 #ifndef GL_VERSION_1_5
9 #define GL_ARRAY_BUFFER 0x8892
10 #define GL_DYNAMIC_DRAW 0x88E8
11 #define GL_STATIC_DRAW 0x88E4
12 #define GL_WRITE_ONLY 0x88B9
13 #ifndef APIENTRYP
14 #define APIENTRYP APIENTRY *
15 typedef ptrdiff_t GLintptr;
16 typedef ptrdiff_t GLsizeiptr;
17 #endif
18 typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
19 typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
20 typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
21 typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
22 typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
23 static PFNGLBINDBUFFERPROC glBindBuffer;
24 static PFNGLGENBUFFERSPROC glGenBuffers;
25 static PFNGLBUFFERDATAPROC glBufferData;
26 static PFNGLMAPBUFFERPROC glMapBuffer;
27 static PFNGLUNMAPBUFFERPROC glUnmapBuffer;
28 #endif
30 #include <math.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #include <caml/fail.h>
36 #include <caml/alloc.h>
37 #include <caml/memory.h>
39 #include "vec.c"
41 enum {V_IDX, N_IDX, UV_IDX, COUNT};
43 struct skin {
44 int boneindices[3];
45 float weights[3];
46 int num_bones;
49 struct bone {
50 int parent;
51 float v[3];
52 float q[4];
54 float mv[3];
55 float mq[4];
57 float aq[4];
58 float amq[4];
59 float amv[3];
61 float am[12];
62 float im[12];
65 typedef struct {
66 int num_bones;
67 int num_vertices;
68 int bufid[COUNT];
69 float *ptrs[COUNT];
70 struct skin *skin;
71 struct bone *bones;
72 } State;
74 static State glob_state;
76 static void skin_init (State *s, value vertexa_v, value normala_v,
77 value uva_v, value skin_v)
79 int i;
80 GLsizei size;
81 float *p;
82 struct skin *skin;
83 s->num_vertices = Wosize_val (vertexa_v) / (Double_wosize * 3);
85 glGenBuffers (COUNT, s->bufid);
87 size = s->num_vertices * sizeof (GLfloat) * 3;
88 p = s->ptrs[V_IDX] = stat_alloc (size);
89 for (i = 0; i < s->num_vertices * 3; ++i) {
90 p[i] = Double_field (vertexa_v, i);
92 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
93 glBufferData (GL_ARRAY_BUFFER, size, p, GL_DYNAMIC_DRAW);
95 p = s->ptrs[N_IDX] = stat_alloc (size);
96 for (i = 0; i < s->num_vertices * 3; ++i) {
97 p[i] = Double_field (normala_v, i);
99 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
100 glBufferData (GL_ARRAY_BUFFER, size, p, GL_DYNAMIC_DRAW);
102 size = s->num_vertices * sizeof (GLfloat) * 2;
103 p = s->ptrs[UV_IDX] = stat_alloc (size);
104 for (i = 0; i < s->num_vertices * 2; ++i) {
105 p[i] = Double_field (uva_v, i);
107 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[UV_IDX]);
108 glBufferData (GL_ARRAY_BUFFER, size, p, GL_STATIC_DRAW);
109 stat_free (p);
111 s->skin = skin = stat_alloc (s->num_vertices * sizeof (struct skin));
112 for (i = 0; i < s->num_vertices; ++i) {
113 int j;
114 value v;
116 v = Field (skin_v, i);
117 skin[i].num_bones = Int_val (Field (v, 3));
119 for (j = 0; j < skin[i].num_bones; ++j) {
120 double val;
122 val = Double_val (Bp_val (Field (v, j)));
123 skin[i].boneindices[j] = (int) val;
124 skin[i].weights[j] = val - skin[i].boneindices[j];
125 skin[i].boneindices[j] += 1;
130 CAMLprim value ml_skin_draw_begin (value unit_v)
132 State *s = &glob_state;
134 glEnableClientState (GL_VERTEX_ARRAY);
135 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
136 glVertexPointer (3, GL_FLOAT, 0, NULL);
138 glEnableClientState (GL_NORMAL_ARRAY);
139 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
140 glNormalPointer (GL_FLOAT, 0, NULL);
142 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
143 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[UV_IDX]);
144 glTexCoordPointer (2, GL_FLOAT, 0, NULL);
145 return Val_unit;
148 CAMLprim value ml_skin_draw_end (value uint_v)
150 glDisableClientState (GL_VERTEX_ARRAY);
151 glDisableClientState (GL_NORMAL_ARRAY);
152 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
153 glBindBuffer (GL_ARRAY_BUFFER, 0);
155 #if 0
156 glDisable (GL_TEXTURE_2D);
157 glDisable (GL_LIGHTING);
158 glColor3f (1.0, 0.0, 0.0);
159 glDisable (GL_DEPTH_TEST);
160 glLineWidth (4.0);
162 glBegin (GL_LINES);
164 int i;
165 State *s = &glob_state;
166 struct bone *b = s->bones + 1;
168 for (i = 0; i < s->num_bones; ++i, ++b) {
169 struct bone *p = &s->bones[b->parent];
171 glVertex3fv (p->amv);
172 glVertex3fv (b->amv);
175 glEnd ();
176 #endif
177 return Val_unit;
180 CAMLprim value ml_skin_init (value geom_v)
182 CAMLparam1 (geom_v);
183 CAMLlocal4 (vertexa_v, normala_v, uva_v, skin_v);
184 State *s = &glob_state;
186 #ifdef _WIN32
187 *(PROC *) &glBindBuffer = wglGetProcAddress ("glBindBuffer");
188 *(PROC *) &glGenBuffers = wglGetProcAddress ("glGenBuffers");
189 *(PROC *) &glBufferData = wglGetProcAddress ("glBufferData");
190 *(PROC *) &glMapBuffer = wglGetProcAddress ("glMapBuffer");
191 *(PROC *) &glUnmapBuffer = wglGetProcAddress ("glUnmapBuffer");
192 #endif
193 vertexa_v = Field (geom_v, 0);
194 normala_v = Field (geom_v, 1);
195 uva_v = Field (geom_v, 2);
196 skin_v = Field (geom_v, 3);
198 skin_init (s, vertexa_v, normala_v, uva_v, skin_v);
199 CAMLreturn (Val_unit);
202 static void translate (State *s, float *dst)
204 int i, j;
205 struct bone *b;
206 float *curvert = s->ptrs[V_IDX];
207 struct skin *skin = s->skin;
209 for (i = 0; i < s->num_vertices; ++i, curvert += 3, dst += 3, ++skin)
211 float v[3] = {0,0,0}, v0[3], v1[3], v2[3], w, m[12];
213 for (j = 0; j < skin->num_bones; ++j) {
214 w = skin->weights[j] + 0.000011;
215 b = &s->bones[skin->boneindices[j]];
217 vsub (v0, curvert, b->mv);
218 mapply_to_vector (v1, b->im, v0);
220 mscale (m, b->am, w);
221 mapply_to_point (v2, m, v1);
223 vaddto (v, v2);
225 vcopy (dst, v);
230 CAMLprim value ml_skin_set_skel (value skel_v)
232 int i;
233 size_t size;
234 struct bone *b;
235 CAMLparam1 (skel_v);
236 CAMLlocal2 (v, floats_v);
237 State *s = &glob_state;
239 s->num_bones = Wosize_val (skel_v);
240 size = (s->num_bones + 1) * sizeof (struct bone);
241 s->bones = b = stat_alloc (size);
243 memset (b, 0, size);
244 b->parent = -1;
245 b->q[3] = 1.0;
246 b->mq[3] = 1.0;
247 b->aq[3] = 1.0;
248 b->amq[3] = 1.0;
249 b++;
251 for (i = 0; i < s->num_bones; ++i, ++b) {
252 v = Field (skel_v, i);
253 floats_v = Field (v, 1);
255 b->parent = Int_val (Field (v, 0)) + 1;
257 b->v[0] = Double_field (floats_v, 1);
258 b->v[1] = Double_field (floats_v, 2);
259 b->v[2] = Double_field (floats_v, 3);
261 b->q[0] = Double_field (floats_v, 5);
262 b->q[1] = Double_field (floats_v, 6);
263 b->q[2] = Double_field (floats_v, 7);
264 b->q[3] = Double_field (floats_v, 8);
267 b = s->bones + 1;
268 for (i = 0; i < s->num_bones; ++i, ++b) {
269 float v[3], q[4], q1[4], z[3] = {0,0,0};
270 struct bone *parent = &s->bones[b->parent];
272 qapply (v, parent->mq, b->v);
273 qcompose (b->mq, b->q, parent->mq);
274 vadd (b->mv, v, parent->mv);
276 qconjugate (q, b->mq);
277 qscale (q1, q, 1.0 / qmagnitude (q));
278 q2matrix (b->im, q1, z);
281 CAMLreturn (Val_unit);
284 CAMLprim value ml_skin_set_anim (value anim_v)
286 int i;
287 CAMLparam1 (anim_v);
288 CAMLlocal1 (floats_v);
289 State *s = &glob_state;
290 struct bone *b = s->bones + 1;
292 for (i = 0; i < s->num_bones; ++i, ++b) {
293 floats_v = Field (anim_v, i);
294 b->aq[0] = Double_field (floats_v, 0);
295 b->aq[1] = Double_field (floats_v, 1);
296 b->aq[2] = Double_field (floats_v, 2);
297 b->aq[3] = Double_field (floats_v, 3);
300 b = s->bones + 1;
301 for (i = 0; i < s->num_bones; ++i, ++b) {
302 float v[3];
303 struct bone *parent = &s->bones[b->parent];
305 qapply (v, parent->amq, b->v);
306 qcompose (b->amq, b->aq, parent->amq);
307 vadd (b->amv, v, parent->amv);
309 q2matrix (b->am, b->amq, b->amv);
312 CAMLreturn (Val_unit);
315 CAMLprim value ml_skin_anim (value unit_v)
317 GLboolean ret;
318 CAMLparam1 (unit_v);
319 float *vdst, *vsrc, *ndst, *nsrc;
320 State *s = &glob_state;
322 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
323 vdst = glMapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
324 if (!vdst) {
325 fprintf (stderr, "glMapBuffer for vertices failed\n");
326 exit (EXIT_FAILURE);
329 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
330 ndst = glMapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
331 if (!ndst) {
332 fprintf (stderr, "glMapBuffer for normals failed\n");
333 exit (EXIT_FAILURE);
336 vsrc = s->ptrs[V_IDX];
337 nsrc = s->ptrs[N_IDX];
339 translate (s, vdst);
340 #if 0
342 int i;
343 for (i = 0; i < s->num_vertices; ++i) {
344 struct skin *skin;
345 struct bone *bone, *parent;
346 float v[3], v1[3], *v2;
347 float q[4];
349 skin = &s->skin[i];
350 bone = &s->bones[skin->boneindices[0]];
351 parent = &s->bones[bone->parent];
353 vdst += 3;
354 vsrc += 3;
356 *ndst++ = *nsrc++;
357 *ndst++ = *nsrc++;
358 *ndst++ = *nsrc++;
361 #endif
363 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
364 ret = glUnmapBuffer (GL_ARRAY_BUFFER);
365 if (ret == GL_FALSE) {
366 fprintf (stderr, "glUnmapBuffer for vertices failed\n");
367 exit (EXIT_FAILURE);
370 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
371 ret = glUnmapBuffer (GL_ARRAY_BUFFER);
372 if (ret == GL_FALSE) {
373 fprintf (stderr, "glUnmapBuffer for normals failed\n");
374 exit (EXIT_FAILURE);
377 CAMLreturn (Val_unit);