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 *dst
)
231 float *curvert
= s
->ptrs
[V_IDX
];
232 struct skin
*skin
= s
->skin
;
234 for (i
= 0; i
< s
->num_vertices
; ++i
, curvert
+= 3, dst
+= 3, ++skin
)
236 float v
[3] = {0,0,0}, v0
[3], v1
[3], v2
[3], w
, m
[12];
238 for (j
= 0; j
< skin
->num_bones
; ++j
) {
239 w
= skin
->weights
[j
] + 0.000011;
240 b
= &s
->bones
[skin
->boneindices
[j
]];
242 vsub (v0
, curvert
, b
->mv
);
243 mapply_to_vector (v1
, b
->im
, v0
);
245 mscale (m
, b
->am
, w
);
246 mapply_to_point (v2
, m
, v1
);
255 CAMLprim value
ml_skin_set_skel (value skel_v
)
261 CAMLlocal2 (v
, floats_v
);
262 State
*s
= &glob_state
;
264 s
->num_bones
= Wosize_val (skel_v
);
265 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
266 s
->bones
= b
= stat_alloc (size
);
276 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
277 v
= Field (skel_v
, i
);
278 floats_v
= Field (v
, 1);
280 b
->parent
= Int_val (Field (v
, 0)) + 1;
282 b
->v
[0] = Double_field (floats_v
, 1);
283 b
->v
[1] = Double_field (floats_v
, 2);
284 b
->v
[2] = Double_field (floats_v
, 3);
286 b
->q
[0] = Double_field (floats_v
, 5);
287 b
->q
[1] = Double_field (floats_v
, 6);
288 b
->q
[2] = Double_field (floats_v
, 7);
289 b
->q
[3] = Double_field (floats_v
, 8);
293 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
294 float v
[3], q
[4], q1
[4], z
[3] = {0,0,0};
295 struct bone
*parent
= &s
->bones
[b
->parent
];
297 qapply (v
, parent
->mq
, b
->v
);
298 qcompose (b
->mq
, b
->q
, parent
->mq
);
299 vadd (b
->mv
, v
, parent
->mv
);
301 qconjugate (q
, b
->mq
);
302 qscale (q1
, q
, 1.0 / qmagnitude (q
));
303 q2matrix (b
->im
, q1
, z
);
306 CAMLreturn (Val_unit
);
309 CAMLprim value
ml_skin_set_anim (value anim_v
)
313 CAMLlocal1 (floats_v
);
314 State
*s
= &glob_state
;
315 struct bone
*b
= s
->bones
+ 1;
317 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
318 floats_v
= Field (anim_v
, i
);
319 b
->aq
[0] = Double_field (floats_v
, 0);
320 b
->aq
[1] = Double_field (floats_v
, 1);
321 b
->aq
[2] = Double_field (floats_v
, 2);
322 b
->aq
[3] = Double_field (floats_v
, 3);
326 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
328 struct bone
*parent
= &s
->bones
[b
->parent
];
330 qapply (v
, parent
->amq
, b
->v
);
331 qcompose (b
->amq
, b
->aq
, parent
->amq
);
332 vadd (b
->amv
, v
, parent
->amv
);
334 q2matrix (b
->am
, b
->amq
, b
->amv
);
337 CAMLreturn (Val_unit
);
340 CAMLprim value
ml_skin_anim (value unit_v
)
344 float *vdst
, *vsrc
, *ndst
, *nsrc
;
345 State
*s
= &glob_state
;
347 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
348 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
350 fprintf (stderr
, "glMapBuffer for vertices failed\n");
354 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
355 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
357 fprintf (stderr
, "glMapBuffer for normals failed\n");
361 vsrc
= s
->ptrs
[V_IDX
];
362 nsrc
= s
->ptrs
[N_IDX
];
368 for (i
= 0; i
< s
->num_vertices
; ++i
) {
370 struct bone
*bone
, *parent
;
371 float v
[3], v1
[3], *v2
;
375 bone
= &s
->bones
[skin
->boneindices
[0]];
376 parent
= &s
->bones
[bone
->parent
];
388 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
389 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
390 if (ret
== GL_FALSE
) {
391 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
395 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
396 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
397 if (ret
== GL_FALSE
) {
398 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
402 CAMLreturn (Val_unit
);