1 #define GL_GLEXT_PROTOTYPES
3 #define WIN32_LEAN_AND_MEAN
12 #ifndef GL_VERSION_1_5
13 #define GL_ARRAY_BUFFER 0x8892
14 #define GL_DYNAMIC_DRAW 0x88E8
15 #define GL_STATIC_DRAW 0x88E4
16 #define GL_WRITE_ONLY 0x88B9
18 #define APIENTRYP APIENTRY *
20 typedef ptrdiff_t GLintptr
;
21 typedef ptrdiff_t GLsizeiptr
;
22 typedef void (APIENTRYP PFNGLBINDBUFFERPROC
) (GLenum target
, GLuint buffer
);
23 typedef void (APIENTRYP PFNGLGENBUFFERSPROC
) (GLsizei n
, GLuint
*buffers
);
24 typedef void (APIENTRYP PFNGLBUFFERDATAPROC
) (GLenum target
, GLsizeiptr size
, const GLvoid
*data
, GLenum usage
);
25 typedef GLvoid
* (APIENTRYP PFNGLMAPBUFFERPROC
) (GLenum target
, GLenum access
);
26 typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC
) (GLenum target
);
27 static PFNGLBINDBUFFERPROC glBindBuffer
;
28 static PFNGLGENBUFFERSPROC glGenBuffers
;
29 static PFNGLBUFFERDATAPROC glBufferData
;
30 static PFNGLMAPBUFFERPROC glMapBuffer
;
31 static PFNGLUNMAPBUFFERPROC glUnmapBuffer
;
32 #define GETPA(name) for (;;) { \
33 *(PROC *) &gl##name = wglGetProcAddress ("gl" # name); \
35 fprintf (stderr, "could not get address of gl"#name"\n"); \
36 exit (EXIT_FAILURE); \
47 #include <caml/fail.h>
48 #include <caml/alloc.h>
49 #include <caml/memory.h>
53 enum {V_IDX
, N_IDX
, UV_IDX
, C_IDX
, COUNT
};
86 static State glob_state
;
88 static void skin_init (State
*s
, value vertexa_v
, value normala_v
,
89 value uva_v
, value skin_v
, value colors_v
)
95 s
->num_vertices
= Wosize_val (vertexa_v
) / (Double_wosize
* 3);
97 glGenBuffers (COUNT
, s
->bufid
);
99 size
= s
->num_vertices
* sizeof (GLfloat
) * 3;
100 p
= s
->ptrs
[V_IDX
] = stat_alloc (size
);
101 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
102 p
[i
] = Double_field (vertexa_v
, i
);
104 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
105 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
107 p
= s
->ptrs
[N_IDX
] = stat_alloc (size
);
108 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
109 p
[i
] = Double_field (normala_v
, i
);
111 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
112 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
114 size
= s
->num_vertices
* sizeof (GLfloat
) * 2;
115 p
= s
->ptrs
[UV_IDX
] = stat_alloc (size
);
116 for (i
= 0; i
< s
->num_vertices
* 2; ++i
) {
117 p
[i
] = Double_field (uva_v
, i
);
119 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
120 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_STATIC_DRAW
);
123 size
= s
->num_vertices
* 4;
124 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
125 glBufferData (GL_ARRAY_BUFFER
, size
, String_val (colors_v
), GL_STATIC_DRAW
);
127 s
->skin
= skin
= stat_alloc (s
->num_vertices
* sizeof (struct skin
));
128 for (i
= 0; i
< s
->num_vertices
; ++i
) {
132 v
= Field (skin_v
, i
);
133 skin
[i
].num_bones
= Int_val (Field (v
, 3));
135 for (j
= 0; j
< skin
[i
].num_bones
; ++j
) {
138 val
= Double_val (Bp_val (Field (v
, j
)));
139 skin
[i
].boneindices
[j
] = (int) val
;
140 skin
[i
].weights
[j
] = val
- skin
[i
].boneindices
[j
];
141 skin
[i
].boneindices
[j
] += 1;
146 CAMLprim value
ml_skin_draw_begin (value unit_v
)
148 State
*s
= &glob_state
;
151 glEnableClientState (GL_VERTEX_ARRAY
);
152 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
153 glVertexPointer (3, GL_FLOAT
, 0, NULL
);
155 glEnableClientState (GL_NORMAL_ARRAY
);
156 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
157 glNormalPointer (GL_FLOAT
, 0, NULL
);
159 glEnableClientState (GL_TEXTURE_COORD_ARRAY
);
160 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
161 glTexCoordPointer (2, GL_FLOAT
, 0, NULL
);
163 glEnableClientState (GL_COLOR_ARRAY
);
164 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
165 glColorPointer (4, GL_UNSIGNED_BYTE
, 0, NULL
);
170 CAMLprim value
ml_skin_draw_end (value unit_v
)
173 glDisableClientState (GL_VERTEX_ARRAY
);
174 glDisableClientState (GL_NORMAL_ARRAY
);
175 glDisableClientState (GL_TEXTURE_COORD_ARRAY
);
176 glDisableClientState (GL_COLOR_ARRAY
);
177 glBindBuffer (GL_ARRAY_BUFFER
, 0);
180 glDisable (GL_TEXTURE_2D
);
181 glDisable (GL_LIGHTING
);
182 glColor3f (1.0, 0.0, 0.0);
183 glDisable (GL_DEPTH_TEST
);
189 State
*s
= &glob_state
;
190 struct bone
*b
= s
->bones
+ 1;
192 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
193 struct bone
*p
= &s
->bones
[b
->parent
];
195 glVertex3fv (p
->amv
);
196 glVertex3fv (b
->amv
);
204 CAMLprim value
ml_skin_init (value geom_v
)
207 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
208 State
*s
= &glob_state
;
217 vertexa_v
= Field (geom_v
, 0);
218 normala_v
= Field (geom_v
, 1);
219 uva_v
= Field (geom_v
, 2);
220 skin_v
= Field (geom_v
, 3);
221 colors_v
= Field (geom_v
, 4);
223 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
224 CAMLreturn (Val_unit
);
227 static void translate (State
*s
, float *vdst
, float *ndst
)
231 float *vsrc
= s
->ptrs
[V_IDX
];
232 float *nsrc
= s
->ptrs
[N_IDX
];
233 struct skin
*skin
= s
->skin
;
235 for (i
= 0; i
< s
->num_vertices
; ++i
,
236 vsrc
+= 3, nsrc
+= 3, vdst
+= 3, ndst
+= 3, ++skin
)
238 float v
[3] = {0,0,0}, n
[3] = {0,0,0}, v0
[3], v1
[3], v2
[3], w
, m
[12];
240 for (j
= 0; j
< skin
->num_bones
; ++j
) {
241 w
= skin
->weights
[j
] + 0.000011;
242 b
= &s
->bones
[skin
->boneindices
[j
]];
244 vsub (v0
, vsrc
, b
->mv
);
245 mapply_to_vector (v1
, b
->im
, v0
);
247 mscale (m
, b
->am
, w
);
248 mapply_to_point (v2
, m
, v1
);
251 mapply_to_vector (v0
, b
->im
, nsrc
);
252 mapply_to_vector (v1
, m
, v0
);
262 CAMLprim value
ml_skin_set_skel (value skel_v
)
268 CAMLlocal2 (v
, floats_v
);
269 State
*s
= &glob_state
;
271 s
->num_bones
= Wosize_val (skel_v
);
272 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
273 s
->bones
= b
= stat_alloc (size
);
283 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
284 v
= Field (skel_v
, i
);
285 floats_v
= Field (v
, 1);
287 b
->parent
= Int_val (Field (v
, 0)) + 1;
289 b
->v
[0] = Double_field (floats_v
, 1);
290 b
->v
[1] = Double_field (floats_v
, 2);
291 b
->v
[2] = Double_field (floats_v
, 3);
293 b
->q
[0] = Double_field (floats_v
, 5);
294 b
->q
[1] = Double_field (floats_v
, 6);
295 b
->q
[2] = Double_field (floats_v
, 7);
296 b
->q
[3] = Double_field (floats_v
, 8);
300 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
301 float v
[3], q
[4], q1
[4], z
[3] = {0,0,0};
302 struct bone
*parent
= &s
->bones
[b
->parent
];
304 qapply (v
, parent
->mq
, b
->v
);
305 qcompose (b
->mq
, b
->q
, parent
->mq
);
306 vadd (b
->mv
, v
, parent
->mv
);
308 qconjugate (q
, b
->mq
);
309 qscale (q1
, q
, 1.0 / qmagnitude (q
));
310 q2matrix (b
->im
, q1
, z
);
313 CAMLreturn (Val_unit
);
316 CAMLprim value
ml_skin_set_anim (value anim_v
)
320 CAMLlocal1 (floats_v
);
321 State
*s
= &glob_state
;
322 struct bone
*b
= s
->bones
+ 1;
324 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
325 floats_v
= Field (anim_v
, i
);
326 b
->aq
[0] = Double_field (floats_v
, 0);
327 b
->aq
[1] = Double_field (floats_v
, 1);
328 b
->aq
[2] = Double_field (floats_v
, 2);
329 b
->aq
[3] = Double_field (floats_v
, 3);
333 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
335 struct bone
*parent
= &s
->bones
[b
->parent
];
337 qapply (v
, parent
->amq
, b
->v
);
338 qcompose (b
->amq
, b
->aq
, parent
->amq
);
339 vadd (b
->amv
, v
, parent
->amv
);
341 q2matrix (b
->am
, b
->amq
, b
->amv
);
344 CAMLreturn (Val_unit
);
347 CAMLprim value
ml_skin_anim (value unit_v
)
351 float *vdst
, *vsrc
, *ndst
, *nsrc
;
352 State
*s
= &glob_state
;
354 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
355 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
357 fprintf (stderr
, "glMapBuffer for vertices failed\n");
361 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
362 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
364 fprintf (stderr
, "glMapBuffer for normals failed\n");
368 vsrc
= s
->ptrs
[V_IDX
];
369 nsrc
= s
->ptrs
[N_IDX
];
371 translate (s
, vdst
, ndst
);
375 for (i
= 0; i
< s
->num_vertices
; ++i
) {
377 struct bone
*bone
, *parent
;
378 float v
[3], v1
[3], *v2
;
382 bone
= &s
->bones
[skin
->boneindices
[0]];
383 parent
= &s
->bones
[bone
->parent
];
395 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
396 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
397 if (ret
== GL_FALSE
) {
398 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
402 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
403 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
404 if (ret
== GL_FALSE
) {
405 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
409 CAMLreturn (Val_unit
);