7 #include <caml/alloc.h>
8 #include <caml/memory.h>
13 enum {V_IDX
, N_IDX
, UV_IDX
, C_IDX
, COUNT
};
48 static State glob_state
;
51 static void skin_init (State
*s
, value vertexa_v
, value normala_v
,
52 value uva_v
, value skin_v
, value colors_v
)
58 s
->num_vertices
= Wosize_val (vertexa_v
) / (Double_wosize
* 3);
61 glGenBuffers (COUNT
, s
->bufid
);
63 size
= s
->num_vertices
* sizeof (GLfloat
) * 3;
64 p
= s
->ptrs
[V_IDX
] = stat_alloc (size
);
65 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
66 p
[i
] = Double_field (vertexa_v
, i
);
69 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
70 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
73 s
->bufs
[V_IDX
] = simd_alloc (16, size
);
74 memcpy (s
->bufs
[V_IDX
], p
, size
);
77 p
= s
->ptrs
[N_IDX
] = stat_alloc (size
);
78 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
79 p
[i
] = Double_field (normala_v
, i
);
82 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
83 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
86 s
->bufs
[N_IDX
] = simd_alloc (16, size
);
87 memcpy (s
->bufs
[N_IDX
], p
, size
);
90 size
= s
->num_vertices
* sizeof (GLfloat
) * 2;
91 p
= s
->ptrs
[UV_IDX
] = stat_alloc (size
);
92 for (i
= 0; i
< s
->num_vertices
* 2; ++i
) {
93 p
[i
] = Double_field (uva_v
, i
);
96 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
97 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_STATIC_DRAW
);
100 s
->bufs
[UV_IDX
] = simd_alloc (16, size
);
101 memcpy (s
->bufs
[UV_IDX
], p
, size
);
105 size
= s
->num_vertices
* 4;
107 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
108 glBufferData (GL_ARRAY_BUFFER
, size
, String_val (colors_v
), GL_STATIC_DRAW
);
111 s
->bufs
[C_IDX
] = simd_alloc (16, size
);
112 memcpy (s
->bufs
[C_IDX
], String_val (colors_v
), size
);
115 s
->skin
= skin
= stat_alloc (s
->num_vertices
* sizeof (struct skin
));
116 for (i
= 0; i
< s
->num_vertices
; ++i
) {
120 v
= Field (skin_v
, i
);
121 skin
[i
].num_bones
= Int_val (Field (v
, 3));
123 for (j
= 0; j
< skin
[i
].num_bones
; ++j
) {
126 val
= Double_val (Bp_val (Field (v
, j
)));
127 skin
[i
].boneindices
[j
] = (int) val
;
128 skin
[i
].weights
[j
] = val
- skin
[i
].boneindices
[j
];
129 skin
[i
].boneindices
[j
] += 1;
134 CAMLprim value
ml_skin_draw_begin (value unit_v
)
136 State
*s
= &glob_state
;
139 glEnableClientState (GL_VERTEX_ARRAY
);
140 if (use_vbo
) glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
141 glVertexPointer (3, GL_FLOAT
, 0, s
->bufs
[V_IDX
]);
143 glEnableClientState (GL_NORMAL_ARRAY
);
144 if (use_vbo
) glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
145 glNormalPointer (GL_FLOAT
, 0, s
->bufs
[V_IDX
]);
147 glEnableClientState (GL_TEXTURE_COORD_ARRAY
);
148 if (use_vbo
) glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
149 glTexCoordPointer (2, GL_FLOAT
, 0, s
->bufs
[UV_IDX
]);
151 glEnableClientState (GL_COLOR_ARRAY
);
152 if (use_vbo
) glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
153 glColorPointer (4, GL_UNSIGNED_BYTE
, 0, s
->bufs
[C_IDX
]);
158 CAMLprim value
ml_skin_draw_end (value unit_v
)
161 glDisableClientState (GL_VERTEX_ARRAY
);
162 glDisableClientState (GL_NORMAL_ARRAY
);
163 glDisableClientState (GL_TEXTURE_COORD_ARRAY
);
164 glDisableClientState (GL_COLOR_ARRAY
);
165 if (use_vbo
) glBindBuffer (GL_ARRAY_BUFFER
, 0);
169 CAMLprim value
ml_skin_init (value use_vbo_v
, value geom_v
)
171 CAMLparam2 (use_vbo_v
, geom_v
);
172 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
173 State
*s
= &glob_state
;
175 use_vbo
= Bool_val (use_vbo_v
);
185 vertexa_v
= Field (geom_v
, 0);
186 normala_v
= Field (geom_v
, 1);
187 uva_v
= Field (geom_v
, 2);
188 skin_v
= Field (geom_v
, 3);
189 colors_v
= Field (geom_v
, 4);
191 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
192 CAMLreturn (Val_unit
);
195 static void translate (State
*s
, float *vdst
, float *ndst
)
199 float *vsrc
= s
->ptrs
[V_IDX
];
200 float *nsrc
= s
->ptrs
[N_IDX
];
201 struct skin
*skin
= s
->skin
;
203 for (i
= 0; i
< s
->num_vertices
; ++i
,
204 vsrc
+= 3, nsrc
+= 3, vdst
+= 3, ndst
+= 3, ++skin
)
208 float v
[4] A16
= {0,0,0,0}, n
[4] A16
= {0,0,0,0};
209 float v0
[4] A16
, v1
[4] A16
, m
[16] A16
, n1
[4] A16
;
214 float v
[3] = {0,0,0}, n
[3] = {0,0,0}, v0
[3], v1
[3], w
, m
[12];
217 for (j
= 0; j
< skin
->num_bones
; ++j
) {
218 w
= skin
->weights
[j
];
219 b
= &s
->bones
[skin
->boneindices
[j
]];
222 vsub (v0
, vsrc
, b
->mv
);
223 mapply_to_vector (v1
, b
->im
, v0
);
225 mscale (m
, b
->am
, w
);
226 mapply_to_point (v0
, m
, v1
);
229 mapply_to_vector (v0
, b
->im
, n1
);
230 mapply_to_vector (v1
, m
, v0
);
235 if (z
) vcopy (vdst
, vsrc
);
236 else vcopy (vdst
, v
);
241 CAMLprim value
ml_skin_set_skel (value skel_v
)
247 CAMLlocal2 (v
, floats_v
);
248 State
*s
= &glob_state
;
250 s
->num_bones
= Wosize_val (skel_v
);
251 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
252 s
->bones
= b
= simd_alloc (16, size
);
262 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
263 v
= Field (skel_v
, i
);
264 floats_v
= Field (v
, 1);
266 b
->parent
= Int_val (Field (v
, 0)) + 1;
268 b
->v
[0] = Double_field (floats_v
, 1);
269 b
->v
[1] = Double_field (floats_v
, 2);
270 b
->v
[2] = Double_field (floats_v
, 3);
272 b
->q
[0] = Double_field (floats_v
, 5);
273 b
->q
[1] = Double_field (floats_v
, 6);
274 b
->q
[2] = Double_field (floats_v
, 7);
275 b
->q
[3] = Double_field (floats_v
, 8);
279 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
280 float v
[3], q
[4], z
[3] = {0,0,0};
281 struct bone
*parent
= &s
->bones
[b
->parent
];
283 qapply (v
, parent
->mq
, b
->v
);
284 qcompose (b
->mq
, b
->q
, parent
->mq
);
285 vadd (b
->mv
, v
, parent
->mv
);
287 qconjugate (q
, b
->mq
);
288 q2matrix (b
->im
, q
, z
);
291 CAMLreturn (Val_unit
);
294 CAMLprim value
ml_skin_set_anim (value anim_v
)
298 CAMLlocal1 (floats_v
);
299 State
*s
= &glob_state
;
300 struct bone
*b
= s
->bones
+ 1;
302 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
303 floats_v
= Field (anim_v
, i
);
304 b
->aq
[0] = Double_field (floats_v
, 0);
305 b
->aq
[1] = Double_field (floats_v
, 1);
306 b
->aq
[2] = Double_field (floats_v
, 2);
307 b
->aq
[3] = Double_field (floats_v
, 3);
311 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
313 struct bone
*parent
= &s
->bones
[b
->parent
];
315 qapply (v
, parent
->amq
, b
->v
);
316 qcompose (b
->amq
, b
->aq
, parent
->amq
);
317 vadd (b
->amv
, v
, parent
->amv
);
319 q2matrix (b
->am
, b
->amq
, b
->amv
);
322 CAMLreturn (Val_unit
);
325 CAMLprim value
ml_skin_anim (value unit_v
)
329 float *vdst
, *vsrc
, *ndst
, *nsrc
;
330 State
*s
= &glob_state
;
333 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
334 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
336 fprintf (stderr
, "glMapBuffer for vertices failed\n");
340 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
341 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
343 fprintf (stderr
, "glMapBuffer for normals failed\n");
348 vdst
= s
->bufs
[V_IDX
];
349 ndst
= s
->bufs
[N_IDX
];
352 vsrc
= s
->ptrs
[V_IDX
];
353 nsrc
= s
->ptrs
[N_IDX
];
355 translate (s
, vdst
, ndst
);
358 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
359 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
360 if (ret
== GL_FALSE
) {
361 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
365 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
366 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
367 if (ret
== GL_FALSE
) {
368 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
373 CAMLreturn (Val_unit
);