Fix initial value for minmax calculation
[dormin.git] / skin.c
blobbd3891f0021ca24cc7183594c34e0a11a8ea4a19
1 #include <math.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
6 #include <caml/fail.h>
7 #include <caml/alloc.h>
8 #include <caml/memory.h>
10 #include "vec.c"
11 #include "pgl.h"
13 enum {V_IDX, N_IDX, UV_IDX, C_IDX, COUNT};
15 struct skin {
16 int boneindices[3];
17 float weights[3];
18 int num_bones;
21 struct bone {
22 int parent;
23 float v[3];
24 float q[4];
26 float mv[3];
27 float mq[4];
29 float aq[4];
30 float amq[4];
31 float amv[3];
33 float am[12];
34 float im[12];
37 typedef struct {
38 int num_bones;
39 int num_vertices;
40 GLuint bufid[COUNT];
41 float *ptrs[COUNT];
42 struct skin *skin;
43 struct bone *bones;
44 } State;
46 static State glob_state;
48 static void skin_init (State *s, value vertexa_v, value normala_v,
49 value uva_v, value skin_v, value colors_v)
51 int i;
52 GLsizei size;
53 float *p;
54 struct skin *skin;
55 s->num_vertices = Wosize_val (vertexa_v) / (Double_wosize * 3);
57 glGenBuffers (COUNT, s->bufid);
59 size = s->num_vertices * sizeof (GLfloat) * 3;
60 p = s->ptrs[V_IDX] = stat_alloc (size);
61 for (i = 0; i < s->num_vertices * 3; ++i) {
62 p[i] = Double_field (vertexa_v, i);
64 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
65 glBufferData (GL_ARRAY_BUFFER, size, p, GL_DYNAMIC_DRAW);
67 p = s->ptrs[N_IDX] = stat_alloc (size);
68 for (i = 0; i < s->num_vertices * 3; ++i) {
69 p[i] = Double_field (normala_v, i);
71 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
72 glBufferData (GL_ARRAY_BUFFER, size, p, GL_DYNAMIC_DRAW);
74 size = s->num_vertices * sizeof (GLfloat) * 2;
75 p = s->ptrs[UV_IDX] = stat_alloc (size);
76 for (i = 0; i < s->num_vertices * 2; ++i) {
77 p[i] = Double_field (uva_v, i);
79 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[UV_IDX]);
80 glBufferData (GL_ARRAY_BUFFER, size, p, GL_STATIC_DRAW);
81 stat_free (p);
83 size = s->num_vertices * 4;
84 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[C_IDX]);
85 glBufferData (GL_ARRAY_BUFFER, size, String_val (colors_v), GL_STATIC_DRAW);
87 s->skin = skin = stat_alloc (s->num_vertices * sizeof (struct skin));
88 for (i = 0; i < s->num_vertices; ++i) {
89 int j;
90 value v;
92 v = Field (skin_v, i);
93 skin[i].num_bones = Int_val (Field (v, 3));
95 for (j = 0; j < skin[i].num_bones; ++j) {
96 double val;
98 val = Double_val (Bp_val (Field (v, j)));
99 skin[i].boneindices[j] = (int) val;
100 skin[i].weights[j] = val - skin[i].boneindices[j];
101 skin[i].boneindices[j] += 1;
106 CAMLprim value ml_skin_draw_begin (value unit_v)
108 State *s = &glob_state;
110 (void) unit_v;
111 glEnableClientState (GL_VERTEX_ARRAY);
112 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
113 glVertexPointer (3, GL_FLOAT, 0, NULL);
115 glEnableClientState (GL_NORMAL_ARRAY);
116 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
117 glNormalPointer (GL_FLOAT, 0, NULL);
119 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
120 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[UV_IDX]);
121 glTexCoordPointer (2, GL_FLOAT, 0, NULL);
123 glEnableClientState (GL_COLOR_ARRAY);
124 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[C_IDX]);
125 glColorPointer (4, GL_UNSIGNED_BYTE, 0, NULL);
127 return Val_unit;
130 CAMLprim value ml_skin_draw_end (value unit_v)
132 (void) unit_v;
133 glDisableClientState (GL_VERTEX_ARRAY);
134 glDisableClientState (GL_NORMAL_ARRAY);
135 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
136 glDisableClientState (GL_COLOR_ARRAY);
137 glBindBuffer (GL_ARRAY_BUFFER, 0);
138 return Val_unit;
141 CAMLprim value ml_skin_init (value geom_v)
143 CAMLparam1 (geom_v);
144 CAMLlocal5 (vertexa_v, normala_v, uva_v, skin_v, colors_v);
145 State *s = &glob_state;
147 #ifdef _WIN32
148 GETPA (BindBuffer);
149 GETPA (GenBuffers);
150 GETPA (BufferData);
151 GETPA (MapBuffer);
152 GETPA (UnmapBuffer);
153 #endif
154 vertexa_v = Field (geom_v, 0);
155 normala_v = Field (geom_v, 1);
156 uva_v = Field (geom_v, 2);
157 skin_v = Field (geom_v, 3);
158 colors_v = Field (geom_v, 4);
160 skin_init (s, vertexa_v, normala_v, uva_v, skin_v, colors_v);
161 CAMLreturn (Val_unit);
164 static void translate (State *s, float *vdst, float *ndst)
166 int i, j;
167 struct bone *b;
168 float *vsrc = s->ptrs[V_IDX];
169 float *nsrc = s->ptrs[N_IDX];
170 struct skin *skin = s->skin;
172 for (i = 0; i < s->num_vertices; ++i,
173 vsrc += 3, nsrc += 3, vdst += 3, ndst += 3, ++skin)
175 int z = 0;
176 float v[3] = {0,0,0}, n[3] = {0,0,0}, v0[3], v1[3], v2[3], w, m[12];
178 for (j = 0; j < skin->num_bones; ++j) {
179 w = skin->weights[j];
180 b = &s->bones[skin->boneindices[j]];
182 if (w < 0.0) z = 1;
183 vsub (v0, vsrc, b->mv);
184 mapply_to_vector (v1, b->im, v0);
186 mscale (m, b->am, w);
187 mapply_to_point (v2, m, v1);
188 vaddto (v, v2);
190 mapply_to_vector (v0, b->im, nsrc);
191 mapply_to_vector (v1, m, v0);
192 vaddto (n, v1);
195 /* hack hack */
196 if (z) vcopy (v, vsrc);
197 vcopy (vdst, v);
198 vcopy (ndst, n);
203 CAMLprim value ml_skin_set_skel (value skel_v)
205 int i;
206 size_t size;
207 struct bone *b;
208 CAMLparam1 (skel_v);
209 CAMLlocal2 (v, floats_v);
210 State *s = &glob_state;
212 s->num_bones = Wosize_val (skel_v);
213 size = (s->num_bones + 1) * sizeof (struct bone);
214 s->bones = b = stat_alloc (size);
216 memset (b, 0, size);
217 b->parent = -1;
218 b->q[3] = 1.0;
219 b->mq[3] = 1.0;
220 b->aq[3] = 1.0;
221 b->amq[3] = 1.0;
222 b++;
224 for (i = 0; i < s->num_bones; ++i, ++b) {
225 v = Field (skel_v, i);
226 floats_v = Field (v, 1);
228 b->parent = Int_val (Field (v, 0)) + 1;
230 b->v[0] = Double_field (floats_v, 1);
231 b->v[1] = Double_field (floats_v, 2);
232 b->v[2] = Double_field (floats_v, 3);
234 b->q[0] = Double_field (floats_v, 5);
235 b->q[1] = Double_field (floats_v, 6);
236 b->q[2] = Double_field (floats_v, 7);
237 b->q[3] = Double_field (floats_v, 8);
240 b = s->bones + 1;
241 for (i = 0; i < s->num_bones; ++i, ++b) {
242 float v[3], q[4], z[3] = {0,0,0};
243 struct bone *parent = &s->bones[b->parent];
245 qapply (v, parent->mq, b->v);
246 qcompose (b->mq, b->q, parent->mq);
247 vadd (b->mv, v, parent->mv);
249 qconjugate (q, b->mq);
250 q2matrix (b->im, q, z);
253 CAMLreturn (Val_unit);
256 CAMLprim value ml_skin_set_anim (value anim_v)
258 int i;
259 CAMLparam1 (anim_v);
260 CAMLlocal1 (floats_v);
261 State *s = &glob_state;
262 struct bone *b = s->bones + 1;
264 for (i = 0; i < s->num_bones; ++i, ++b) {
265 floats_v = Field (anim_v, i);
266 b->aq[0] = Double_field (floats_v, 0);
267 b->aq[1] = Double_field (floats_v, 1);
268 b->aq[2] = Double_field (floats_v, 2);
269 b->aq[3] = Double_field (floats_v, 3);
272 b = s->bones + 1;
273 for (i = 0; i < s->num_bones; ++i, ++b) {
274 float v[3];
275 struct bone *parent = &s->bones[b->parent];
277 qapply (v, parent->amq, b->v);
278 qcompose (b->amq, b->aq, parent->amq);
279 vadd (b->amv, v, parent->amv);
281 q2matrix (b->am, b->amq, b->amv);
284 CAMLreturn (Val_unit);
287 CAMLprim value ml_skin_anim (value unit_v)
289 GLboolean ret;
290 CAMLparam1 (unit_v);
291 float *vdst, *vsrc, *ndst, *nsrc;
292 State *s = &glob_state;
294 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
295 vdst = glMapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
296 if (!vdst) {
297 fprintf (stderr, "glMapBuffer for vertices failed\n");
298 exit (EXIT_FAILURE);
301 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
302 ndst = glMapBuffer (GL_ARRAY_BUFFER, GL_WRITE_ONLY);
303 if (!ndst) {
304 fprintf (stderr, "glMapBuffer for normals failed\n");
305 exit (EXIT_FAILURE);
308 vsrc = s->ptrs[V_IDX];
309 nsrc = s->ptrs[N_IDX];
311 translate (s, vdst, ndst);
313 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[V_IDX]);
314 ret = glUnmapBuffer (GL_ARRAY_BUFFER);
315 if (ret == GL_FALSE) {
316 fprintf (stderr, "glUnmapBuffer for vertices failed\n");
317 exit (EXIT_FAILURE);
320 glBindBuffer (GL_ARRAY_BUFFER, s->bufid[N_IDX]);
321 ret = glUnmapBuffer (GL_ARRAY_BUFFER);
322 if (ret == GL_FALSE) {
323 fprintf (stderr, "glUnmapBuffer for normals failed\n");
324 exit (EXIT_FAILURE);
327 CAMLreturn (Val_unit);