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
)
206 glBindProgramARB (GL_VERTEX_PROGRAM_ARB
, progid
);
208 glProgramStringARB (GL_VERTEX_PROGRAM_ARB
, GL_PROGRAM_FORMAT_ASCII_ARB
,
209 size
, (const GLubyte
*) text
);
210 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB
, &pos
);
214 snprintf (buf
, 1024, "glProgramStringARB: error %s at %d",
215 (char *) glGetString (GL_PROGRAM_ERROR_STRING_ARB
), pos
);
221 memset (r
, 0, sizeof (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
);
225 glProgramLocalParameter4fvARB (GL_VERTEX_PROGRAM_ARB
, 0, r
);
229 CAMLprim value
ml_skin_draw_begin_vp (value unit_v
)
232 State
*s
= &glob_state
;
236 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
);
238 for (i
= 0; i
< COUNT
; ++i
) {
239 struct adescr
*ad
= &s
->ad
[i
];
241 glEnableVertexAttribArrayARB (ad
->index
);
242 glVertexAttribPointerARB (ad
->index
, ad
->num_elems
, ad
->type
,
243 ad
->norm
, ad
->stride
, s
->array
+ ad
->offset
);
246 glEnable (GL_VERTEX_PROGRAM_ARB
);
250 CAMLprim value
ml_skin_draw_end_vp (value unit_v
)
253 State
*s
= &glob_state
;
257 for (i
= 0; i
< COUNT
; ++i
)
258 glDisableVertexAttribArrayARB (s
->ad
[i
].index
);
260 glBindBuffer (GL_ARRAY_BUFFER
, 0);
261 glDisable (GL_VERTEX_PROGRAM_ARB
);
265 CAMLprim value
ml_skin_init_vp (value use_vbo_v
, value geom_v
)
267 CAMLparam2 (use_vbo_v
, geom_v
);
268 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
269 State
*s
= &glob_state
;
271 use_vbo
= Bool_val (use_vbo_v
);
278 GETPA (BindProgramARB
);
279 GETPA (ProgramStringARB
);
280 GETPA (ProgramLocalParameter4fvARB
);
281 GETPA (EnableVertexAttribArrayARB
);
282 GETPA (DisableVertexAttribArrayARB
);
283 GETPA (VertexAttribPointerARB
);
286 vertexa_v
= Field (geom_v
, 0);
287 normala_v
= Field (geom_v
, 1);
288 uva_v
= Field (geom_v
, 2);
289 skin_v
= Field (geom_v
, 3);
290 colors_v
= Field (geom_v
, 4);
292 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
, 1);
294 CAMLreturn (Val_unit
);
297 CAMLprim value
ml_skin_set_skel_vp (value skel_v
)
303 CAMLlocal2 (v
, floats_v
);
304 State
*s
= &glob_state
;
306 s
->num_bones
= Wosize_val (skel_v
);
307 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
308 s
->bones
= b
= stat_alloc (size
);
318 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
319 v
= Field (skel_v
, i
);
320 floats_v
= Field (v
, 1);
322 b
->parent
= Int_val (Field (v
, 0)) + 1;
324 b
->v
[0] = Double_field (floats_v
, 1);
325 b
->v
[1] = Double_field (floats_v
, 2);
326 b
->v
[2] = Double_field (floats_v
, 3);
328 b
->q
[0] = Double_field (floats_v
, 5);
329 b
->q
[1] = Double_field (floats_v
, 6);
330 b
->q
[2] = Double_field (floats_v
, 7);
331 b
->q
[3] = Double_field (floats_v
, 8);
335 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
337 struct bone
*parent
= &s
->bones
[b
->parent
];
339 qapply (v
, parent
->mq
, b
->v
);
340 qcompose (b
->mq
, b
->q
, parent
->mq
);
341 vadd (b
->mv
, v
, parent
->mv
);
343 memset (b
->cm
, 0, sizeof (b
->cm
));
349 CAMLreturn (Val_unit
);
352 CAMLprim value
ml_skin_set_anim_vp (value anim_v
)
356 CAMLlocal1 (floats_v
);
357 State
*s
= &glob_state
;
358 struct bone
*b
= s
->bones
+ 1;
360 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
361 floats_v
= Field (anim_v
, i
);
362 b
->aq
[0] = Double_field (floats_v
, 0);
363 b
->aq
[1] = Double_field (floats_v
, 1);
364 b
->aq
[2] = Double_field (floats_v
, 2);
365 b
->aq
[3] = Double_field (floats_v
, 3);
369 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
370 float v
[4], v1
[4], q
[4], q1
[4];
371 struct bone
*parent
= &s
->bones
[b
->parent
];
373 qapply (v
, parent
->amq
, b
->v
);
374 qcompose (b
->amq
, b
->aq
, parent
->amq
);
375 vadd (b
->amv
, v
, parent
->amv
);
377 qconjugate (q1
, b
->mq
);
378 qcompose (q
, q1
, b
->amq
);
380 qapply (v
, q
, b
->mv
);
381 vsub (v1
, b
->amv
, v
);
382 q2matrixt (b
->cm
, q
, v1
);
385 CAMLreturn (Val_unit
);
388 CAMLprim value
ml_skin_anim_vp (value unit_v
)
391 State
*s
= &glob_state
;
394 CAMLreturn (Val_unit
);
397 CAMLprim value
ml_skin_set_text_vp (value text_v
)
400 State
*s
= &glob_state
;
402 load_program (String_val (text_v
), caml_string_length (text_v
), 1);
404 CAMLreturn (Val_unit
);