1 #define GL_GLEXT_PROTOTYPES
3 #define WIN32_LEAN_AND_MEAN
9 #define GL_ARRAY_BUFFER 0x8892
10 #define GL_DYNAMIC_DRAW 0x88E8
11 #define GL_STATIC_DRAW 0x88E4
12 #define GL_WRITE_ONLY 0x88B9
14 #define APIENTRYP APIENTRY *
15 typedef ptrdiff_t GLintptr
;
16 typedef ptrdiff_t GLsizeiptr
;
18 typedef void (APIENTRYP PFNGLBINDBUFFERPROC
) (GLenum target
, GLuint buffer
);
19 typedef void (APIENTRYP PFNGLGENBUFFERSPROC
) (GLsizei n
, GLuint
*buffers
);
20 typedef void (APIENTRYP PFNGLBUFFERDATAPROC
) (GLenum target
, GLsizeiptr size
, const GLvoid
*data
, GLenum usage
);
21 typedef GLvoid
* (APIENTRYP PFNGLMAPBUFFERPROC
) (GLenum target
, GLenum access
);
22 typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC
) (GLenum target
);
23 static PFNGLBINDBUFFERPROC glBindBuffer
;
24 static PFNGLGENBUFFERSPROC glGenBuffers
;
25 static PFNGLBUFFERDATAPROC glBufferData
;
26 static PFNGLMAPBUFFERPROC glMapBuffer
;
27 static PFNGLUNMAPBUFFERPROC glUnmapBuffer
;
35 #include <caml/fail.h>
36 #include <caml/alloc.h>
37 #include <caml/memory.h>
41 enum {V_IDX
, N_IDX
, UV_IDX
, COUNT
};
74 static State glob_state
;
76 static void skin_init (State
*s
, value vertexa_v
, value normala_v
,
77 value uva_v
, value skin_v
)
83 s
->num_vertices
= Wosize_val (vertexa_v
) / (Double_wosize
* 3);
85 glGenBuffers (COUNT
, s
->bufid
);
87 size
= s
->num_vertices
* sizeof (GLfloat
) * 3;
88 p
= s
->ptrs
[V_IDX
] = stat_alloc (size
);
89 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
90 p
[i
] = Double_field (vertexa_v
, i
);
92 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
93 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
95 p
= s
->ptrs
[N_IDX
] = stat_alloc (size
);
96 for (i
= 0; i
< s
->num_vertices
* 3; ++i
) {
97 p
[i
] = Double_field (normala_v
, i
);
99 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
100 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_DYNAMIC_DRAW
);
102 size
= s
->num_vertices
* sizeof (GLfloat
) * 2;
103 p
= s
->ptrs
[UV_IDX
] = stat_alloc (size
);
104 for (i
= 0; i
< s
->num_vertices
* 2; ++i
) {
105 p
[i
] = Double_field (uva_v
, i
);
107 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
108 glBufferData (GL_ARRAY_BUFFER
, size
, p
, GL_STATIC_DRAW
);
111 s
->skin
= skin
= stat_alloc (s
->num_vertices
* sizeof (struct skin
));
112 for (i
= 0; i
< s
->num_vertices
; ++i
) {
116 v
= Field (skin_v
, i
);
117 skin
[i
].num_bones
= Int_val (Field (v
, 3));
119 for (j
= 0; j
< skin
[i
].num_bones
; ++j
) {
122 val
= Double_val (Bp_val (Field (v
, j
)));
123 skin
[i
].boneindices
[j
] = (int) val
;
124 skin
[i
].weights
[j
] = val
- skin
[i
].boneindices
[j
];
125 skin
[i
].boneindices
[j
] += 1;
130 CAMLprim value
ml_skin_draw_begin (value unit_v
)
132 State
*s
= &glob_state
;
134 glEnableClientState (GL_VERTEX_ARRAY
);
135 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
136 glVertexPointer (3, GL_FLOAT
, 0, NULL
);
138 glEnableClientState (GL_NORMAL_ARRAY
);
139 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
140 glNormalPointer (GL_FLOAT
, 0, NULL
);
142 glEnableClientState (GL_TEXTURE_COORD_ARRAY
);
143 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
144 glTexCoordPointer (2, GL_FLOAT
, 0, NULL
);
148 CAMLprim value
ml_skin_draw_end (value uint_v
)
150 glDisableClientState (GL_VERTEX_ARRAY
);
151 glDisableClientState (GL_NORMAL_ARRAY
);
152 glDisableClientState (GL_TEXTURE_COORD_ARRAY
);
153 glBindBuffer (GL_ARRAY_BUFFER
, 0);
156 glDisable (GL_TEXTURE_2D
);
157 glDisable (GL_LIGHTING
);
158 glColor3f (1.0, 0.0, 0.0);
159 glDisable (GL_DEPTH_TEST
);
165 State
*s
= &glob_state
;
166 struct bone
*b
= s
->bones
+ 1;
168 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
169 struct bone
*p
= &s
->bones
[b
->parent
];
171 glVertex3fv (p
->amv
);
172 glVertex3fv (b
->amv
);
180 CAMLprim value
ml_skin_init (value geom_v
)
183 CAMLlocal4 (vertexa_v
, normala_v
, uva_v
, skin_v
);
184 State
*s
= &glob_state
;
187 *(PROC
*) &glBindBuffer
= wglGetProcAddress ("glBindBuffer");
188 *(PROC
*) &glGenBuffers
= wglGetProcAddress ("glGenBuffers");
189 *(PROC
*) &glBufferData
= wglGetProcAddress ("glBufferData");
190 *(PROC
*) &glMapBuffer
= wglGetProcAddress ("glMapBuffer");
191 *(PROC
*) &glUnmapBuffer
= wglGetProcAddress ("glUnmapBuffer");
193 vertexa_v
= Field (geom_v
, 0);
194 normala_v
= Field (geom_v
, 1);
195 uva_v
= Field (geom_v
, 2);
196 skin_v
= Field (geom_v
, 3);
198 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
);
199 CAMLreturn (Val_unit
);
202 static void translate (State
*s
, float *dst
)
206 float *curvert
= s
->ptrs
[V_IDX
];
207 struct skin
*skin
= s
->skin
;
209 for (i
= 0; i
< s
->num_vertices
; ++i
, curvert
+= 3, dst
+= 3, ++skin
)
211 float v
[3] = {0,0,0}, v0
[3], v1
[3], v2
[3], w
, m
[12];
213 for (j
= 0; j
< skin
->num_bones
; ++j
) {
214 w
= skin
->weights
[j
] + 0.000011;
215 b
= &s
->bones
[skin
->boneindices
[j
]];
217 vsub (v0
, curvert
, b
->mv
);
218 mapply_to_vector (v1
, b
->im
, v0
);
220 mscale (m
, b
->am
, w
);
221 mapply_to_point (v2
, m
, v1
);
230 CAMLprim value
ml_skin_set_skel (value skel_v
)
236 CAMLlocal2 (v
, floats_v
);
237 State
*s
= &glob_state
;
239 s
->num_bones
= Wosize_val (skel_v
);
240 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
241 s
->bones
= b
= stat_alloc (size
);
251 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
252 v
= Field (skel_v
, i
);
253 floats_v
= Field (v
, 1);
255 b
->parent
= Int_val (Field (v
, 0)) + 1;
257 b
->v
[0] = Double_field (floats_v
, 1);
258 b
->v
[1] = Double_field (floats_v
, 2);
259 b
->v
[2] = Double_field (floats_v
, 3);
261 b
->q
[0] = Double_field (floats_v
, 5);
262 b
->q
[1] = Double_field (floats_v
, 6);
263 b
->q
[2] = Double_field (floats_v
, 7);
264 b
->q
[3] = Double_field (floats_v
, 8);
268 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
269 float v
[3], q
[4], q1
[4], z
[3] = {0,0,0};
270 struct bone
*parent
= &s
->bones
[b
->parent
];
272 qapply (v
, parent
->mq
, b
->v
);
273 qcompose (b
->mq
, b
->q
, parent
->mq
);
274 vadd (b
->mv
, v
, parent
->mv
);
276 qconjugate (q
, b
->mq
);
277 qscale (q1
, q
, 1.0 / qmagnitude (q
));
278 q2matrix (b
->im
, q1
, z
);
281 CAMLreturn (Val_unit
);
284 CAMLprim value
ml_skin_set_anim (value anim_v
)
288 CAMLlocal1 (floats_v
);
289 State
*s
= &glob_state
;
290 struct bone
*b
= s
->bones
+ 1;
292 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
293 floats_v
= Field (anim_v
, i
);
294 b
->aq
[0] = Double_field (floats_v
, 0);
295 b
->aq
[1] = Double_field (floats_v
, 1);
296 b
->aq
[2] = Double_field (floats_v
, 2);
297 b
->aq
[3] = Double_field (floats_v
, 3);
301 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
303 struct bone
*parent
= &s
->bones
[b
->parent
];
305 qapply (v
, parent
->amq
, b
->v
);
306 qcompose (b
->amq
, b
->aq
, parent
->amq
);
307 vadd (b
->amv
, v
, parent
->amv
);
309 q2matrix (b
->am
, b
->amq
, b
->amv
);
312 CAMLreturn (Val_unit
);
315 CAMLprim value
ml_skin_anim (value unit_v
)
319 float *vdst
, *vsrc
, *ndst
, *nsrc
;
320 State
*s
= &glob_state
;
322 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
323 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
325 fprintf (stderr
, "glMapBuffer for vertices failed\n");
329 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
330 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
332 fprintf (stderr
, "glMapBuffer for normals failed\n");
336 vsrc
= s
->ptrs
[V_IDX
];
337 nsrc
= s
->ptrs
[N_IDX
];
343 for (i
= 0; i
< s
->num_vertices
; ++i
) {
345 struct bone
*bone
, *parent
;
346 float v
[3], v1
[3], *v2
;
350 bone
= &s
->bones
[skin
->boneindices
[0]];
351 parent
= &s
->bones
[bone
->parent
];
363 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
364 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
365 if (ret
== GL_FALSE
) {
366 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
370 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
371 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
372 if (ret
== GL_FALSE
) {
373 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
377 CAMLreturn (Val_unit
);