7 #include <caml/alloc.h>
8 #include <caml/memory.h>
16 #define snprintf _snprintf
19 enum {V_IDX
, N_IDX
, UV_IDX
, C_IDX
, A_IDX
, COUNT
};
53 const struct adescr ad
[] = {
54 { 4, 0, 0, 12, 0, 3, GL_FLOAT
},
55 { 4, 0, 2, 12, 0, 3, GL_FLOAT
},
56 { 4, 0, 8, 8, 0, 2, GL_FLOAT
},
57 { 1, 1, 3, 4, 0, 4, GL_UNSIGNED_BYTE
},
58 { 4, 0, 6, 12, 0, 3, GL_FLOAT
}
66 struct adescr ad
[COUNT
];
71 static State glob_state
;
74 static void skin_init (State
*s
, value vertexa_v
, value normala_v
,
75 value uva_v
, value skin_v
, value colors_v
,
84 GLsizei stride
= 12 * sizeof (GLfloat
);
85 GLsizei strides
[COUNT
];
87 s
->num_vertices
= Wosize_val (vertexa_v
) / (Double_wosize
* 3);
89 for (i
= 0, size
= 0; i
< COUNT
; ++i
) {
90 s
->ad
[i
].index
= ad
[i
].index
;
92 s
->ad
[i
].offset
= offset
;
93 s
->ad
[i
].stride
= stride
;
95 offset
+= ad
[i
].stride
;
98 strides
[i
] = ad
[i
].stride
;
99 s
->ad
[i
].offset
= size
;
101 ad
[i
].num_elems
*ad
[i
].size
== ad
[i
].stride
106 s
->ad
[i
].norm
= ad
[i
].norm
;
107 s
->ad
[i
].type
= ad
[i
].type
;
108 s
->ad
[i
].num_elems
= ad
[i
].num_elems
;
109 s
->ad
[i
].size
= ad
[i
].num_elems
* ad
[i
].size
* s
->num_vertices
;
110 size
+= s
->ad
[i
].size
;
114 glGenBuffers (1, &s
->bufid
);
115 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
);
116 glBufferData (GL_ARRAY_BUFFER
, size
, NULL
, GL_STATIC_DRAW
);
117 map
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
118 if (!map
) caml_failwith ("glMapBuffer failed");
121 map
= stat_alloc (size
);
124 p
= map
+ s
->ad
[V_IDX
].offset
;
125 for (i
= 0; i
< s
->num_vertices
; ++i
) {
126 ((float *) p
)[0] = Double_field (vertexa_v
, i
*3 + 0);
127 ((float *) p
)[1] = Double_field (vertexa_v
, i
*3 + 1);
128 ((float *) p
)[2] = Double_field (vertexa_v
, i
*3 + 2);
132 p
= map
+ s
->ad
[N_IDX
].offset
;
133 for (i
= 0; i
< s
->num_vertices
; ++i
) {
134 ((float *) p
)[0] = Double_field (normala_v
, i
*3 + 0);
135 ((float *) p
)[1] = Double_field (normala_v
, i
*3 + 1);
136 ((float *) p
)[2] = Double_field (normala_v
, i
*3 + 2);
140 p
= map
+ s
->ad
[UV_IDX
].offset
;
141 for (i
= 0; i
< s
->num_vertices
; ++i
) {
142 ((float *) p
)[0] = Double_field (uva_v
, i
*2 + 0);
143 ((float *) p
)[1] = Double_field (uva_v
, i
*2 + 1);
144 p
+= strides
[UV_IDX
];
147 p
= map
+ s
->ad
[C_IDX
].offset
;
149 for (i
= 0; i
< s
->num_vertices
; ++i
) {
150 memcpy (p
, String_val (colors_v
) + i
*4, 4);
154 s
->skin
= skin
= stat_alloc (s
->num_vertices
* sizeof (struct skin
));
155 p
= map
+ s
->ad
[A_IDX
].offset
;
157 for (i
= 0; i
< s
->num_vertices
; ++i
) {
161 v
= Field (skin_v
, i
);
162 skin
[i
].num_bones
= Int_val (Field (v
, 3));
164 for (j
= 0; j
< skin
[i
].num_bones
; ++j
) {
167 val
= Double_val (Bp_val (Field (v
, j
)));
168 skin
[i
].boneindices
[j
] = (int) val
;
169 w
= val
- skin
[i
].boneindices
[j
];
170 skin
[i
].weights
[j
] = w
;
171 skin
[i
].boneindices
[j
] += 1;
172 ((float *) p
)[j
] = skin
[i
].boneindices
[j
] * 3 + w
;
175 for (j
= skin
[i
].num_bones
; j
< 3; ++j
) {
176 ((float *) p
)[j
] = 0.0;
182 if (glUnmapBuffer (GL_ARRAY_BUFFER
) == GL_FALSE
)
183 caml_failwith ("glUnmapBuffer failed");
190 static void skin_anim (State
*s
)
193 struct bone
*b
= s
->bones
+ 1;
195 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
, j
+= 3) {
196 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, j
+ 0, b
->cm
+ 0);
197 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, j
+ 1, b
->cm
+ 4);
198 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, j
+ 2, b
->cm
+ 8);
202 static void load_program (const char *text
, GLsizei size
, GLuint progid
)
204 glBindProgramARB (GL_VERTEX_PROGRAM_ARB
, progid
);
206 glProgramStringARB (GL_VERTEX_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
,
207 size
, (const GLubyte
*) text
);
208 if (glGetError () != GL_NO_ERROR
) {
212 glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB
, &pos
);
213 snprintf (buf
, 1024, "glProgramStringARB: error %s at %d",
214 (char *) glGetString (GL_PROGRAM_ERROR_STRING_ARB
), pos
);
220 memset (r
, 0, sizeof (r
));
221 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, 0, r
);
222 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, 0, r
);
223 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, 0, r
);
224 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, 0, r
);
228 CAMLprim value
ml_skin_draw_begin_vp (value unit_v
)
231 State
*s
= &glob_state
;
235 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
);
237 for (i
= 0; i
< COUNT
; ++i
) {
238 struct adescr
*ad
= &s
->ad
[i
];
240 glEnableVertexAttribArrayARB (ad
->index
);
241 glVertexAttribPointerARB (ad
->index
, ad
->num_elems
, ad
->type
,
242 ad
->norm
, ad
->stride
, s
->array
+ ad
->offset
);
245 glEnable (GL_VERTEX_PROGRAM_ARB
);
249 CAMLprim value
ml_skin_draw_end_vp (value unit_v
)
252 State
*s
= &glob_state
;
256 for (i
= 0; i
< COUNT
; ++i
)
257 glDisableVertexAttribArrayARB (s
->ad
[i
].index
);
259 glBindBuffer (GL_ARRAY_BUFFER
, 0);
260 glDisable (GL_VERTEX_PROGRAM_ARB
);
264 CAMLprim value
ml_skin_init_vp (value text_v
, value use_vbo_v
, value geom_v
)
266 CAMLparam3 (use_vbo_v
, text_v
, geom_v
);
267 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
268 State
*s
= &glob_state
;
270 use_vbo
= Bool_val (use_vbo_v
);
277 GETPA (BindProgramARB
);
278 GETPA (ProgramStringARB
);
279 GETPA (ProgramLocalParameter4fvARB
);
280 GETPA (EnableVertexAttribArrayARB
);
281 GETPA (DisableVertexAttribArrayARB
);
282 GETPA (VertexAttribPointerARB
);
285 vertexa_v
= Field (geom_v
, 0);
286 normala_v
= Field (geom_v
, 1);
287 uva_v
= Field (geom_v
, 2);
288 skin_v
= Field (geom_v
, 3);
289 colors_v
= Field (geom_v
, 4);
291 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
, 1);
292 load_program (String_val (text_v
), caml_string_length (text_v
), 1);
295 CAMLreturn (Val_unit
);
298 CAMLprim value
ml_skin_set_skel_vp (value skel_v
)
304 CAMLlocal2 (v
, floats_v
);
305 State
*s
= &glob_state
;
307 s
->num_bones
= Wosize_val (skel_v
);
308 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
309 s
->bones
= b
= stat_alloc (size
);
319 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
320 v
= Field (skel_v
, i
);
321 floats_v
= Field (v
, 1);
323 b
->parent
= Int_val (Field (v
, 0)) + 1;
325 b
->v
[0] = Double_field (floats_v
, 1);
326 b
->v
[1] = Double_field (floats_v
, 2);
327 b
->v
[2] = Double_field (floats_v
, 3);
329 b
->q
[0] = Double_field (floats_v
, 5);
330 b
->q
[1] = Double_field (floats_v
, 6);
331 b
->q
[2] = Double_field (floats_v
, 7);
332 b
->q
[3] = Double_field (floats_v
, 8);
336 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
338 struct bone
*parent
= &s
->bones
[b
->parent
];
340 qapply (v
, parent
->mq
, b
->v
);
341 qcompose (b
->mq
, b
->q
, parent
->mq
);
342 vadd (b
->mv
, v
, parent
->mv
);
344 memset (b
->cm
, 0, sizeof (b
->cm
));
350 CAMLreturn (Val_unit
);
353 CAMLprim value
ml_skin_set_anim_vp (value anim_v
)
357 CAMLlocal1 (floats_v
);
358 State
*s
= &glob_state
;
359 struct bone
*b
= s
->bones
+ 1;
361 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
362 floats_v
= Field (anim_v
, i
);
363 b
->aq
[0] = Double_field (floats_v
, 0);
364 b
->aq
[1] = Double_field (floats_v
, 1);
365 b
->aq
[2] = Double_field (floats_v
, 2);
366 b
->aq
[3] = Double_field (floats_v
, 3);
370 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
371 float v
[4], v1
[4], q
[4], q1
[4];
372 struct bone
*parent
= &s
->bones
[b
->parent
];
374 qapply (v
, parent
->amq
, b
->v
);
375 qcompose (b
->amq
, b
->aq
, parent
->amq
);
376 vadd (b
->amv
, v
, parent
->amv
);
378 qconjugate (q1
, b
->mq
);
379 qcompose (q
, q1
, b
->amq
);
381 qapply (v
, q
, b
->mv
);
382 vsub (v1
, b
->amv
, v
);
383 q2matrixt (b
->cm
, q
, v1
);
386 CAMLreturn (Val_unit
);
389 CAMLprim value
ml_skin_anim_vp (value unit_v
)
392 State
*s
= &glob_state
;
395 CAMLreturn (Val_unit
);