|
1 /* |
|
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: SkinnedMesh implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /*! |
|
20 * \internal |
|
21 * \file |
|
22 * \brief SkinnedMesh implementation |
|
23 */ |
|
24 |
|
25 #ifndef M3G_CORE_INCLUDE |
|
26 # error included by m3g_core.c; do not compile separately. |
|
27 #endif |
|
28 |
|
29 #include "m3g_skinnedmesh.h" |
|
30 #include "m3g_memory.h" |
|
31 #include "m3g_animationtrack.h" |
|
32 |
|
33 /*---------------------------------------------------------------------- |
|
34 * Internal structures |
|
35 *--------------------------------------------------------------------*/ |
|
36 |
|
37 struct BoneRecord |
|
38 { |
|
39 Node *node; |
|
40 |
|
41 /*! \internal \brief "At-rest" transformation from skinned mesh to bone */ |
|
42 Matrix toBone; |
|
43 |
|
44 /*! \internal \brief Cached animated transformation for positions */ |
|
45 M3Gshort baseMatrix[9]; |
|
46 M3Gshort posVec[3]; |
|
47 M3Gshort baseExp, posExp, maxExp; |
|
48 |
|
49 /*! \internal \brief Cached animated transformation for normals */ |
|
50 M3Gshort normalMatrix[9]; |
|
51 }; |
|
52 |
|
53 /*---------------------------------------------------------------------- |
|
54 * Internal functions |
|
55 *--------------------------------------------------------------------*/ |
|
56 |
|
57 /*! |
|
58 * \internal |
|
59 * \brief Destroys this SkinnedMesh object. |
|
60 * |
|
61 * \param obj SkinnedMesh object |
|
62 */ |
|
63 static void m3gDestroySkinnedMesh(Object *obj) |
|
64 { |
|
65 SkinnedMesh *mesh = (SkinnedMesh *) obj; |
|
66 M3G_VALIDATE_OBJECT(mesh); |
|
67 { |
|
68 int i; |
|
69 Interface *m3g = M3G_INTERFACE(mesh); |
|
70 |
|
71 m3gDeleteVertexBuffer(mesh->morphedVB); |
|
72 |
|
73 for (i = 0; i < mesh->bonesPerVertex; ++i) { |
|
74 m3gFree(m3g, mesh->boneIndices[i]); |
|
75 m3gFree(m3g, mesh->boneWeights[i]); |
|
76 m3gFree(m3g, mesh->normalizedWeights[i]); |
|
77 } |
|
78 m3gFree(m3g, mesh->weightShifts); |
|
79 |
|
80 for (i = 0; i < m3gArraySize(&mesh->bones); ++i) { |
|
81 m3gFree(m3g, m3gGetArrayElement(&mesh->bones, i)); |
|
82 } |
|
83 m3gDestroyArray(&mesh->bones, m3g); |
|
84 |
|
85 if (mesh->skeleton != NULL) { |
|
86 m3gSetParent((Node*) mesh->skeleton, NULL); |
|
87 M3G_ASSIGN_REF(mesh->skeleton, NULL); |
|
88 } |
|
89 } |
|
90 m3gDestroyMesh(obj); |
|
91 } |
|
92 |
|
93 |
|
94 /*! |
|
95 * \internal |
|
96 * \brief Get a bone index for a given node |
|
97 * |
|
98 * This finds an existing record if the bone has been added |
|
99 * previously, or creates a new one if no record exists yet. |
|
100 * |
|
101 * \note Inline because only called from AddTransform. |
|
102 */ |
|
103 static M3G_INLINE M3Gint m3gBoneIndex(SkinnedMesh *mesh, Node *node) |
|
104 { |
|
105 PointerArray *boneArray = &mesh->bones; |
|
106 const int numBones = m3gArraySize(boneArray); |
|
107 |
|
108 /* First look for an existing record in the array */ |
|
109 { |
|
110 int i; |
|
111 |
|
112 for (i = 0; i < numBones; ++i) { |
|
113 Bone *b = m3gGetArrayElement(boneArray, i); |
|
114 if (b->node == node) { |
|
115 return i; |
|
116 } |
|
117 } |
|
118 } |
|
119 |
|
120 /* Not found; create a new one, append to the array, and set up |
|
121 * the "at-rest" transformation for the bone. Note, however, that |
|
122 * we can only store a maximum of 256 bones with byte indices! */ |
|
123 { |
|
124 Interface *m3g = M3G_INTERFACE(mesh); |
|
125 |
|
126 if (numBones >= 256) { |
|
127 /* Out of available bone indices */ |
|
128 m3gRaiseError(m3g, M3G_OUT_OF_MEMORY); |
|
129 return -1; |
|
130 } |
|
131 else { |
|
132 M3Gint idx; |
|
133 Bone *bone = (Bone*) m3gAllocZ(m3g, sizeof(Bone)); |
|
134 if (!bone || !m3gGetTransformTo((Node*) mesh, node, |
|
135 &bone->toBone)) { |
|
136 m3gFree(m3g, bone); |
|
137 return -1; /* out of memory or singular transform */ |
|
138 } |
|
139 bone->node = node; |
|
140 |
|
141 idx = m3gArrayAppend(boneArray, bone, m3g); |
|
142 if (idx < 0) { |
|
143 m3gFree(m3g, bone); |
|
144 return -1; /* out of memory */ |
|
145 } |
|
146 return idx; |
|
147 } |
|
148 } |
|
149 } |
|
150 |
|
151 /*! |
|
152 * \internal |
|
153 * \brief Reallocate the per-vertex data if necessary. |
|
154 * |
|
155 * \note Inline because only called from AddTransform. |
|
156 */ |
|
157 static M3G_INLINE M3Gbool m3gEnsureVertexCount(SkinnedMesh *mesh, M3Gint count) |
|
158 { |
|
159 /* Reallocate only if vertex count increased */ |
|
160 |
|
161 if (count > mesh->weightedVertexCount) { |
|
162 |
|
163 Interface *m3g = M3G_INTERFACE(mesh); |
|
164 |
|
165 int i; |
|
166 |
|
167 /* Reallocate the weight shift array */ |
|
168 { |
|
169 M3Gubyte *pNew = (M3Gubyte*) m3gAllocZ(m3g, count); |
|
170 if (!pNew) { |
|
171 return M3G_FALSE; |
|
172 } |
|
173 m3gCopy(pNew, mesh->weightShifts, mesh->weightedVertexCount); |
|
174 m3gFree(m3g, mesh->weightShifts); |
|
175 mesh->weightShifts = pNew; |
|
176 } |
|
177 |
|
178 /* Reallocate each of the bone index and weight arrays */ |
|
179 |
|
180 for (i = 0; i < mesh->bonesPerVertex; ++i) { |
|
181 |
|
182 M3Gubyte *pNew; |
|
183 |
|
184 /* Weights */ |
|
185 pNew = (M3Gubyte*) m3gAllocZ(m3g, count); |
|
186 if (!pNew) { |
|
187 return M3G_FALSE; /* out of memory */ |
|
188 } |
|
189 m3gCopy(pNew, mesh->boneWeights[i], mesh->weightedVertexCount); |
|
190 m3gFree(m3g, mesh->boneWeights[i]); |
|
191 mesh->boneWeights[i] = pNew; |
|
192 |
|
193 pNew = (M3Gubyte*) m3gAllocZ(m3g, count); |
|
194 if (!pNew) { |
|
195 return M3G_FALSE; /* out of memory */ |
|
196 } |
|
197 m3gCopy(pNew, mesh->normalizedWeights[i], |
|
198 mesh->weightedVertexCount); |
|
199 m3gFree(m3g, mesh->normalizedWeights[i]); |
|
200 mesh->normalizedWeights[i] = pNew; |
|
201 |
|
202 /* Indices */ |
|
203 pNew = (M3Gubyte*) m3gAllocZ(m3g, count); |
|
204 if (!pNew) { |
|
205 return M3G_FALSE; /* out of memory */ |
|
206 } |
|
207 m3gCopy(pNew, mesh->boneIndices[i], mesh->weightedVertexCount); |
|
208 m3gFree(m3g, mesh->boneIndices[i]); |
|
209 mesh->boneIndices[i] = pNew; |
|
210 } |
|
211 |
|
212 mesh->weightedVertexCount = count; |
|
213 } |
|
214 return M3G_TRUE; |
|
215 } |
|
216 |
|
217 /*! |
|
218 * \internal |
|
219 * \brief Reallocate the per-vertex data if necessary. |
|
220 * |
|
221 * \note Inline because only called from AddTransform. |
|
222 */ |
|
223 static M3G_INLINE M3Gbool m3gEnsureBonesPerVertex(SkinnedMesh *mesh, |
|
224 M3Gint count) |
|
225 { |
|
226 M3G_ASSERT(count <= M3G_MAX_VERTEX_TRANSFORMS); |
|
227 |
|
228 /* Allocate only if per-vertex bone count increased */ |
|
229 |
|
230 if (count > mesh->bonesPerVertex) { |
|
231 |
|
232 Interface *m3g = M3G_INTERFACE(mesh); |
|
233 |
|
234 const M3Gint vertexCount = mesh->weightedVertexCount; |
|
235 M3Gubyte *pNew; |
|
236 |
|
237 int i; |
|
238 |
|
239 /* Allocate new arrays for bone indices and weights until |
|
240 * we're satisfied */ |
|
241 |
|
242 for (i = mesh->bonesPerVertex; i < count; ++i) { |
|
243 pNew = (M3Gubyte*) m3gAllocZ(m3g, vertexCount); |
|
244 if (!pNew) { |
|
245 goto AllocFailed; /* out of memory */ |
|
246 } |
|
247 mesh->boneIndices[i] = pNew; |
|
248 |
|
249 pNew = (M3Gubyte*) m3gAllocZ(m3g, vertexCount); |
|
250 if (!pNew) { |
|
251 goto AllocFailed; /* out of memory */ |
|
252 } |
|
253 mesh->boneWeights[i] = pNew; |
|
254 |
|
255 pNew = (M3Gubyte*) m3gAllocZ(m3g, vertexCount); |
|
256 if (!pNew) { |
|
257 goto AllocFailed; /* out of memory */ |
|
258 } |
|
259 mesh->normalizedWeights[i] = pNew; |
|
260 } |
|
261 |
|
262 mesh->bonesPerVertex = count; |
|
263 return M3G_TRUE; |
|
264 |
|
265 /* In case of failure, clean up to keep the bonesPerVertex |
|
266 * counter in sync with the actual number of arrays |
|
267 * allocated */ |
|
268 |
|
269 AllocFailed: |
|
270 for (i = mesh->bonesPerVertex; i < count; ++i) { |
|
271 m3gFree(m3g, mesh->boneIndices[i]); |
|
272 m3gFree(m3g, mesh->boneWeights[i]); |
|
273 m3gFree(m3g, mesh->normalizedWeights[i]); |
|
274 |
|
275 mesh->boneIndices[i] = NULL; |
|
276 mesh->boneWeights[i] = NULL; |
|
277 mesh->normalizedWeights[i] = NULL; |
|
278 } |
|
279 return M3G_FALSE; |
|
280 } |
|
281 return M3G_TRUE; |
|
282 } |
|
283 |
|
284 /*! |
|
285 * \internal |
|
286 * \brief Add a new bone influence to a vertex |
|
287 * |
|
288 * If the target vertex is already affected by |
|
289 * M3G_MAX_VERTEX_TRANSFORMS bones, the one with the lowest weight is |
|
290 * discarded. |
|
291 */ |
|
292 static M3G_INLINE void m3gAddInfluence(SkinnedMesh *mesh, |
|
293 M3Gint vertexIndex, |
|
294 M3Gint boneIndex, |
|
295 M3Gint weight) |
|
296 { |
|
297 M3Gint bonesPerVertex = mesh->bonesPerVertex; |
|
298 M3Guint minWeight = weight; |
|
299 M3Gint minWeightIndex = -1; |
|
300 int i; |
|
301 |
|
302 /* Shift the weight into the same scale with the other weights for |
|
303 * this vertex. */ |
|
304 |
|
305 weight >>= mesh->weightShifts[vertexIndex]; |
|
306 |
|
307 /* Look for an existing weight for our bone, or find the index |
|
308 * with the lowest weight if not found, and store it in |
|
309 * minWeightIndex. Note that we're not separately tagging indices |
|
310 * as used/unused; unused ones will merely have a weight of |
|
311 * zero. */ |
|
312 |
|
313 for (i = 0; i < bonesPerVertex; ++i) { |
|
314 |
|
315 /* If we find an existing weight for our bone, just add to |
|
316 * that and break out. Otherwise, keep track of the minimum |
|
317 * weight encountered so far. */ |
|
318 |
|
319 if (mesh->boneIndices[i][vertexIndex] == boneIndex) { |
|
320 weight += mesh->boneWeights[i][vertexIndex]; |
|
321 minWeightIndex = i; |
|
322 break; |
|
323 } |
|
324 else { |
|
325 M3Guint tempWeight = mesh->boneWeights[i][vertexIndex]; |
|
326 if (tempWeight < minWeight) { |
|
327 minWeight = tempWeight; |
|
328 minWeightIndex = i; |
|
329 } |
|
330 } |
|
331 } |
|
332 |
|
333 /* Check whether our total weight exceeds the allocated range, |
|
334 * shifting all existing weights down if necessary */ |
|
335 |
|
336 while (weight >= (1 << 8)) { /* byte range */ |
|
337 weight >>= 1; |
|
338 mesh->weightShifts[vertexIndex] += 1; |
|
339 for (i = 0; i < bonesPerVertex; ++i) { |
|
340 mesh->boneWeights[i][vertexIndex] >>= 1; |
|
341 } |
|
342 M3G_ASSERT(mesh->weightShifts[vertexIndex] <= 31); |
|
343 } |
|
344 |
|
345 /* Add the index and weight contribution of the new |
|
346 * transformation, provided that the minimum weight found was |
|
347 * indeed smaller than the one we're adding */ |
|
348 |
|
349 if (minWeightIndex >= 0) { |
|
350 mesh->boneIndices[minWeightIndex][vertexIndex] = (M3Gubyte) boneIndex; |
|
351 mesh->boneWeights[minWeightIndex][vertexIndex] = (M3Gubyte) weight; |
|
352 |
|
353 /* Need an update of the normalizing scales, too, as well as |
|
354 * the actual transformed vertices */ |
|
355 |
|
356 mesh->weightsDirty = M3G_TRUE; |
|
357 m3gInvalidateNode((Node*) mesh, NODE_TRANSFORMS_BIT|NODE_BBOX_BIT); |
|
358 } |
|
359 } |
|
360 |
|
361 /*! |
|
362 * \internal |
|
363 * \brief Computes the normalization scales for vertex weights |
|
364 */ |
|
365 static void m3gNormalizeWeights(SkinnedMesh *mesh) |
|
366 { |
|
367 const M3Gint bonesPerVertex = mesh->bonesPerVertex; |
|
368 const M3Gint vertexCount = mesh->weightedVertexCount; |
|
369 M3Gint vi; |
|
370 |
|
371 for (vi = 0; vi < vertexCount; ++vi) { |
|
372 M3Gint k; |
|
373 |
|
374 /* Sum up the 8-bit (possibly downshifted) weights */ |
|
375 |
|
376 M3Guint sum = 0; |
|
377 for (k = 0; k < bonesPerVertex; ++k) { |
|
378 sum += mesh->boneWeights[k][vi]; |
|
379 } |
|
380 |
|
381 /* Compute an 8.24 reciprocal of the weights, then scale with |
|
382 * that to normalize, and shift to 1.7 fixed point */ |
|
383 { |
|
384 M3Guint s = (sum > 0 ? (1U << 24) / sum : 0); |
|
385 |
|
386 sum = 0; |
|
387 for (k = 0; k < bonesPerVertex; ++k) { |
|
388 M3Guint normalized = (s * mesh->boneWeights[k][vi]) >> 17; |
|
389 M3G_ASSERT(m3gInRange((M3Gint)normalized, 0, 128)); |
|
390 sum += normalized; |
|
391 mesh->normalizedWeights[k][vi] = (M3Gubyte) normalized; |
|
392 } |
|
393 |
|
394 /* NOTE there is a maximum of ½ rounding error per |
|
395 * component, plus the rounding error from the reciprocal |
|
396 * calculation, so the sum of weights will often not sum |
|
397 * to 128 exactly! We therefore only assert against |
|
398 * clearly out-of-range values here */ |
|
399 |
|
400 M3G_ASSERT(sum == 0 || m3gInRange((M3Gint) sum, 96, 128)); |
|
401 } |
|
402 } |
|
403 |
|
404 mesh->weightsDirty = M3G_FALSE; |
|
405 } |
|
406 |
|
407 /*! |
|
408 * \internal |
|
409 * \brief Computes an optimal exponent value for a fixed point |
|
410 * transformation |
|
411 * |
|
412 * This scales the translation exponent up to optimally utilize the |
|
413 * 32-bit intermediate precision if the matrix exponent is smaller. |
|
414 */ |
|
415 static M3Gint m3gOptimalExponent(M3Gint matrixExp, M3Gint transExp) |
|
416 { |
|
417 M3Gint maxExp = matrixExp; |
|
418 M3Gint shift = transExp - matrixExp; |
|
419 if (shift > 0) { |
|
420 |
|
421 /* The matrix part will always occupy less than half of the |
|
422 * available range if shifted down by at least one bit, so we |
|
423 * can shift the translation up by a maximum of 15 bits. If |
|
424 * the matrix is shifted by more than 31 bits, it will always |
|
425 * flush to zero, freeing the full 32-bit range for the |
|
426 * translation alone. */ |
|
427 |
|
428 if (shift >= 32) { /* matrix will flush to zero */ |
|
429 shift = 16; |
|
430 } |
|
431 else if (shift >= 16) { /* matrix always < half of the range */ |
|
432 shift = 15; |
|
433 } |
|
434 else { |
|
435 shift -= 1; /* shift matrix by at least one bit */ |
|
436 } |
|
437 |
|
438 maxExp = transExp - shift; |
|
439 } |
|
440 |
|
441 M3G_ASSERT(maxExp >= matrixExp && maxExp >= transExp - 16); |
|
442 return maxExp; |
|
443 } |
|
444 |
|
445 /* |
|
446 * \brief Fixed point vertex transformation |
|
447 * |
|
448 * \param mtx pointer to a 3x3 16-bit matrix |
|
449 * \param mtxExp exponent for the matrix elements (upshift from int) |
|
450 * \param trans pointer to 3-element 16-bit translation vector |
|
451 * \param transExp exponent for the translation vector |
|
452 * \param maxExp precalculated "optimal" exponent |
|
453 * \param vx vertex X coordinate (16-bit range) |
|
454 * \param vy vertex Y coordinate (16-bit range) |
|
455 * \param vz vertex Z coordinate (16-bit range) |
|
456 * \param out output vertex, 25 bits of precision |
|
457 * \return exponent value for \c out |
|
458 */ |
|
459 static M3Gint m3gFixedPointTransform(const M3Gshort *mtx, M3Gint mtxExp, |
|
460 const M3Gshort *trans, M3Gint transExp, |
|
461 M3Gint maxExp, |
|
462 M3Gint vx, M3Gint vy, M3Gint vz, |
|
463 M3Gint *out) |
|
464 { |
|
465 M3Gint shift; |
|
466 M3Gint ox = 0, oy = 0, oz = 0; |
|
467 |
|
468 /* First put in the translation part, upscaled to the optimal |
|
469 * range for this bone */ |
|
470 |
|
471 if (trans) { |
|
472 shift = maxExp - (transExp - 16); |
|
473 M3G_ASSERT(shift >= 0); |
|
474 if (shift < 32) { |
|
475 ox += ((M3Gint) trans[0] << 16) >> shift; |
|
476 oy += ((M3Gint) trans[1] << 16) >> shift; |
|
477 oz += ((M3Gint) trans[2] << 16) >> shift; |
|
478 } |
|
479 } |
|
480 |
|
481 /* Add the input multiplied with the base 3x3 matrix and shifted |
|
482 * to the "maxExp" scale, provided that it has any effect on the |
|
483 * outcome */ |
|
484 |
|
485 shift = maxExp - mtxExp; |
|
486 M3G_ASSERT(shift >= 0); |
|
487 if (shift < 32) { |
|
488 |
|
489 # if defined(M3G_DEBUG) |
|
490 M3Gint iMin = (-1 << 31) + (65535 * 32768 >> shift); |
|
491 M3Gint iMax = (M3Gint)((1u << 31)-1) - (65535 * 32768 >> shift); |
|
492 M3G_ASSERT(m3gInRange(ox, iMin, iMax)); |
|
493 M3G_ASSERT(m3gInRange(oy, iMin, iMax)); |
|
494 M3G_ASSERT(m3gInRange(oz, iMin, iMax)); |
|
495 # endif /* M3G_DEBUG */ |
|
496 |
|
497 ox += (mtx[0] * vx + mtx[3] * vy + mtx[6] * vz) >> shift; |
|
498 oy += (mtx[1] * vx + mtx[4] * vy + mtx[7] * vz) >> shift; |
|
499 oz += (mtx[2] * vx + mtx[5] * vy + mtx[8] * vz) >> shift; |
|
500 } |
|
501 |
|
502 /* Shift the output down to fit into 25 bits; we're dropping 7 |
|
503 * bits of precision here, so adjust the exponent accordingly */ |
|
504 |
|
505 out[0] = ox >> 7; |
|
506 out[1] = oy >> 7; |
|
507 out[2] = oz >> 7; |
|
508 return maxExp + 7; |
|
509 } |
|
510 |
|
511 /*! |
|
512 * \internal |
|
513 * \brief Applies scale and bias to a vertex |
|
514 * |
|
515 * This is required for vertices that have no bones attached. |
|
516 * |
|
517 * \param mesh the SkinnedMesh object |
|
518 * \param vx vertex X coordinate (16-bit range) |
|
519 * \param vy vertex Y coordinate (16-bit range) |
|
520 * \param vz vertex Z coordinate (16-bit range) |
|
521 * \param upshift scaling value for the input coordinates and the |
|
522 * translation component of the transformation |
|
523 * \param vertex output vertex position |
|
524 * \return exponent value for \c vertex |
|
525 */ |
|
526 static M3Gint m3gScaleAndBiasVertex(const SkinnedMesh *mesh, |
|
527 M3Gint vx, M3Gint vy, M3Gint vz, |
|
528 M3Gint upshift, |
|
529 M3Gshort *vertex) |
|
530 { |
|
531 M3Gint temp[3]; |
|
532 M3Gint expo; |
|
533 |
|
534 M3G_ASSERT(m3gInRange(vx, -1 << 15, (1 << 15) - 1)); |
|
535 M3G_ASSERT(m3gInRange(vy, -1 << 15, (1 << 15) - 1)); |
|
536 M3G_ASSERT(m3gInRange(vz, -1 << 15, (1 << 15) - 1)); |
|
537 |
|
538 expo = m3gFixedPointTransform(mesh->scaleMatrix, mesh->scaleExp, |
|
539 mesh->biasVector, mesh->biasExp + upshift, |
|
540 mesh->scaleBiasExp, |
|
541 vx << upshift, vy << upshift, vz << upshift, |
|
542 temp) - upshift; |
|
543 |
|
544 /* Scale down from 25 to 16 bits, adjusting the exponent |
|
545 * accordingly */ |
|
546 |
|
547 vertex[0] = (M3Gshort)(temp[0] >> 9); |
|
548 vertex[1] = (M3Gshort)(temp[1] >> 9); |
|
549 vertex[2] = (M3Gshort)(temp[2] >> 9); |
|
550 expo += 9; |
|
551 |
|
552 M3G_ASSERT(m3gInRange(expo, -127, 127)); |
|
553 return expo; |
|
554 } |
|
555 |
|
556 /*! |
|
557 * \internal |
|
558 * \brief Computes the blended position for a single vertex |
|
559 * |
|
560 * \param mesh the SkinnedMesh object |
|
561 * \param vidx vertex index (for accessing bone data) |
|
562 * \param vx vertex X coordinate (16-bit range) |
|
563 * \param vy vertex Y coordinate (16-bit range) |
|
564 * \param vz vertex Z coordinate (16-bit range) |
|
565 * \param upshift scaling value for the input coordinates and the |
|
566 * translation component of the transformation |
|
567 * \param vertex output vertex position |
|
568 * \return exponent value for \c vertex |
|
569 */ |
|
570 static M3Gint m3gBlendVertex(const SkinnedMesh *mesh, |
|
571 M3Gint vidx, |
|
572 M3Gint vx, M3Gint vy, M3Gint vz, |
|
573 M3Gint upshift, |
|
574 M3Gshort *vertex) |
|
575 { |
|
576 const M3Gint boneCount = mesh->bonesPerVertex; |
|
577 const PointerArray *boneArray = &mesh->bones; |
|
578 M3Gint i; |
|
579 |
|
580 M3Gint outExp = -128; |
|
581 M3Gint sumWeights = 0; |
|
582 |
|
583 M3Gint ox = 0, oy = 0, oz = 0; |
|
584 |
|
585 vx <<= upshift; |
|
586 vy <<= upshift; |
|
587 vz <<= upshift; |
|
588 |
|
589 M3G_ASSERT(m3gInRange(vx, -1 << 15, (1 << 15) - 1)); |
|
590 M3G_ASSERT(m3gInRange(vy, -1 << 15, (1 << 15) - 1)); |
|
591 M3G_ASSERT(m3gInRange(vz, -1 << 15, (1 << 15) - 1)); |
|
592 |
|
593 /* Loop over the bones and sum the contribution from each */ |
|
594 |
|
595 for (i = 0; i < boneCount; ++i) { |
|
596 |
|
597 M3Gint weight = (M3Gint) mesh->normalizedWeights[i][vidx]; |
|
598 sumWeights += weight; |
|
599 |
|
600 /* Skip bones with zero weights */ |
|
601 |
|
602 if (weight > 0) { |
|
603 |
|
604 const Bone *bone = (const Bone *) |
|
605 m3gGetArrayElement(boneArray, mesh->boneIndices[i][vidx]); |
|
606 M3Gint temp[3]; |
|
607 M3Gint shift; |
|
608 |
|
609 shift = m3gFixedPointTransform(bone->baseMatrix, bone->baseExp, |
|
610 bone->posVec, bone->posExp + upshift, |
|
611 bone->maxExp, |
|
612 vx, vy, vz, |
|
613 temp); |
|
614 |
|
615 shift = outExp - shift; |
|
616 if (shift < 0) { |
|
617 shift = -shift; |
|
618 if (shift < 31) { |
|
619 ox >>= shift; |
|
620 oy >>= shift; |
|
621 oz >>= shift; |
|
622 } |
|
623 else { |
|
624 ox = oy = oz = 0; |
|
625 } |
|
626 outExp += shift; |
|
627 shift = 0; |
|
628 } |
|
629 |
|
630 /* Apply the vertex weights: 1.7 * 25.0 -> 26.7, but since |
|
631 * the weights are positive and sum to 1, we should stay |
|
632 * within the 32-bit range */ |
|
633 |
|
634 if (shift < 31) { |
|
635 |
|
636 M3G_ASSERT(m3gInRange(temp[0], -1 << 24, (1 << 24) - 1)); |
|
637 M3G_ASSERT(m3gInRange(temp[1], -1 << 24, (1 << 24) - 1)); |
|
638 M3G_ASSERT(m3gInRange(temp[2], -1 << 24, (1 << 24) - 1)); |
|
639 |
|
640 ox += (weight * temp[0]) >> shift; |
|
641 oy += (weight * temp[1]) >> shift; |
|
642 oz += (weight * temp[2]) >> shift; |
|
643 } |
|
644 } |
|
645 } |
|
646 |
|
647 /* Before returning, we still need to check for the special case |
|
648 * of all-zero weights, and shift the values from the post-scaling |
|
649 * 32-bit precision back into the 16-bit range; we're essentially |
|
650 * dropping the (25 - 16) bits of the blended result, so the |
|
651 * exponent must change accordingly */ |
|
652 |
|
653 if (sumWeights > 0) { |
|
654 vertex[0] = (M3Gshort)(ox >> 16); |
|
655 vertex[1] = (M3Gshort)(oy >> 16); |
|
656 vertex[2] = (M3Gshort)(oz >> 16); |
|
657 outExp = outExp - upshift + 9; |
|
658 |
|
659 M3G_ASSERT(m3gInRange(outExp, -127, 127)); |
|
660 return outExp; |
|
661 } |
|
662 else { |
|
663 vx >>= upshift; |
|
664 vy >>= upshift; |
|
665 vz >>= upshift; |
|
666 return m3gScaleAndBiasVertex(mesh, vx, vy, vz, upshift, vertex); |
|
667 } |
|
668 } |
|
669 |
|
670 /*! |
|
671 * \internal |
|
672 * \brief Computes the blended normal vector for a single vertex |
|
673 * |
|
674 * \param mesh the SkinnedMesh object |
|
675 * \param vidx vertex index (for accessing bone data) |
|
676 * \param nx normal X coordinate (16-bit range) |
|
677 * \param ny normal Y coordinate (16-bit range) |
|
678 * \param nz normal Z coordinate (16-bit range) |
|
679 * \param upshift scaling for input coordinates to increase precision |
|
680 * \param normal output normal vector (8-bit range!) |
|
681 * \return a shift value for the output vertex (scale from integer) |
|
682 */ |
|
683 static void m3gBlendNormal(const SkinnedMesh *mesh, |
|
684 M3Gint vidx, |
|
685 M3Gint nx, M3Gint ny, M3Gint nz, |
|
686 M3Gint upshift, |
|
687 M3Gbyte *normal) |
|
688 { |
|
689 const M3Gint boneCount = mesh->bonesPerVertex; |
|
690 const PointerArray *boneArray = &mesh->bones; |
|
691 M3Gint i; |
|
692 |
|
693 M3Gint outExp = -128; |
|
694 M3Gint sumWeights = 0; |
|
695 |
|
696 M3Gint ox = 0, oy = 0, oz = 0; |
|
697 |
|
698 nx <<= upshift; |
|
699 ny <<= upshift; |
|
700 nz <<= upshift; |
|
701 |
|
702 M3G_ASSERT(m3gInRange(nx, -1 << 15, (1 << 15) - 1)); |
|
703 M3G_ASSERT(m3gInRange(ny, -1 << 15, (1 << 15) - 1)); |
|
704 M3G_ASSERT(m3gInRange(nz, -1 << 15, (1 << 15) - 1)); |
|
705 |
|
706 /* Loop over the bones and sum the contribution from each */ |
|
707 |
|
708 for (i = 0; i < boneCount; ++i) { |
|
709 |
|
710 M3Gint weight = (M3Gint) mesh->normalizedWeights[i][vidx]; |
|
711 sumWeights += weight; |
|
712 |
|
713 /* Skip bones with zero weights */ |
|
714 |
|
715 if (weight > 0) { |
|
716 |
|
717 const Bone *bone = (const Bone *) |
|
718 m3gGetArrayElement(boneArray, mesh->boneIndices[i][vidx]); |
|
719 M3Gint temp[3]; |
|
720 M3Gint shift; |
|
721 |
|
722 shift = m3gFixedPointTransform(bone->normalMatrix, 0, |
|
723 NULL, 0, |
|
724 0, |
|
725 nx, ny, nz, |
|
726 temp); |
|
727 |
|
728 shift = outExp - shift; |
|
729 if (shift < 0) { |
|
730 shift = -shift; |
|
731 if (shift < 31) { |
|
732 ox >>= shift; |
|
733 oy >>= shift; |
|
734 oz >>= shift; |
|
735 } |
|
736 else { |
|
737 ox = oy = oz = 0; |
|
738 } |
|
739 outExp += shift; |
|
740 shift = 0; |
|
741 } |
|
742 |
|
743 /* Apply the vertex weights: 1.7 * 25.0 -> 26.7, but since |
|
744 * the weights are positive and sum to 1, we should stay |
|
745 * within the 32-bit range */ |
|
746 |
|
747 if (shift < 31) { |
|
748 |
|
749 M3G_ASSERT(m3gInRange(temp[0], -1 << 24, (1 << 24) - 1)); |
|
750 M3G_ASSERT(m3gInRange(temp[1], -1 << 24, (1 << 24) - 1)); |
|
751 M3G_ASSERT(m3gInRange(temp[2], -1 << 24, (1 << 24) - 1)); |
|
752 |
|
753 ox += (weight * temp[0]) >> shift; |
|
754 oy += (weight * temp[1]) >> shift; |
|
755 oz += (weight * temp[2]) >> shift; |
|
756 } |
|
757 } |
|
758 } |
|
759 |
|
760 /* Before returning, we still need to check for the special case |
|
761 * of all-zero weights, and shift the values from the post-scaling |
|
762 * 32-bit precision down into the 8-bit range */ |
|
763 |
|
764 if (sumWeights > 0) { |
|
765 normal[0] = (M3Gbyte)(ox >> 24); |
|
766 normal[1] = (M3Gbyte)(oy >> 24); |
|
767 normal[2] = (M3Gbyte)(oz >> 24); |
|
768 } |
|
769 else { |
|
770 normal[0] = (M3Gbyte)(ox >> 8); |
|
771 normal[1] = (M3Gbyte)(oy >> 8); |
|
772 normal[2] = (M3Gbyte)(oz >> 8); |
|
773 } |
|
774 } |
|
775 |
|
776 /*! |
|
777 * \internal |
|
778 * \brief Updates internal vertex buffer |
|
779 * |
|
780 * \param mesh SkinnedMesh object |
|
781 * |
|
782 * \retval M3G_TRUE VertexBuffer is up to date |
|
783 * \retval M3G_FALSE Failed to update VertexBuffer, out of memory exception raised |
|
784 */ |
|
785 static M3Gbool m3gSkinnedMeshUpdateVB(SkinnedMesh *mesh) |
|
786 { |
|
787 M3Gint vbTimestamp; |
|
788 M3G_ASSERT(mesh->mesh.vertexBuffer != NULL); |
|
789 M3G_ASSERT(mesh->morphedVB != NULL); |
|
790 |
|
791 /* Source vertex buffer array configuration changed since last |
|
792 * update? */ |
|
793 |
|
794 vbTimestamp = m3gGetTimestamp(mesh->mesh.vertexBuffer); |
|
795 |
|
796 if (mesh->vbTimestamp != vbTimestamp) { |
|
797 Interface *m3g = M3G_INTERFACE(mesh); |
|
798 VertexArray *array; |
|
799 M3Gint vcount = m3gGetVertexCount(mesh->mesh.vertexBuffer); |
|
800 |
|
801 /* Must ensure that our internal morphing buffer matches the |
|
802 * configuration of the source buffer, with dedicated arrays |
|
803 * for the morphed positions and normals */ |
|
804 |
|
805 if (!m3gMakeModifiedVertexBuffer(mesh->morphedVB, |
|
806 mesh->mesh.vertexBuffer, |
|
807 M3G_POSITION_BIT|M3G_NORMAL_BIT, |
|
808 M3G_FALSE)) { |
|
809 return M3G_FALSE; /* out of memory */ |
|
810 } |
|
811 |
|
812 /* We always have the vertex positions as shorts, but the |
|
813 * array may not be actually initialized yet, so we must check |
|
814 * whether to create a copy or not */ |
|
815 |
|
816 if (mesh->mesh.vertexBuffer->vertices) { |
|
817 array = m3gCreateVertexArray(m3g, vcount, 3, M3G_SHORT); |
|
818 if (!array) { |
|
819 return M3G_FALSE; |
|
820 } |
|
821 m3gSetVertexArray(mesh->morphedVB, array, 1.f, NULL, 0); |
|
822 } |
|
823 |
|
824 /* Normals (always bytes) only exist if in the original VB */ |
|
825 |
|
826 if (mesh->mesh.vertexBuffer->normals) { |
|
827 array = m3gCreateVertexArray(m3g, vcount, 3, M3G_BYTE); |
|
828 if (!array) { |
|
829 return M3G_FALSE; |
|
830 } |
|
831 m3gSetNormalArray(mesh->morphedVB, array); |
|
832 } |
|
833 |
|
834 mesh->vbTimestamp = vbTimestamp; |
|
835 } |
|
836 |
|
837 /* The default color must always be updated, because it can be |
|
838 * animated (doesn't affect timestamp) */ |
|
839 |
|
840 mesh->morphedVB->defaultColor = mesh->mesh.vertexBuffer->defaultColor; |
|
841 return M3G_TRUE; |
|
842 } |
|
843 |
|
844 |
|
845 /*! |
|
846 * \internal |
|
847 * \brief Gets the transformation(s) for a single bone record |
|
848 * |
|
849 * Also stores the normal transformation matrix if needed. |
|
850 * |
|
851 * \param mesh pointer to the mesh object |
|
852 * \param bone pointer to the bone record |
|
853 * \param hasNormals flag indicating whether the normals transformation |
|
854 * should be computed and cached in the bone record |
|
855 * \param mtx matrix to store the vertex transformation in |
|
856 */ |
|
857 static M3G_INLINE M3Gbool m3gGetBoneTransformInternal(SkinnedMesh *mesh, |
|
858 Bone *bone, |
|
859 M3Gbool hasNormals, |
|
860 Matrix *mtx) |
|
861 { |
|
862 const VertexBuffer *vb = mesh->mesh.vertexBuffer; |
|
863 |
|
864 /* Get the vertex transformation and concatenate it with the |
|
865 * at-rest matrix and the vertex scale and bias transformations. |
|
866 * The resulting 3x4 transformation matrix is then split into a |
|
867 * fixed point 3x3 matrix and translation vector */ |
|
868 |
|
869 if (!m3gGetTransformTo(bone->node, (Node*) mesh, mtx)) { |
|
870 return M3G_FALSE; /* no path or singular transform */ |
|
871 } |
|
872 m3gMulMatrix(mtx, &bone->toBone); |
|
873 |
|
874 /* If normals are enabled, compute and store the inverse transpose |
|
875 * matrix for transforming normals at this stage */ |
|
876 |
|
877 if (hasNormals) { |
|
878 Matrix t; |
|
879 if (!m3gInverseTranspose(&t, mtx)) { |
|
880 m3gRaiseError(M3G_INTERFACE(mesh), M3G_ARITHMETIC_ERROR); |
|
881 return M3G_FALSE; /* singular transform */ |
|
882 } |
|
883 m3gGetFixedPoint3x3Basis(&t, bone->normalMatrix); |
|
884 } |
|
885 |
|
886 /* Apply the vertex bias and scale to the transformation */ |
|
887 |
|
888 m3gTranslateMatrix( |
|
889 mtx, vb->vertexBias[0], vb->vertexBias[1], vb->vertexBias[2]); |
|
890 m3gScaleMatrix(mtx, vb->vertexScale, vb->vertexScale, vb->vertexScale); |
|
891 |
|
892 return M3G_TRUE; |
|
893 } |
|
894 |
|
895 /*! |
|
896 * \internal |
|
897 * \brief Compute and cache the bone transformations for morphing |
|
898 * |
|
899 * \param mesh the SkinnedMesh object |
|
900 * \param posShift vertex position value "gain" |
|
901 */ |
|
902 static M3Gbool m3gPreComputeTransformations(SkinnedMesh *mesh, |
|
903 M3Gint posShift, |
|
904 M3Gbool hasNormals) |
|
905 { |
|
906 M3Gint boneCount = m3gArraySize(&mesh->bones); |
|
907 M3Gint i; |
|
908 Matrix *tBone = NULL; |
|
909 |
|
910 /* First, just compute the floating point transformation matrices |
|
911 * for the bones, caching them in a temp array */ |
|
912 |
|
913 if (boneCount > 0) { |
|
914 tBone = m3gAllocTemp(M3G_INTERFACE(mesh), boneCount * sizeof(Matrix)); |
|
915 if (!tBone) { |
|
916 return M3G_FALSE; /* out of memory */ |
|
917 } |
|
918 for (i = 0; i < boneCount; ++i) { |
|
919 Bone *bone = m3gGetArrayElement(&mesh->bones, i); |
|
920 if (!m3gGetBoneTransformInternal(mesh, bone, hasNormals, &tBone[i])) { |
|
921 return M3G_FALSE; |
|
922 } |
|
923 } |
|
924 } |
|
925 |
|
926 /* Find the value range of the bone translations, and offset the |
|
927 * bones to center output vertex values (roughly) around the |
|
928 * origin */ |
|
929 { |
|
930 const VertexBuffer *vb = mesh->mesh.vertexBuffer; |
|
931 M3Gfloat min[3], max[3], bias[3]; |
|
932 M3Gint maxExp; |
|
933 Vec4 t; |
|
934 |
|
935 /* Find the minimum and maximum values; start with the plain |
|
936 * vertex bias for non-weighted bones */ |
|
937 |
|
938 min[0] = max[0] = vb->vertexBias[0]; |
|
939 min[1] = max[1] = vb->vertexBias[1]; |
|
940 min[2] = max[2] = vb->vertexBias[2]; |
|
941 |
|
942 for (i = 0; i < boneCount; ++i) { |
|
943 m3gGetMatrixColumn(&tBone[i], 3, &t); |
|
944 min[0] = M3G_MIN(min[0], t.x); |
|
945 max[0] = M3G_MAX(max[0], t.x); |
|
946 min[1] = M3G_MIN(min[1], t.y); |
|
947 max[1] = M3G_MAX(max[1], t.y); |
|
948 min[2] = M3G_MIN(min[2], t.z); |
|
949 max[2] = M3G_MAX(max[2], t.z); |
|
950 } |
|
951 |
|
952 /* Divide to get the mean translation, store in the |
|
953 * destination VB, and invert for de-biasing the bones */ |
|
954 |
|
955 for (i = 0; i < 3; ++i) { |
|
956 bias[i] = m3gMul(0.5f, m3gAdd(min[i], max[i])); |
|
957 mesh->morphedVB->vertexBias[i] = bias[i]; |
|
958 bias[i] = m3gNegate(bias[i]); |
|
959 } |
|
960 |
|
961 /* Offset bones by the (now inverted) bias vector, and store |
|
962 * the fixed point matrix & vector parts in the bone record; |
|
963 * also set the maximum bone exponent into the mesh */ |
|
964 |
|
965 maxExp = -128; |
|
966 for (i = 0; i < boneCount; ++i) { |
|
967 Bone *bone = m3gGetArrayElement(&mesh->bones, i); |
|
968 m3gPreTranslateMatrix(&tBone[i], bias[0], bias[1], bias[2]); /*lint !e613 tBone not null if boneCount > 0 */ |
|
969 |
|
970 bone->baseExp = (M3Gshort) |
|
971 m3gGetFixedPoint3x3Basis(&tBone[i], bone->baseMatrix); /*lint !e613 tBone not null if boneCount > 0 */ |
|
972 bone->posExp = (M3Gshort) |
|
973 m3gGetFixedPointTranslation(&tBone[i], bone->posVec); /*lint !e613 tBone not null if boneCount > 0 */ |
|
974 bone->maxExp = (M3Gshort) |
|
975 m3gOptimalExponent(bone->baseExp, bone->posExp + posShift); |
|
976 |
|
977 maxExp = M3G_MAX(maxExp, bone->maxExp); |
|
978 } |
|
979 |
|
980 /* Make a fixed-point matrix for applying the scale and bias as |
|
981 * well, for vertices not attached to any bone (this is not the |
|
982 * optimal way to store the information, but we can just reuse |
|
983 * existing code this way) */ |
|
984 { |
|
985 Matrix sb; |
|
986 m3gTranslationMatrix(&sb, |
|
987 m3gAdd(bias[0], vb->vertexBias[0]), |
|
988 m3gAdd(bias[1], vb->vertexBias[1]), |
|
989 m3gAdd(bias[2], vb->vertexBias[2])); |
|
990 m3gScaleMatrix(&sb, |
|
991 vb->vertexScale, vb->vertexScale, vb->vertexScale); |
|
992 |
|
993 mesh->scaleExp = (M3Gshort) |
|
994 m3gGetFixedPoint3x3Basis(&sb, mesh->scaleMatrix); |
|
995 mesh->biasExp = (M3Gshort) |
|
996 m3gGetFixedPointTranslation(&sb, mesh->biasVector); |
|
997 mesh->scaleBiasExp = (M3Gshort) |
|
998 m3gOptimalExponent(mesh->scaleExp, mesh->biasExp + posShift); |
|
999 |
|
1000 maxExp = M3G_MAX(mesh->scaleBiasExp, maxExp); |
|
1001 } |
|
1002 |
|
1003 /* Compute the maximum post-blending exponent and store it as the |
|
1004 * morphed vertex buffer scale -- this is dependent on the |
|
1005 * implementations of m3gBlendVertex, m3gScaleAndBiasVertex, and |
|
1006 * m3gFixedPointTransform! */ |
|
1007 |
|
1008 maxExp = maxExp + 16 - posShift; |
|
1009 M3G_ASSERT(m3gInRange(maxExp, -127, 127)); |
|
1010 *(M3Gint*)&mesh->morphedVB->vertexScale = (maxExp + 127) << 23; |
|
1011 mesh->maxExp = (M3Gshort) maxExp; |
|
1012 } |
|
1013 |
|
1014 if (boneCount > 0) { |
|
1015 m3gFreeTemp(M3G_INTERFACE(mesh)); |
|
1016 } |
|
1017 |
|
1018 return M3G_TRUE; |
|
1019 } |
|
1020 |
|
1021 /*! |
|
1022 * \internal |
|
1023 * \brief Computes derived data required for bounding volumes and skinning |
|
1024 */ |
|
1025 static M3Gbool m3gSkinnedMeshPreMorph(SkinnedMesh *mesh) |
|
1026 { |
|
1027 const VertexBuffer *srcVB = mesh->mesh.vertexBuffer; |
|
1028 M3Gint posShift = 0, normalShift = 0; |
|
1029 |
|
1030 /* Compute upscaling shift values for positions and normals so |
|
1031 * that we can maximize precision even for absurdly small |
|
1032 * vertex values */ |
|
1033 { |
|
1034 M3Gint minVal, maxVal; |
|
1035 |
|
1036 if (srcVB->normals) { |
|
1037 m3gGetArrayValueRange(srcVB->normals, &minVal, &maxVal); |
|
1038 maxVal = M3G_MAX(-minVal, maxVal); |
|
1039 M3G_ASSERT(maxVal >= 0); |
|
1040 if (maxVal) { |
|
1041 while ((maxVal << normalShift) < (1 << 14)) { |
|
1042 ++normalShift; |
|
1043 } |
|
1044 } |
|
1045 } |
|
1046 |
|
1047 m3gGetArrayValueRange(srcVB->vertices, &minVal, &maxVal); |
|
1048 maxVal = M3G_MAX(-minVal, maxVal); |
|
1049 M3G_ASSERT(maxVal >= 0); |
|
1050 if (maxVal) { |
|
1051 while ((maxVal << posShift) < (1 << 14)) { |
|
1052 ++posShift; |
|
1053 } |
|
1054 } |
|
1055 |
|
1056 mesh->posShift = (M3Gshort) posShift; |
|
1057 mesh->normalShift = (M3Gshort) normalShift; |
|
1058 } |
|
1059 |
|
1060 /* Now that we can compute the optimized exponents for the |
|
1061 * transformations based on the position upshift value, let's |
|
1062 * resolve the bone transformations; this will also cache the |
|
1063 * maximum bone exponent in mesh->maxExp */ |
|
1064 |
|
1065 if (!m3gPreComputeTransformations(mesh, |
|
1066 posShift, |
|
1067 srcVB->normals != NULL)) { |
|
1068 return M3G_FALSE; /* invalid transform */ |
|
1069 } |
|
1070 |
|
1071 return M3G_TRUE; |
|
1072 } |
|
1073 |
|
1074 /*! |
|
1075 * \internal |
|
1076 * \brief Does the actual vertex morphing into the internal vertex buffer |
|
1077 * |
|
1078 * \param mesh SkinnedMesh object |
|
1079 * \retval M3G_TRUE skinning ok |
|
1080 * \retval M3G_FALSE skinning failed, exception raised |
|
1081 */ |
|
1082 static void m3gSkinnedMeshMorph(SkinnedMesh *mesh) |
|
1083 { |
|
1084 const VertexBuffer *srcVB = mesh->mesh.vertexBuffer; |
|
1085 const void *srcPositions; |
|
1086 const void *srcNormals = NULL; |
|
1087 VertexBuffer *dstVB = mesh->morphedVB; |
|
1088 M3Gshort *dstPositions; |
|
1089 M3Gbyte *dstNormals = NULL; |
|
1090 M3Gint vertexCount = mesh->weightedVertexCount; |
|
1091 M3Gint maxExp = mesh->maxExp; |
|
1092 M3Gint posShift = mesh->posShift, normShift = mesh->normalShift; |
|
1093 M3Gint i; |
|
1094 |
|
1095 M3G_ASSERT(!((Node*) mesh)->dirtyBits); |
|
1096 |
|
1097 /* Let's update the vertex weights if we need to */ |
|
1098 |
|
1099 if (mesh->weightsDirty) { |
|
1100 m3gNormalizeWeights(mesh); |
|
1101 } |
|
1102 |
|
1103 /* Get pointers to source and destination position and normal |
|
1104 * data; the latter will always be shorts and bytes, |
|
1105 * respectively, while the former can be either */ |
|
1106 |
|
1107 srcPositions = m3gMapVertexArrayReadOnly(srcVB->vertices); |
|
1108 dstPositions = (M3Gshort*) m3gMapVertexArray(dstVB->vertices); |
|
1109 if (srcVB->normals) { |
|
1110 srcNormals = m3gMapVertexArrayReadOnly(srcVB->normals); |
|
1111 dstNormals = (M3Gbyte*) m3gMapVertexArray(dstVB->normals); |
|
1112 } |
|
1113 |
|
1114 /* Transform the vertices that are affected by bones */ |
|
1115 { |
|
1116 M3Gshort *dst = dstPositions; |
|
1117 |
|
1118 if (srcVB->vertices->elementType == GL_BYTE) { |
|
1119 const M3Gbyte *src = (const M3Gbyte*) srcPositions; |
|
1120 for (i = 0; i < vertexCount; ++i) { |
|
1121 M3Gint shift = |
|
1122 maxExp - m3gBlendVertex(mesh, i, |
|
1123 src[0], src[1], src[2], |
|
1124 posShift, |
|
1125 dst); |
|
1126 if (shift > 31) { |
|
1127 *dst++ = 0; |
|
1128 *dst++ = 0; |
|
1129 *dst++ = 0; |
|
1130 } |
|
1131 else { |
|
1132 *dst++ >>= shift; |
|
1133 *dst++ >>= shift; |
|
1134 *dst++ >>= shift; |
|
1135 } |
|
1136 |
|
1137 src += 4; /* byte data always padded to 32 bits */ |
|
1138 } |
|
1139 } |
|
1140 else { |
|
1141 const M3Gshort *src = (const M3Gshort*) srcPositions; |
|
1142 for (i = 0; i < vertexCount; ++i) { |
|
1143 M3Gint shift = |
|
1144 maxExp - m3gBlendVertex(mesh, i, |
|
1145 src[0], src[1], src[2], |
|
1146 posShift, |
|
1147 dst); |
|
1148 if (shift > 31) { |
|
1149 *dst++ = 0; |
|
1150 *dst++ = 0; |
|
1151 *dst++ = 0; |
|
1152 } |
|
1153 else { |
|
1154 *dst++ >>= shift; |
|
1155 *dst++ >>= shift; |
|
1156 *dst++ >>= shift; |
|
1157 } |
|
1158 |
|
1159 src += 3; |
|
1160 } |
|
1161 } |
|
1162 } |
|
1163 |
|
1164 /* Transform the normals (if enabled). Normals will be |
|
1165 * normalized when rendering, so no need to keep track of |
|
1166 * scales here */ |
|
1167 |
|
1168 if (srcNormals) { |
|
1169 M3Gbyte *dst = dstNormals; |
|
1170 |
|
1171 if (srcVB->normals->elementType == GL_BYTE) { |
|
1172 const M3Gbyte *src = (const M3Gbyte*) srcNormals; |
|
1173 for (i = 0; i < vertexCount; ++i) { |
|
1174 m3gBlendNormal(mesh, i, |
|
1175 src[0], src[1], src[2], |
|
1176 normShift, |
|
1177 dst); |
|
1178 src += 4; /* byte data padded to 32 bits */ |
|
1179 dst += 4; |
|
1180 } |
|
1181 } |
|
1182 else { |
|
1183 const M3Gshort *src = (const M3Gshort*) srcNormals; |
|
1184 for (i = 0; i < vertexCount; ++i) { |
|
1185 m3gBlendNormal(mesh, i, |
|
1186 src[0], src[1], src[2], |
|
1187 normShift, |
|
1188 dst); |
|
1189 src += 3; |
|
1190 dst += 4; |
|
1191 } |
|
1192 } |
|
1193 } |
|
1194 |
|
1195 /* Finally, handle the remaining vertices, which have no bones |
|
1196 * attached; these just need to have the scale and bias |
|
1197 * applied */ |
|
1198 |
|
1199 vertexCount = m3gGetNumVertices(srcVB); |
|
1200 if (i < vertexCount) { |
|
1201 |
|
1202 M3Gint startIndex = i; |
|
1203 M3Gshort *dstPos = dstPositions + startIndex * 3; |
|
1204 M3Gshort temp[3]; |
|
1205 |
|
1206 if (srcVB->vertices->elementType == GL_BYTE) { |
|
1207 const M3Gbyte *src = ((const M3Gbyte*) srcPositions) + startIndex * 4; |
|
1208 for (i = startIndex ; i < vertexCount; ++i) { |
|
1209 M3Gint shift = |
|
1210 maxExp - m3gScaleAndBiasVertex(mesh, |
|
1211 src[0], src[1], src[2], |
|
1212 posShift, |
|
1213 temp); |
|
1214 *dstPos++ = (M3Gshort)(temp[0] >> shift); |
|
1215 *dstPos++ = (M3Gshort)(temp[1] >> shift); |
|
1216 *dstPos++ = (M3Gshort)(temp[2] >> shift); |
|
1217 src += 4; /* byte data, padded to 32 bits */ |
|
1218 } |
|
1219 } |
|
1220 else { |
|
1221 const M3Gshort *src = ((const M3Gshort*) srcPositions) + startIndex * 3; |
|
1222 for (i = startIndex ; i < vertexCount; ++i) { |
|
1223 M3Gint shift = |
|
1224 maxExp - m3gScaleAndBiasVertex(mesh, |
|
1225 src[0], src[1], src[2], |
|
1226 posShift, |
|
1227 temp); |
|
1228 *dstPos++ = (M3Gshort)(temp[0] >> shift); |
|
1229 *dstPos++ = (M3Gshort)(temp[1] >> shift); |
|
1230 *dstPos++ = (M3Gshort)(temp[2] >> shift); |
|
1231 src += 3; |
|
1232 } |
|
1233 } |
|
1234 |
|
1235 /* Byte normals can just use a memcopy, as we don't have |
|
1236 * to scale them at all; shorts will require a conversion, |
|
1237 * after prescaling with the normal upshift to avoid |
|
1238 * underflowing to zero */ |
|
1239 |
|
1240 if (srcNormals) { |
|
1241 M3Gbyte *dstNorm = dstNormals + startIndex * 4; |
|
1242 if (srcVB->normals->elementType == GL_BYTE) { |
|
1243 const M3Gbyte *src = |
|
1244 ((const M3Gbyte*) srcNormals) + startIndex * 4; |
|
1245 m3gCopy(dstNorm, src, (vertexCount - startIndex) * 4); |
|
1246 } |
|
1247 else { |
|
1248 const M3Gshort *src = |
|
1249 ((const M3Gshort*) srcNormals) + startIndex * 3; |
|
1250 for (i = startIndex ; i < vertexCount; ++i) { |
|
1251 *dstNorm++ = (M3Gbyte)((*src++ << normShift) >> 8); |
|
1252 *dstNorm++ = (M3Gbyte)((*src++ << normShift) >> 8); |
|
1253 *dstNorm++ = (M3Gbyte)((*src++ << normShift) >> 8); |
|
1254 ++dstNorm; /* again, padding for byte values */ |
|
1255 } |
|
1256 } |
|
1257 } |
|
1258 } |
|
1259 |
|
1260 /* All done! Clean up and exit */ |
|
1261 |
|
1262 m3gUnmapVertexArray(srcVB->vertices); |
|
1263 m3gUnmapVertexArray(dstVB->vertices); |
|
1264 if (srcNormals) { |
|
1265 m3gUnmapVertexArray(srcVB->normals); |
|
1266 m3gUnmapVertexArray(dstVB->normals); |
|
1267 } |
|
1268 } |
|
1269 |
|
1270 /*! |
|
1271 * \internal |
|
1272 * \brief Overloaded Node method. |
|
1273 * |
|
1274 * Setup skinned mesh render. Call mesh render setup, |
|
1275 * do skinning calculations and traverse into the skeleton or the parent |
|
1276 * |
|
1277 * \param self SkinnedMesh object |
|
1278 * \param toCamera transform to camera |
|
1279 * \param alphaFactor total alpha factor |
|
1280 * \param caller caller node |
|
1281 * \param renderQueue RenderQueue |
|
1282 * |
|
1283 * \retval M3G_TRUE continue render setup |
|
1284 * \retval M3G_FALSE abort render setup |
|
1285 */ |
|
1286 static M3Gbool m3gSkinnedMeshSetupRender(Node *self, |
|
1287 const Node *caller, |
|
1288 SetupRenderState *s, |
|
1289 RenderQueue *renderQueue) |
|
1290 { |
|
1291 SkinnedMesh *mesh = (SkinnedMesh *)self; |
|
1292 Node *skeleton = (Node*) mesh->skeleton; |
|
1293 M3Gbool enabled, success = M3G_TRUE; |
|
1294 m3gIncStat(M3G_INTERFACE(self), M3G_STAT_RENDER_NODES, 1); |
|
1295 |
|
1296 /* Optimize the rendering-enable checking for top-down traversal */ |
|
1297 |
|
1298 enabled = (self->enableBits & NODE_RENDER_BIT) != 0; |
|
1299 if (caller != self->parent) { |
|
1300 enabled = m3gHasEnabledPath(self, renderQueue->root); |
|
1301 s->cullMask = CULLMASK_ALL; |
|
1302 } |
|
1303 |
|
1304 /* Handle self and the skeleton if enabled */ |
|
1305 |
|
1306 if (enabled) { |
|
1307 |
|
1308 /* Traverse into the skeleton unless coming from there */ |
|
1309 |
|
1310 if (skeleton != caller) { |
|
1311 SetupRenderState cs; |
|
1312 cs.cullMask = s->cullMask; |
|
1313 |
|
1314 M3G_BEGIN_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SETUP_TRANSFORMS); |
|
1315 m3gGetCompositeNodeTransform(skeleton, &cs.toCamera); |
|
1316 m3gPreMultiplyMatrix(&cs.toCamera, &s->toCamera); |
|
1317 M3G_END_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SETUP_TRANSFORMS); |
|
1318 |
|
1319 success = M3G_VFUNC(Node, skeleton, setupRender)(skeleton, |
|
1320 self, |
|
1321 &cs, |
|
1322 renderQueue); |
|
1323 } |
|
1324 |
|
1325 /* Handle self if in scope */ |
|
1326 |
|
1327 if ((self->scope & renderQueue->scope) != 0) { |
|
1328 |
|
1329 /* Try view frustum culling */ |
|
1330 |
|
1331 # if defined(M3G_ENABLE_VF_CULLING) |
|
1332 m3gUpdateCullingMask(s, renderQueue->camera, &mesh->bbox); |
|
1333 # endif |
|
1334 |
|
1335 if (s->cullMask == 0) { |
|
1336 m3gIncStat(M3G_INTERFACE(self), |
|
1337 M3G_STAT_RENDER_NODES_CULLED, 1); |
|
1338 } |
|
1339 else { |
|
1340 success &= m3gQueueMesh((Mesh*) self, &s->toCamera, renderQueue); |
|
1341 |
|
1342 if (success) { |
|
1343 M3G_BEGIN_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SKIN); |
|
1344 m3gSkinnedMeshMorph(mesh); |
|
1345 M3G_END_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SKIN); |
|
1346 } |
|
1347 } |
|
1348 } |
|
1349 } |
|
1350 |
|
1351 /* Traverse into the parent node unless coming from there. Again, |
|
1352 * discard the old traversal state at this point, as we're not |
|
1353 * coming back. */ |
|
1354 |
|
1355 if (success && self != renderQueue->root) { |
|
1356 Node *parent = self->parent; |
|
1357 if (parent != NULL && parent != caller) { |
|
1358 Matrix t; |
|
1359 |
|
1360 M3G_BEGIN_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SETUP_TRANSFORMS); |
|
1361 if (!m3gGetInverseNodeTransform(self, &t)) { |
|
1362 return M3G_FALSE; |
|
1363 } |
|
1364 m3gMulMatrix(&s->toCamera, &t); |
|
1365 M3G_END_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SETUP_TRANSFORMS); |
|
1366 |
|
1367 success = M3G_VFUNC(Node, parent, setupRender)(parent, |
|
1368 self, |
|
1369 s, |
|
1370 renderQueue); |
|
1371 } |
|
1372 } |
|
1373 |
|
1374 return success; |
|
1375 } |
|
1376 |
|
1377 /*! |
|
1378 * \internal |
|
1379 * \brief Overloaded Node method. |
|
1380 * |
|
1381 * Renders one skinned submesh. |
|
1382 * |
|
1383 * \param self SkinnedMesh object |
|
1384 * \param ctx current render context |
|
1385 * \param patchIndex submesh index |
|
1386 */ |
|
1387 static void m3gSkinnedMeshDoRender(Node *self, |
|
1388 RenderContext *ctx, |
|
1389 const Matrix *toCamera, |
|
1390 int patchIndex) |
|
1391 { |
|
1392 SkinnedMesh *mesh = (SkinnedMesh *)self; |
|
1393 IndexBuffer *indexBuffer = mesh->mesh.indexBuffers[patchIndex]; |
|
1394 Appearance *appearance = mesh->mesh.appearances[patchIndex]; |
|
1395 |
|
1396 if (indexBuffer == NULL || appearance == NULL) |
|
1397 return; |
|
1398 |
|
1399 m3gDrawMesh(ctx, |
|
1400 mesh->morphedVB, |
|
1401 indexBuffer, |
|
1402 appearance, |
|
1403 toCamera, |
|
1404 mesh->mesh.totalAlphaFactor + 1, |
|
1405 mesh->mesh.node.scope); |
|
1406 } |
|
1407 |
|
1408 /*! |
|
1409 * \internal |
|
1410 * \brief Overloaded Node method. |
|
1411 * |
|
1412 * Do skinning calculations and forward to Mesh internal ray intersect. |
|
1413 * |
|
1414 * \param self SkinnedMesh object |
|
1415 * \param mask pick scope mask |
|
1416 * \param ray pick ray |
|
1417 * \param ri RayIntersection object |
|
1418 * \param toGroup transform to originating group |
|
1419 * \retval M3G_TRUE continue pick |
|
1420 * \retval M3G_FALSE abort pick |
|
1421 */ |
|
1422 static M3Gbool m3gSkinnedMeshRayIntersect( Node *self, |
|
1423 M3Gint mask, |
|
1424 M3Gfloat *ray, |
|
1425 RayIntersection *ri, |
|
1426 Matrix *toGroup) |
|
1427 { |
|
1428 SkinnedMesh *mesh = (SkinnedMesh *)self; |
|
1429 M3G_BEGIN_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SKIN); |
|
1430 |
|
1431 if ((((Node *)mesh)->scope & mask) == 0) { |
|
1432 return M3G_TRUE; |
|
1433 } |
|
1434 |
|
1435 if (!m3gSkinnedMeshPreMorph(mesh)) { |
|
1436 return M3G_FALSE; |
|
1437 } |
|
1438 m3gSkinnedMeshMorph(mesh); |
|
1439 M3G_END_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_SKIN); |
|
1440 return m3gMeshRayIntersectInternal( &mesh->mesh, |
|
1441 mesh->morphedVB, |
|
1442 mask, |
|
1443 ray, |
|
1444 ri, |
|
1445 toGroup); |
|
1446 } |
|
1447 |
|
1448 /*! |
|
1449 * \internal |
|
1450 * \brief Overloaded Object3D method. |
|
1451 * |
|
1452 * \param self SkinnedMesh object |
|
1453 * \param time current world time |
|
1454 * \return minimum validity |
|
1455 */ |
|
1456 static M3Gint m3gSkinnedMeshApplyAnimation(Object *self, M3Gint time) |
|
1457 { |
|
1458 SkinnedMesh *mesh = (SkinnedMesh *)self; |
|
1459 |
|
1460 M3Gint validity = m3gMeshApplyAnimation((Object*) &mesh->mesh, time); |
|
1461 |
|
1462 if (validity > 0) { |
|
1463 M3Gint validity2 = |
|
1464 M3G_VFUNC(Object, mesh->skeleton, applyAnimation)( |
|
1465 (Object *)mesh->skeleton, time); |
|
1466 return (validity < validity2 ? validity : validity2); |
|
1467 } |
|
1468 return 0; |
|
1469 } |
|
1470 |
|
1471 /*! |
|
1472 * \internal |
|
1473 * \brief Overloaded Object3D method. |
|
1474 * |
|
1475 * \param self SkinnedMesh object |
|
1476 * \param references array of reference objects |
|
1477 * \return number of references |
|
1478 */ |
|
1479 static M3Gint m3gSkinnedMeshDoGetReferences(Object *self, Object **references) |
|
1480 { |
|
1481 SkinnedMesh *smesh = (SkinnedMesh *)self; |
|
1482 M3Gint num = m3gMeshDoGetReferences(self, references); |
|
1483 if (smesh->skeleton != NULL) |
|
1484 { |
|
1485 if (references != NULL) |
|
1486 references[num] = (Object *)smesh->skeleton; |
|
1487 num++; |
|
1488 } |
|
1489 return num; |
|
1490 } |
|
1491 |
|
1492 /*! |
|
1493 * \internal |
|
1494 * \brief Overloaded Object3D method. |
|
1495 */ |
|
1496 static Object *m3gSkinnedMeshFindID(Object *self, M3Gint userID) |
|
1497 { |
|
1498 SkinnedMesh *smesh = (SkinnedMesh *)self; |
|
1499 Object *found = m3gMeshFindID(self, userID); |
|
1500 |
|
1501 if (!found && smesh->skeleton != NULL) { |
|
1502 found = m3gFindID((Object*) smesh->skeleton, userID); |
|
1503 } |
|
1504 return found; |
|
1505 } |
|
1506 |
|
1507 /*! |
|
1508 * \internal |
|
1509 * \brief Overloaded Object3D method. |
|
1510 * |
|
1511 * \param originalObj original SkinnedMesh object |
|
1512 * \param cloneObj pointer to cloned SkinnedMesh object |
|
1513 * \param pairs array for all object-duplicate pairs |
|
1514 * \param numPairs number of pairs |
|
1515 */ |
|
1516 static M3Gbool m3gSkinnedMeshDuplicate(const Object *originalObj, |
|
1517 Object **cloneObj, |
|
1518 Object **pairs, |
|
1519 M3Gint *numPairs) |
|
1520 { |
|
1521 M3Gint i; |
|
1522 SkinnedMesh *original = (SkinnedMesh *)originalObj; |
|
1523 Group *skeleton = NULL; |
|
1524 SkinnedMesh *clone; |
|
1525 M3G_ASSERT(*cloneObj == NULL); /* no derived classes */ |
|
1526 |
|
1527 /* Duplicate the skeleton group first, as this is a prerequisite |
|
1528 * for creating the clone SkinnedMesh. If this fails, we must |
|
1529 * manually delete the skeleton, as no record of it will be stored |
|
1530 * anywhere else; we also need to hold a reference until ownership |
|
1531 * of the skeleton transfers to the clone SkinnedMesh. */ |
|
1532 |
|
1533 if (!M3G_VFUNC(Object, original->skeleton, duplicate)( |
|
1534 (Object*) original->skeleton, |
|
1535 (Object**) &skeleton, pairs, numPairs)) { |
|
1536 m3gDeleteObject((Object*) skeleton); |
|
1537 return M3G_FALSE; |
|
1538 } |
|
1539 m3gAddRef((Object*) skeleton); /* don't leave this floating */ |
|
1540 |
|
1541 /* Create the actual clone object */ |
|
1542 |
|
1543 clone = (SkinnedMesh*) |
|
1544 m3gCreateSkinnedMesh(originalObj->interface, |
|
1545 original->mesh.vertexBuffer, |
|
1546 original->mesh.indexBuffers, |
|
1547 original->mesh.appearances, |
|
1548 original->mesh.trianglePatchCount, |
|
1549 skeleton); |
|
1550 m3gDeleteRef((Object*) skeleton); /* ownership transferred to clone */ |
|
1551 if (!clone) { |
|
1552 return M3G_FALSE; |
|
1553 } |
|
1554 *cloneObj = (Object *)clone; |
|
1555 |
|
1556 /* Duplicate base class data; we're OK for normal deletion at this |
|
1557 * point, so can just leave it up to the caller on failure */ |
|
1558 |
|
1559 if (!m3gMeshDuplicate(originalObj, cloneObj, pairs, numPairs)) { |
|
1560 return M3G_FALSE; |
|
1561 } |
|
1562 |
|
1563 /* Duplicate the rest of our own data */ |
|
1564 |
|
1565 if (!m3gEnsureVertexCount(clone, original->weightedVertexCount) || |
|
1566 !m3gEnsureBonesPerVertex(clone, original->bonesPerVertex)) { |
|
1567 return M3G_FALSE; /* out of memory */ |
|
1568 } |
|
1569 |
|
1570 for (i = 0; i < clone->bonesPerVertex; i++) { |
|
1571 m3gCopy(clone->boneIndices[i], original->boneIndices[i], |
|
1572 clone->weightedVertexCount); |
|
1573 m3gCopy(clone->boneWeights[i], original->boneWeights[i], |
|
1574 clone->weightedVertexCount); |
|
1575 m3gCopy(clone->normalizedWeights[i], original->normalizedWeights[i], |
|
1576 clone->weightedVertexCount); |
|
1577 } |
|
1578 clone->weightsDirty = original->weightsDirty; |
|
1579 m3gCopy(clone->weightShifts, original->weightShifts, |
|
1580 clone->weightedVertexCount); |
|
1581 |
|
1582 for (i = 0; i < m3gArraySize(&original->bones); i++) { |
|
1583 Bone *cloneBone = (Bone*) m3gAllocZ(originalObj->interface, |
|
1584 sizeof(Bone)); |
|
1585 if (!cloneBone) { |
|
1586 return M3G_FALSE; /* out of memory */ |
|
1587 } |
|
1588 /* this line looks odd, but really just copies the *contents* |
|
1589 * of the bone structure... */ |
|
1590 *cloneBone = *(Bone*)m3gGetArrayElement(&original->bones, i); |
|
1591 |
|
1592 if (m3gArrayAppend(&clone->bones, cloneBone, originalObj->interface) < 0) { |
|
1593 m3gFree(originalObj->interface, cloneBone); |
|
1594 return M3G_FALSE; /* out of memory */ |
|
1595 } |
|
1596 } |
|
1597 |
|
1598 return M3G_TRUE; |
|
1599 } |
|
1600 |
|
1601 /*! |
|
1602 * \internal |
|
1603 * \brief Overloaded Node method |
|
1604 */ |
|
1605 static M3Gint m3gSkinnedMeshGetBBox(Node *self, AABB *bbox) |
|
1606 { |
|
1607 SkinnedMesh *mesh = (SkinnedMesh*) self; |
|
1608 Node *skeleton = (Node*) mesh->skeleton; |
|
1609 |
|
1610 /* First update our local bounding box if necessary */ |
|
1611 |
|
1612 if (self->dirtyBits & NODE_BBOX_BIT) { |
|
1613 |
|
1614 /* Compute an estimated bounding box from the morphed vertex |
|
1615 * buffer scale and bias (from PreComputeTransformations). |
|
1616 * The morphed vertex array is always scaled to utilize most |
|
1617 * of the 16-bit short range, so we just use that as the |
|
1618 * extents. */ |
|
1619 { |
|
1620 const GLfloat scale = mesh->morphedVB->vertexScale; |
|
1621 const GLfloat *bias = mesh->morphedVB->vertexBias; |
|
1622 int i; |
|
1623 |
|
1624 for (i = 0; i < 3; ++i) { |
|
1625 mesh->bbox.min[i] = m3gMadd(scale, -1 << 15, bias[i]); |
|
1626 mesh->bbox.max[i] = m3gMadd(scale, (1 << 15) - 1, bias[i]); |
|
1627 } |
|
1628 } |
|
1629 } |
|
1630 *bbox = mesh->bbox; |
|
1631 |
|
1632 /* Mix in the skeleton bounding box if we need to -- but only into |
|
1633 * the output bbox, as we're handling the local mesh bbox |
|
1634 * specially in SetupRender! */ |
|
1635 |
|
1636 if (skeleton->hasRenderables && skeleton->enableBits) { |
|
1637 AABB skeletonBBox; |
|
1638 if (m3gGetNodeBBox(skeleton, &skeletonBBox)) { |
|
1639 Matrix t; |
|
1640 m3gGetCompositeNodeTransform(self, &t); |
|
1641 m3gTransformAABB(&skeletonBBox, &t); |
|
1642 m3gFitAABB(bbox, &skeletonBBox, bbox); |
|
1643 } |
|
1644 } |
|
1645 return m3gArraySize(&mesh->bones) * VFC_NODE_OVERHEAD; |
|
1646 } |
|
1647 |
|
1648 /*! |
|
1649 * \internal |
|
1650 * \brief Overloaded Node method |
|
1651 */ |
|
1652 static M3Gbool m3gSkinnedMeshValidate(Node *self, M3Gbitmask stateBits, M3Gint scope) |
|
1653 { |
|
1654 SkinnedMesh *mesh = (SkinnedMesh*) self; |
|
1655 Interface *m3g = M3G_INTERFACE(mesh); |
|
1656 Node *skeleton = (Node*) mesh->skeleton; |
|
1657 const VertexBuffer *srcVB = mesh->mesh.vertexBuffer; |
|
1658 M3Gint vertexCount = mesh->weightedVertexCount; |
|
1659 |
|
1660 if ((scope & self->scope) != 0) { |
|
1661 if (stateBits & self->enableBits) { |
|
1662 |
|
1663 /* Check for invalid SkinnedMesh state */ |
|
1664 |
|
1665 if (srcVB->vertices == NULL || vertexCount > srcVB->vertexCount) { |
|
1666 m3gRaiseError(m3g, M3G_INVALID_OPERATION); |
|
1667 return M3G_FALSE; |
|
1668 } |
|
1669 if (!m3gSkinnedMeshUpdateVB(mesh)) { /* Memory allocation failed */ |
|
1670 return M3G_FALSE; |
|
1671 } |
|
1672 |
|
1673 /* Validate the skeleton */ |
|
1674 |
|
1675 if (!m3gValidateNode(skeleton, stateBits, scope)) { |
|
1676 return M3G_FALSE; |
|
1677 } |
|
1678 |
|
1679 /* Validate our local state */ |
|
1680 |
|
1681 if ((self->dirtyBits & NODE_TRANSFORMS_BIT) != 0 || |
|
1682 m3gGetTimestamp(srcVB) != mesh->mesh.vbTimestamp) { |
|
1683 if (!m3gSkinnedMeshPreMorph((SkinnedMesh*) self)) { |
|
1684 return M3G_FALSE; |
|
1685 } |
|
1686 } |
|
1687 if (self->dirtyBits & NODE_BBOX_BIT) { |
|
1688 M3G_BEGIN_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_VFC_UPDATE); |
|
1689 m3gGetNodeBBox(self, &mesh->bbox); |
|
1690 M3G_END_PROFILE(M3G_INTERFACE(self), M3G_PROFILE_VFC_UPDATE); |
|
1691 } |
|
1692 |
|
1693 return m3gMeshValidate(self, stateBits, scope); |
|
1694 } |
|
1695 } |
|
1696 return M3G_TRUE; |
|
1697 } |
|
1698 |
|
1699 /*! |
|
1700 * \internal |
|
1701 * \brief Overloaded Object3D method. |
|
1702 * |
|
1703 * \param self SkinnedMesh object |
|
1704 * \param pairs array for all object-duplicate pairs |
|
1705 * \param numPairs number of pairs |
|
1706 */ |
|
1707 static void m3gSkinnedMeshUpdateDuplicateReferences(Node *self, Object **pairs, M3Gint numPairs) |
|
1708 { |
|
1709 SkinnedMesh *skinned = (SkinnedMesh *)self; |
|
1710 SkinnedMesh *duplicate = (SkinnedMesh *)m3gGetDuplicatedInstance(self, pairs, numPairs); |
|
1711 M3Gint i, n; |
|
1712 |
|
1713 m3gNodeUpdateDuplicateReferences(self, pairs, numPairs); |
|
1714 |
|
1715 n = m3gArraySize(&duplicate->bones); |
|
1716 for (i = 0; i < n; i++) { |
|
1717 Bone *bone = (Bone*) m3gGetArrayElement(&duplicate->bones, i); |
|
1718 Node *boneDuplicate = m3gGetDuplicatedInstance(bone->node, pairs, numPairs); |
|
1719 if (boneDuplicate != NULL) { |
|
1720 bone->node = boneDuplicate; |
|
1721 } |
|
1722 } |
|
1723 |
|
1724 M3G_VFUNC(Node, skinned->skeleton, updateDuplicateReferences)( |
|
1725 (Node *)skinned->skeleton, pairs, numPairs); |
|
1726 } |
|
1727 |
|
1728 /*! |
|
1729 * \internal |
|
1730 * \brief Initializes a SkinnedMesh object. See specification |
|
1731 * for default values. |
|
1732 * |
|
1733 * \param m3g M3G interface |
|
1734 * \param mesh SkinnedMesh object |
|
1735 * \param hVertices VertexBuffer object |
|
1736 * \param hTriangles array of IndexBuffer objects |
|
1737 * \param hAppearances array of Appearance objects |
|
1738 * \param trianglePatchCount number of submeshes |
|
1739 * \param hSkeleton Group containing the skeleton |
|
1740 * \retval M3G_TRUE success |
|
1741 * \retval M3G_FALSE failure |
|
1742 */ |
|
1743 static M3Gbool m3gInitSkinnedMesh(Interface *m3g, |
|
1744 SkinnedMesh *mesh, |
|
1745 M3GVertexBuffer hVertices, |
|
1746 M3GIndexBuffer *hTriangles, |
|
1747 M3GAppearance *hAppearances, |
|
1748 M3Gint trianglePatchCount, |
|
1749 M3GGroup hSkeleton) |
|
1750 { |
|
1751 /* SkinnedMesh is derived from Mesh */ |
|
1752 if (!m3gInitMesh(m3g, &mesh->mesh, |
|
1753 hVertices, hTriangles, hAppearances, |
|
1754 trianglePatchCount, |
|
1755 M3G_CLASS_SKINNED_MESH)) |
|
1756 { |
|
1757 return M3G_FALSE; |
|
1758 } |
|
1759 |
|
1760 /* Make sure our mesh gets blended even if no bones are added */ |
|
1761 ((Node*)mesh)->dirtyBits |= NODE_TRANSFORMS_BIT; |
|
1762 |
|
1763 /* Set default values, see RI SkinnedMesh.java for reference */ |
|
1764 m3gSetParent(&((Group *)hSkeleton)->node, &mesh->mesh.node); |
|
1765 M3G_ASSIGN_REF(mesh->skeleton, (Group *)hSkeleton); |
|
1766 |
|
1767 m3gInitArray(&mesh->bones); |
|
1768 |
|
1769 mesh->morphedVB = (VertexBuffer *)m3gCreateVertexBuffer(m3g); |
|
1770 if (mesh->morphedVB == NULL |
|
1771 || m3gSkinnedMeshUpdateVB(mesh) == M3G_FALSE) { |
|
1772 |
|
1773 /* We're sufficiently initialized at this point that the |
|
1774 * destructor can be called for cleaning up */ |
|
1775 |
|
1776 m3gDestroySkinnedMesh((Object *)mesh); |
|
1777 return M3G_FALSE; |
|
1778 } |
|
1779 return M3G_TRUE; |
|
1780 } |
|
1781 |
|
1782 /*---------------------------------------------------------------------- |
|
1783 * Virtual function table |
|
1784 *--------------------------------------------------------------------*/ |
|
1785 |
|
1786 static const NodeVFTable m3gvf_SkinnedMesh = { |
|
1787 { |
|
1788 { |
|
1789 m3gSkinnedMeshApplyAnimation, |
|
1790 m3gNodeIsCompatible, |
|
1791 m3gNodeUpdateProperty, |
|
1792 m3gSkinnedMeshDoGetReferences, |
|
1793 m3gSkinnedMeshFindID, |
|
1794 m3gSkinnedMeshDuplicate, |
|
1795 m3gDestroySkinnedMesh |
|
1796 } |
|
1797 }, |
|
1798 m3gNodeAlign, |
|
1799 m3gSkinnedMeshDoRender, |
|
1800 m3gSkinnedMeshGetBBox, |
|
1801 m3gSkinnedMeshRayIntersect, |
|
1802 m3gSkinnedMeshSetupRender, |
|
1803 m3gSkinnedMeshUpdateDuplicateReferences, |
|
1804 m3gSkinnedMeshValidate |
|
1805 }; |
|
1806 |
|
1807 |
|
1808 /*---------------------------------------------------------------------- |
|
1809 * Public API functions |
|
1810 *--------------------------------------------------------------------*/ |
|
1811 |
|
1812 /*! |
|
1813 * \brief Creates a SkinnedMesh object. |
|
1814 * |
|
1815 * \param interface M3G interface |
|
1816 * \param hVertices VertexBuffer object |
|
1817 * \param hTriangles array of IndexBuffer objects |
|
1818 * \param hAppearances array of Appearance objects |
|
1819 * \param trianglePatchCount number of submeshes |
|
1820 * \param hSkeleton Group containing the skeleton |
|
1821 * \retval SkinnedMesh new SkinnedMesh object |
|
1822 * \retval NULL SkinnedMesh creating failed |
|
1823 */ |
|
1824 M3G_API M3GSkinnedMesh m3gCreateSkinnedMesh(M3GInterface interface, |
|
1825 M3GVertexBuffer hVertices, |
|
1826 M3GIndexBuffer *hTriangles, |
|
1827 M3GAppearance *hAppearances, |
|
1828 M3Gint trianglePatchCount, |
|
1829 M3GGroup hSkeleton) |
|
1830 { |
|
1831 Interface *m3g = (Interface *) interface; |
|
1832 M3G_VALIDATE_INTERFACE(m3g); |
|
1833 { |
|
1834 SkinnedMesh *mesh = NULL; |
|
1835 Group *skeleton = (Group *) hSkeleton; |
|
1836 if (skeleton == NULL) { |
|
1837 m3gRaiseError(m3g, M3G_NULL_POINTER); |
|
1838 return NULL; |
|
1839 } |
|
1840 if (skeleton->node.parent != NULL || |
|
1841 M3G_CLASS(skeleton) == M3G_CLASS_WORLD) { |
|
1842 m3gRaiseError(m3g, M3G_INVALID_VALUE); |
|
1843 return NULL; |
|
1844 } |
|
1845 |
|
1846 mesh = m3gAllocZ(m3g, sizeof(SkinnedMesh)); |
|
1847 if (mesh) { |
|
1848 if (!m3gInitSkinnedMesh(m3g, mesh, |
|
1849 hVertices, hTriangles, hAppearances, |
|
1850 trianglePatchCount, |
|
1851 hSkeleton)) { |
|
1852 m3gFree(m3g, mesh); |
|
1853 return NULL; |
|
1854 } |
|
1855 } |
|
1856 return (M3GSkinnedMesh)mesh; |
|
1857 } |
|
1858 } |
|
1859 |
|
1860 /*! |
|
1861 * \brief Add new weighted transformation (bone) to range of vertices |
|
1862 * |
|
1863 * |
|
1864 * \param handle SkinnedMesh object |
|
1865 * \param hNode bone to transform the vertices with |
|
1866 * \param weight weight of the bone |
|
1867 * \param firstVertex index to the first affected vertex |
|
1868 * \param numVertices number of affected vertices |
|
1869 */ |
|
1870 M3G_API void m3gAddTransform(M3GSkinnedMesh handle, |
|
1871 M3GNode hNode, |
|
1872 M3Gint weight, |
|
1873 M3Gint firstVertex, M3Gint numVertices) |
|
1874 { |
|
1875 SkinnedMesh *mesh = (SkinnedMesh *)handle; |
|
1876 Node *boneNode = (Node *)hNode; |
|
1877 Interface *m3g = M3G_INTERFACE(mesh); |
|
1878 |
|
1879 M3Gint lastVertex = firstVertex + numVertices; |
|
1880 M3G_VALIDATE_OBJECT(mesh); |
|
1881 |
|
1882 /* Check for errors */ |
|
1883 |
|
1884 if (!boneNode) { |
|
1885 m3gRaiseError(m3g, M3G_NULL_POINTER); |
|
1886 return; |
|
1887 } |
|
1888 M3G_VALIDATE_OBJECT(boneNode); |
|
1889 if (!m3gIsChildOf((const Node*) mesh, boneNode) |
|
1890 || numVertices <= 0 || weight <= 0) { |
|
1891 m3gRaiseError(m3g, M3G_INVALID_VALUE); |
|
1892 return; |
|
1893 } |
|
1894 if (firstVertex < 0 || lastVertex > 65535) { |
|
1895 m3gRaiseError(m3g, M3G_INVALID_INDEX); |
|
1896 return; |
|
1897 } |
|
1898 |
|
1899 /* Make sure we have enough per-vertex data */ |
|
1900 |
|
1901 if (!m3gEnsureVertexCount(mesh, lastVertex)) { |
|
1902 return; /* out of memory */ |
|
1903 } |
|
1904 |
|
1905 /* Check whether we may need to increase the number of bone |
|
1906 * entries per vertex, or whether we're already maxed out */ |
|
1907 |
|
1908 if (mesh->bonesPerVertex < M3G_MAX_VERTEX_TRANSFORMS) { |
|
1909 |
|
1910 /* Scan the input vertex range to find the maximum number of |
|
1911 * transforms per vertex (with non-zero weights) already in |
|
1912 * use, then make sure we can fit one more */ |
|
1913 |
|
1914 int numBones = mesh->bonesPerVertex; |
|
1915 int maxBones = 0; |
|
1916 |
|
1917 int vertex; |
|
1918 for (vertex = firstVertex; vertex < lastVertex; ++vertex) { |
|
1919 int k; |
|
1920 for (k = numBones; k > 0; --k) { |
|
1921 if (mesh->boneWeights[k-1][vertex] > 0) { |
|
1922 maxBones = M3G_MAX(maxBones, k); |
|
1923 break; |
|
1924 } |
|
1925 } |
|
1926 } |
|
1927 if (!m3gEnsureBonesPerVertex(mesh, maxBones + 1)) { |
|
1928 return; /* out of memory */ |
|
1929 } |
|
1930 } |
|
1931 |
|
1932 /* Get a bone record for the bone node, and add the bone influence |
|
1933 * to all affected vertices */ |
|
1934 { |
|
1935 int i; |
|
1936 |
|
1937 M3Gint boneIndex = m3gBoneIndex(mesh, boneNode); |
|
1938 if (boneIndex < 0) { |
|
1939 return; /* out of memory */ |
|
1940 } |
|
1941 |
|
1942 for (i = firstVertex; i < lastVertex; i++) { |
|
1943 m3gAddInfluence(mesh, i, boneIndex, weight); |
|
1944 } |
|
1945 } |
|
1946 |
|
1947 /* Update the bone flag for the bone node and its parents up to |
|
1948 * the SkinnedMesh node */ |
|
1949 |
|
1950 while (boneNode != (Node*) mesh) { /* boneNode must be a child of ours */ |
|
1951 M3G_ASSERT(boneNode); |
|
1952 boneNode->hasBones = M3G_TRUE; |
|
1953 boneNode = boneNode->parent; |
|
1954 } |
|
1955 } |
|
1956 |
|
1957 /*! |
|
1958 * \brief Getter for skeleton. |
|
1959 * |
|
1960 * \param handle SkinnedMesh object |
|
1961 * \return Group object |
|
1962 */ |
|
1963 M3G_API M3GGroup m3gGetSkeleton(M3GSkinnedMesh handle) |
|
1964 { |
|
1965 SkinnedMesh *mesh = (SkinnedMesh *)handle; |
|
1966 M3G_VALIDATE_OBJECT(mesh); |
|
1967 |
|
1968 return mesh->skeleton; |
|
1969 } |
|
1970 |
|
1971 /*! |
|
1972 * \brief Getter for bone transform. |
|
1973 * |
|
1974 * \param handle SkinnedMesh object |
|
1975 * \param hBone Bone |
|
1976 * \param transform Transform |
|
1977 */ |
|
1978 M3G_API void m3gGetBoneTransform(M3GSkinnedMesh handle, |
|
1979 M3GNode hBone, |
|
1980 M3GMatrix *transform) |
|
1981 { |
|
1982 SkinnedMesh *mesh = (SkinnedMesh *)handle; |
|
1983 Node *node = (Node *)hBone; |
|
1984 M3Gint i; |
|
1985 M3Gint boneCount; |
|
1986 |
|
1987 M3G_VALIDATE_OBJECT(mesh); |
|
1988 M3G_VALIDATE_OBJECT(node); |
|
1989 |
|
1990 if (!m3gIsChildOf((Node*) mesh->skeleton, node)) { |
|
1991 m3gRaiseError(M3G_INTERFACE(mesh), M3G_INVALID_VALUE); |
|
1992 return; |
|
1993 } |
|
1994 |
|
1995 boneCount = m3gArraySize(&mesh->bones); |
|
1996 |
|
1997 for (i = 0; i < boneCount; ++i) { |
|
1998 Bone *bone = m3gGetArrayElement(&mesh->bones, i); |
|
1999 |
|
2000 if (bone->node == node) { |
|
2001 m3gCopyMatrix(transform, &bone->toBone); |
|
2002 break; |
|
2003 } |
|
2004 } |
|
2005 } |
|
2006 |
|
2007 /*! |
|
2008 * \brief Getter for bone vertices. |
|
2009 * |
|
2010 * \param handle SkinnedMesh object |
|
2011 * \param hBone Bone |
|
2012 * \param indices Influenced indices |
|
2013 * \param weights Weights |
|
2014 * \return Number of influenced vertices |
|
2015 */ |
|
2016 M3G_API M3Gint m3gGetBoneVertices(M3GSkinnedMesh handle, |
|
2017 M3GNode hBone, |
|
2018 M3Gint *indices, M3Gfloat *weights) |
|
2019 { |
|
2020 SkinnedMesh *mesh = (SkinnedMesh *)handle; |
|
2021 Node *node = (Node *)hBone; |
|
2022 M3Gint boneIndex, boneCount, count = 0; |
|
2023 |
|
2024 M3G_VALIDATE_OBJECT(mesh); |
|
2025 M3G_VALIDATE_OBJECT(node); |
|
2026 |
|
2027 /* Check for errors */ |
|
2028 |
|
2029 if (!m3gIsChildOf((Node*) mesh->skeleton, node)) { |
|
2030 m3gRaiseError(M3G_INTERFACE(mesh), M3G_INVALID_VALUE); |
|
2031 return 0; |
|
2032 } |
|
2033 |
|
2034 /* Find the bone index corresponding to our bone node */ |
|
2035 |
|
2036 boneCount = m3gArraySize(&mesh->bones); |
|
2037 |
|
2038 for (boneIndex = 0; boneIndex < boneCount; ++boneIndex) { |
|
2039 Bone *bone = m3gGetArrayElement(&mesh->bones, boneIndex); |
|
2040 if (bone->node == node) { |
|
2041 break; |
|
2042 } |
|
2043 } |
|
2044 |
|
2045 /* Loop over the vertices, outputting index-weight pairs for each |
|
2046 * vertex influenced by the bone */ |
|
2047 |
|
2048 if (boneIndex < boneCount) { |
|
2049 M3Gint i, j; |
|
2050 |
|
2051 for (i = 0; i < mesh->weightedVertexCount; ++i) { |
|
2052 for (j = 0; j < mesh->bonesPerVertex; ++j) { |
|
2053 if (mesh->boneIndices[j][i] == boneIndex && mesh->boneWeights[j][i] > 0) { |
|
2054 if (indices != NULL && weights != NULL) { |
|
2055 M3Gint k, sum = 0; |
|
2056 for (k = 0; k < mesh->bonesPerVertex; ++k) { |
|
2057 sum += mesh->boneWeights[k][i]; |
|
2058 } |
|
2059 indices[count] = i; |
|
2060 if (sum != 0) { |
|
2061 weights[count] = ((M3Gfloat) mesh->boneWeights[j][i]) / sum; |
|
2062 } |
|
2063 else { |
|
2064 weights[count] = 0; |
|
2065 } |
|
2066 } |
|
2067 ++count; |
|
2068 } |
|
2069 } |
|
2070 } |
|
2071 } |
|
2072 return count; |
|
2073 } |
|
2074 |