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
;
150 glEnableClientState (GL_VERTEX_ARRAY
);
151 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
152 glVertexPointer (3, GL_FLOAT
, 0, NULL
);
154 glEnableClientState (GL_NORMAL_ARRAY
);
155 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
156 glNormalPointer (GL_FLOAT
, 0, NULL
);
158 glEnableClientState (GL_TEXTURE_COORD_ARRAY
);
159 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[UV_IDX
]);
160 glTexCoordPointer (2, GL_FLOAT
, 0, NULL
);
162 glEnableClientState (GL_COLOR_ARRAY
);
163 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[C_IDX
]);
164 glColorPointer (4, GL_UNSIGNED_BYTE
, 0, NULL
);
169 CAMLprim value
ml_skin_draw_end (value uint_v
)
171 glDisableClientState (GL_VERTEX_ARRAY
);
172 glDisableClientState (GL_NORMAL_ARRAY
);
173 glDisableClientState (GL_TEXTURE_COORD_ARRAY
);
174 glDisableClientState (GL_COLOR_ARRAY
);
175 glBindBuffer (GL_ARRAY_BUFFER
, 0);
178 glDisable (GL_TEXTURE_2D
);
179 glDisable (GL_LIGHTING
);
180 glColor3f (1.0, 0.0, 0.0);
181 glDisable (GL_DEPTH_TEST
);
187 State
*s
= &glob_state
;
188 struct bone
*b
= s
->bones
+ 1;
190 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
191 struct bone
*p
= &s
->bones
[b
->parent
];
193 glVertex3fv (p
->amv
);
194 glVertex3fv (b
->amv
);
202 CAMLprim value
ml_skin_init (value geom_v
)
205 CAMLlocal5 (vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
206 State
*s
= &glob_state
;
215 vertexa_v
= Field (geom_v
, 0);
216 normala_v
= Field (geom_v
, 1);
217 uva_v
= Field (geom_v
, 2);
218 skin_v
= Field (geom_v
, 3);
219 colors_v
= Field (geom_v
, 4);
221 skin_init (s
, vertexa_v
, normala_v
, uva_v
, skin_v
, colors_v
);
222 CAMLreturn (Val_unit
);
225 static void translate (State
*s
, float *dst
)
229 float *curvert
= s
->ptrs
[V_IDX
];
230 struct skin
*skin
= s
->skin
;
232 for (i
= 0; i
< s
->num_vertices
; ++i
, curvert
+= 3, dst
+= 3, ++skin
)
234 float v
[3] = {0,0,0}, v0
[3], v1
[3], v2
[3], w
, m
[12];
236 for (j
= 0; j
< skin
->num_bones
; ++j
) {
237 w
= skin
->weights
[j
] + 0.000011;
238 b
= &s
->bones
[skin
->boneindices
[j
]];
240 vsub (v0
, curvert
, b
->mv
);
241 mapply_to_vector (v1
, b
->im
, v0
);
243 mscale (m
, b
->am
, w
);
244 mapply_to_point (v2
, m
, v1
);
253 CAMLprim value
ml_skin_set_skel (value skel_v
)
259 CAMLlocal2 (v
, floats_v
);
260 State
*s
= &glob_state
;
262 s
->num_bones
= Wosize_val (skel_v
);
263 size
= (s
->num_bones
+ 1) * sizeof (struct bone
);
264 s
->bones
= b
= stat_alloc (size
);
274 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
275 v
= Field (skel_v
, i
);
276 floats_v
= Field (v
, 1);
278 b
->parent
= Int_val (Field (v
, 0)) + 1;
280 b
->v
[0] = Double_field (floats_v
, 1);
281 b
->v
[1] = Double_field (floats_v
, 2);
282 b
->v
[2] = Double_field (floats_v
, 3);
284 b
->q
[0] = Double_field (floats_v
, 5);
285 b
->q
[1] = Double_field (floats_v
, 6);
286 b
->q
[2] = Double_field (floats_v
, 7);
287 b
->q
[3] = Double_field (floats_v
, 8);
291 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
292 float v
[3], q
[4], q1
[4], z
[3] = {0,0,0};
293 struct bone
*parent
= &s
->bones
[b
->parent
];
295 qapply (v
, parent
->mq
, b
->v
);
296 qcompose (b
->mq
, b
->q
, parent
->mq
);
297 vadd (b
->mv
, v
, parent
->mv
);
299 qconjugate (q
, b
->mq
);
300 qscale (q1
, q
, 1.0 / qmagnitude (q
));
301 q2matrix (b
->im
, q1
, z
);
304 CAMLreturn (Val_unit
);
307 CAMLprim value
ml_skin_set_anim (value anim_v
)
311 CAMLlocal1 (floats_v
);
312 State
*s
= &glob_state
;
313 struct bone
*b
= s
->bones
+ 1;
315 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
316 floats_v
= Field (anim_v
, i
);
317 b
->aq
[0] = Double_field (floats_v
, 0);
318 b
->aq
[1] = Double_field (floats_v
, 1);
319 b
->aq
[2] = Double_field (floats_v
, 2);
320 b
->aq
[3] = Double_field (floats_v
, 3);
324 for (i
= 0; i
< s
->num_bones
; ++i
, ++b
) {
326 struct bone
*parent
= &s
->bones
[b
->parent
];
328 qapply (v
, parent
->amq
, b
->v
);
329 qcompose (b
->amq
, b
->aq
, parent
->amq
);
330 vadd (b
->amv
, v
, parent
->amv
);
332 q2matrix (b
->am
, b
->amq
, b
->amv
);
335 CAMLreturn (Val_unit
);
338 CAMLprim value
ml_skin_anim (value unit_v
)
342 float *vdst
, *vsrc
, *ndst
, *nsrc
;
343 State
*s
= &glob_state
;
345 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
346 vdst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
348 fprintf (stderr
, "glMapBuffer for vertices failed\n");
352 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
353 ndst
= glMapBuffer (GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
355 fprintf (stderr
, "glMapBuffer for normals failed\n");
359 vsrc
= s
->ptrs
[V_IDX
];
360 nsrc
= s
->ptrs
[N_IDX
];
366 for (i
= 0; i
< s
->num_vertices
; ++i
) {
368 struct bone
*bone
, *parent
;
369 float v
[3], v1
[3], *v2
;
373 bone
= &s
->bones
[skin
->boneindices
[0]];
374 parent
= &s
->bones
[bone
->parent
];
386 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[V_IDX
]);
387 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
388 if (ret
== GL_FALSE
) {
389 fprintf (stderr
, "glUnmapBuffer for vertices failed\n");
393 glBindBuffer (GL_ARRAY_BUFFER
, s
->bufid
[N_IDX
]);
394 ret
= glUnmapBuffer (GL_ARRAY_BUFFER
);
395 if (ret
== GL_FALSE
) {
396 fprintf (stderr
, "glUnmapBuffer for normals failed\n");
400 CAMLreturn (Val_unit
);