7 #include <caml/alloc.h>
8 #include <caml/memory.h>
13 enum {V_IDX
, N_IDX
, UV_IDX
, C_IDX
, COUNT
};
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
)
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
);
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
) {
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
) {
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
;
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
);
130 CAMLprim value
ml_skin_draw_end (value 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);
141 CAMLprim value
ml_skin_init (value geom_v
)
144 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
145 State
*s
= &glob_state
;
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
)
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 float v
[3] = {0,0,0}, n
[3] = {0,0,0}, v0
[3], v1
[3], v2
[3], w
, m
[12];
177 for (j
= 0; j
< skin
->num_bones
; ++j
) {
178 w
= skin
->weights
[j
] + 0.000011;
179 b
= &s
->bones
[skin
->boneindices
[j
]];
181 vsub (v0
, vsrc
, b
->mv
);
182 mapply_to_vector (v1
, b
->im
, v0
);
184 mscale (m
, b
->am
, w
);
185 mapply_to_point (v2
, m
, v1
);
188 mapply_to_vector (v0
, b
->im
, nsrc
);
189 mapply_to_vector (v1
, m
, v0
);
199 CAMLprim value
ml_skin_set_skel (value skel_v
)
205 CAMLlocal2 (v
, floats_v
);
206 State
*s
= &glob_state
;
208 s
->num_bones
= Wosize_val (skel_v
);
209 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
210 s
->bones
= b
= stat_alloc (size
);
220 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
221 v
= Field (skel_v
, i
);
222 floats_v
= Field (v
, 1);
224 b
->parent
= Int_val (Field (v
, 0)) + 1;
226 b
->v
[0] = Double_field (floats_v
, 1);
227 b
->v
[1] = Double_field (floats_v
, 2);
228 b
->v
[2] = Double_field (floats_v
, 3);
230 b
->q
[0] = Double_field (floats_v
, 5);
231 b
->q
[1] = Double_field (floats_v
, 6);
232 b
->q
[2] = Double_field (floats_v
, 7);
233 b
->q
[3] = Double_field (floats_v
, 8);
237 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
238 float v
[3], q
[4], q1
[4], z
[3] = {0,0,0};
239 struct bone
*parent
= &s
->bones
[b
->parent
];
241 qapply (v
, parent
->mq
, b
->v
);
242 qcompose (b
->mq
, b
->q
, parent
->mq
);
243 vadd (b
->mv
, v
, parent
->mv
);
245 qconjugate (q
, b
->mq
);
246 qscale (q1
, q
, 1.0 / qmagnitude (q
));
247 q2matrix (b
->im
, q1
, z
);
250 CAMLreturn (Val_unit
);
253 CAMLprim value
ml_skin_set_anim (value anim_v
)
257 CAMLlocal1 (floats_v
);
258 State
*s
= &glob_state
;
259 struct bone
*b
= s
->bones
+ 1;
261 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
262 floats_v
= Field (anim_v
, i
);
263 b
->aq
[0] = Double_field (floats_v
, 0);
264 b
->aq
[1] = Double_field (floats_v
, 1);
265 b
->aq
[2] = Double_field (floats_v
, 2);
266 b
->aq
[3] = Double_field (floats_v
, 3);
270 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
272 struct bone
*parent
= &s
->bones
[b
->parent
];
274 qapply (v
, parent
->amq
, b
->v
);
275 qcompose (b
->amq
, b
->aq
, parent
->amq
);
276 vadd (b
->amv
, v
, parent
->amv
);
278 q2matrix (b
->am
, b
->amq
, b
->amv
);
281 CAMLreturn (Val_unit
);
284 CAMLprim value
ml_skin_anim (value unit_v
)
288 float *vdst
, *vsrc
, *ndst
, *nsrc
;
289 State
*s
= &glob_state
;
291 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
292 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
294 fprintf (stderr
, "glMapBuffer for vertices failed\n");
298 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
299 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
301 fprintf (stderr
, "glMapBuffer for normals failed\n");
305 vsrc
= s
->ptrs
[V_IDX
];
306 nsrc
= s
->ptrs
[N_IDX
];
308 translate (s
, vdst
, ndst
);
310 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
311 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
312 if (ret
== GL_FALSE
) {
313 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
317 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
318 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
319 if (ret
== GL_FALSE
) {
320 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
324 CAMLreturn (Val_unit
);