7 #include <caml/alloc.h>
8 #include <caml/memory.h>
13 enum {V_IDX
, N_IDX
, UV_IDX
, C_IDX
, COUNT
};
47 static State glob_state
;
49 static void skin_init (State
*s
, value vertexa_v
, value normala_v
,
50 value uva_v
, value skin_v
, value colors_v
)
56 s
->num_vertices
= Wosize_val (vertexa_v
) / (Double_wosize
* 3);
58 glGenBuffers (COUNT
, s
->bufid
);
60 size
= s
->num_vertices
* sizeof (GLfloat
) * 3;
61 p
= s
->ptrs
[V_IDX
] = stat_alloc (size
);
62 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
63 p
[i
] = Double_field (vertexa_v
, i
);
65 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
66 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
68 p
= s
->ptrs
[N_IDX
] = stat_alloc (size
);
69 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
70 p
[i
] = Double_field (normala_v
, i
);
72 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
73 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
75 size
= s
->num_vertices
* sizeof (GLfloat
) * 2;
76 p
= s
->ptrs
[UV_IDX
] = stat_alloc (size
);
77 for (i
= 0; i
< s
->num_vertices
* 2; ++i
) {
78 p
[i
] = Double_field (uva_v
, i
);
80 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
81 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_STATIC_DRAW
);
84 size
= s
->num_vertices
* 4;
85 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
86 glBufferData (GL_ARRAY_BUFFER
, size
, String_val (colors_v
), GL_STATIC_DRAW
);
88 s
->skin
= skin
= stat_alloc (s
->num_vertices
* sizeof (struct skin
));
89 for (i
= 0; i
< s
->num_vertices
; ++i
) {
93 v
= Field (skin_v
, i
);
94 skin
[i
].num_bones
= Int_val (Field (v
, 3));
96 for (j
= 0; j
< skin
[i
].num_bones
; ++j
) {
99 val
= Double_val (Bp_val (Field (v
, j
)));
100 skin
[i
].boneindices
[j
] = (int) val
;
101 skin
[i
].weights
[j
] = val
- skin
[i
].boneindices
[j
];
102 skin
[i
].boneindices
[j
] += 1;
107 CAMLprim value
ml_skin_draw_begin (value unit_v
)
109 State
*s
= &glob_state
;
112 glEnableClientState (GL_VERTEX_ARRAY
);
113 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
114 glVertexPointer (3, GL_FLOAT
, 0, NULL
);
116 glEnableClientState (GL_NORMAL_ARRAY
);
117 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
118 glNormalPointer (GL_FLOAT
, 0, NULL
);
120 glEnableClientState (GL_TEXTURE_COORD_ARRAY
);
121 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
122 glTexCoordPointer (2, GL_FLOAT
, 0, NULL
);
124 glEnableClientState (GL_COLOR_ARRAY
);
125 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
126 glColorPointer (4, GL_UNSIGNED_BYTE
, 0, NULL
);
131 CAMLprim value
ml_skin_draw_end (value unit_v
)
134 glDisableClientState (GL_VERTEX_ARRAY
);
135 glDisableClientState (GL_NORMAL_ARRAY
);
136 glDisableClientState (GL_TEXTURE_COORD_ARRAY
);
137 glDisableClientState (GL_COLOR_ARRAY
);
138 glBindBuffer (GL_ARRAY_BUFFER
, 0);
142 CAMLprim value
ml_skin_init (value geom_v
)
145 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
146 State
*s
= &glob_state
;
155 vertexa_v
= Field (geom_v
, 0);
156 normala_v
= Field (geom_v
, 1);
157 uva_v
= Field (geom_v
, 2);
158 skin_v
= Field (geom_v
, 3);
159 colors_v
= Field (geom_v
, 4);
161 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
162 CAMLreturn (Val_unit
);
165 static void translate (State
*s
, float *vdst
, float *ndst
)
169 float *vsrc
= s
->ptrs
[V_IDX
];
170 float *nsrc
= s
->ptrs
[N_IDX
];
171 struct skin
*skin
= s
->skin
;
173 for (i
= 0; i
< s
->num_vertices
; ++i
,
174 vsrc
+= 3, nsrc
+= 3, vdst
+= 3, ndst
+= 3, ++skin
)
178 float v
[4] A16
= {0,0,0,0}, n
[4] A16
= {0,0,0,0};
179 float v0
[4] A16
, v1
[4] A16
, m
[16] A16
, n1
[4];
184 float v
[3] = {0,0,0}, n
[3] = {0,0,0}, v0
[3], v1
[3], w
, m
[12];
188 for (j
= 0; j
< skin
->num_bones
; ++j
) {
189 w
= skin
->weights
[j
];
190 b
= &s
->bones
[skin
->boneindices
[j
]];
193 vsub (v0
, vsrc
, b
->mv
);
194 mapply_to_vector (v1
, b
->im
, v0
);
196 mscale (m
, b
->am
, w
);
197 mapply_to_point (v0
, m
, v1
);
200 mapply_to_vector (v0
, b
->im
, n1
);
201 mapply_to_vector (v1
, m
, v0
);
206 if (z
) vcopy (v
, vsrc
);
213 CAMLprim value
ml_skin_set_skel (value skel_v
)
219 CAMLlocal2 (v
, floats_v
);
220 State
*s
= &glob_state
;
222 s
->num_bones
= Wosize_val (skel_v
);
223 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
224 s
->bones
= b
= simd_alloc (16, size
);
234 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
235 v
= Field (skel_v
, i
);
236 floats_v
= Field (v
, 1);
238 b
->parent
= Int_val (Field (v
, 0)) + 1;
240 b
->v
[0] = Double_field (floats_v
, 1);
241 b
->v
[1] = Double_field (floats_v
, 2);
242 b
->v
[2] = Double_field (floats_v
, 3);
244 b
->q
[0] = Double_field (floats_v
, 5);
245 b
->q
[1] = Double_field (floats_v
, 6);
246 b
->q
[2] = Double_field (floats_v
, 7);
247 b
->q
[3] = Double_field (floats_v
, 8);
251 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
252 float v
[3], q
[4], z
[3] = {0,0,0};
253 struct bone
*parent
= &s
->bones
[b
->parent
];
255 qapply (v
, parent
->mq
, b
->v
);
256 qcompose (b
->mq
, b
->q
, parent
->mq
);
257 vadd (b
->mv
, v
, parent
->mv
);
259 qconjugate (q
, b
->mq
);
260 q2matrix (b
->im
, q
, z
);
263 CAMLreturn (Val_unit
);
266 CAMLprim value
ml_skin_set_anim (value anim_v
)
270 CAMLlocal1 (floats_v
);
271 State
*s
= &glob_state
;
272 struct bone
*b
= s
->bones
+ 1;
274 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
275 floats_v
= Field (anim_v
, i
);
276 b
->aq
[0] = Double_field (floats_v
, 0);
277 b
->aq
[1] = Double_field (floats_v
, 1);
278 b
->aq
[2] = Double_field (floats_v
, 2);
279 b
->aq
[3] = Double_field (floats_v
, 3);
283 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
285 struct bone
*parent
= &s
->bones
[b
->parent
];
287 qapply (v
, parent
->amq
, b
->v
);
288 qcompose (b
->amq
, b
->aq
, parent
->amq
);
289 vadd (b
->amv
, v
, parent
->amv
);
291 q2matrix (b
->am
, b
->amq
, b
->amv
);
294 CAMLreturn (Val_unit
);
297 CAMLprim value
ml_skin_anim (value unit_v
)
301 float *vdst
, *vsrc
, *ndst
, *nsrc
;
302 State
*s
= &glob_state
;
304 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
305 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
307 fprintf (stderr
, "glMapBuffer for vertices failed\n");
311 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
312 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
314 fprintf (stderr
, "glMapBuffer for normals failed\n");
318 vsrc
= s
->ptrs
[V_IDX
];
319 nsrc
= s
->ptrs
[N_IDX
];
321 translate (s
, vdst
, ndst
);
323 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
324 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
325 if (ret
== GL_FALSE
) {
326 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
330 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
331 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
332 if (ret
== GL_FALSE
) {
333 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
337 CAMLreturn (Val_unit
);