-static int maxbonepose = 0;
-static float (*bonepose)[12] = NULL;
-
-void Mod_Skeletal_FreeBuffers(void)
-{
- if(bonepose)
- Mem_Free(bonepose);
- maxbonepose = 0;
- bonepose = NULL;
-}
-
-void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
-{
- // vertex weighted skeletal
- int i, k;
- int blends;
- float m[12];
- float (*boneposerelative)[12];
- const blendweights_t * RESTRICT weights;
-
- if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
- {
- if (bonepose)
- Mem_Free(bonepose);
- maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
- bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12]));
- }
-
- boneposerelative = bonepose + model->num_bones;
-
- if (skeleton && !skeleton->relativetransforms)
- skeleton = NULL;
-
- // interpolate matrices
- if (skeleton)
- {
- for (i = 0;i < model->num_bones;i++)
- {
- Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
- if (model->data_bones[i].parent >= 0)
- R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
- else
- memcpy(bonepose[i], m, sizeof(m));
-
- // create a relative deformation matrix to describe displacement
- // from the base mesh, which is used by the actual weighting
- R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
- }
- }
- else
- {
- float originscale = model->num_posescale;
- float x,y,z,w,lerp;
- const short * RESTRICT pose6s;
- for (i = 0;i < model->num_bones;i++)
- {
- memset(m, 0, sizeof(m));
- for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
- {
- pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
- lerp = frameblend[blends].lerp;
- x = pose6s[3] * (1.0f / 32767.0f);
- y = pose6s[4] * (1.0f / 32767.0f);
- z = pose6s[5] * (1.0f / 32767.0f);
- w = 1.0f - (x*x+y*y+z*z);
- w = w > 0.0f ? -sqrt(w) : 0.0f;
- m[ 0] += (1-2*(y*y+z*z)) * lerp;
- m[ 1] += ( 2*(x*y-z*w)) * lerp;
- m[ 2] += ( 2*(x*z+y*w)) * lerp;
- m[ 3] += (pose6s[0] * originscale) * lerp;
- m[ 4] += ( 2*(x*y+z*w)) * lerp;
- m[ 5] += (1-2*(x*x+z*z)) * lerp;
- m[ 6] += ( 2*(y*z-x*w)) * lerp;
- m[ 7] += (pose6s[1] * originscale) * lerp;
- m[ 8] += ( 2*(x*z-y*w)) * lerp;
- m[ 9] += ( 2*(y*z+x*w)) * lerp;
- m[10] += (1-2*(x*x+y*y)) * lerp;
- m[11] += (pose6s[2] * originscale) * lerp;
- }
- VectorNormalize(m );
- VectorNormalize(m + 4);
- VectorNormalize(m + 8);
- if (i == r_skeletal_debugbone.integer)
- m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
- m[3] *= r_skeletal_debugtranslatex.value;
- m[7] *= r_skeletal_debugtranslatey.value;
- m[11] *= r_skeletal_debugtranslatez.value;
- if (model->data_bones[i].parent >= 0)
- R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
- else
- memcpy(bonepose[i], m, sizeof(m));
- // create a relative deformation matrix to describe displacement
- // from the base mesh, which is used by the actual weighting
- R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
- }
- }
-
- // generate matrices for all blend combinations
- weights = model->surfmesh.data_blendweights;
- for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
- {
- float * RESTRICT b = boneposerelative[model->num_bones + i];
- const float * RESTRICT m = boneposerelative[weights->index[0]];
- float f = weights->influence[0] * (1.0f / 255.0f);
- b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
- b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
- b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
- for (k = 1;k < 4 && weights->influence[k];k++)
- {
- m = boneposerelative[weights->index[k]];
- f = weights->influence[k] * (1.0f / 255.0f);
- b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
- b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
- b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
- }
- }
-
- // transform vertex attributes by blended matrices
- if (vertex3f)
- {
- const float * RESTRICT v = model->surfmesh.data_vertex3f;
- const unsigned short * RESTRICT b = model->surfmesh.blends;
- // special case common combinations of attributes to avoid repeated loading of matrices
- if (normal3f)
- {
- const float * RESTRICT n = model->surfmesh.data_normal3f;
- if (svector3f && tvector3f)
- {
- const float * RESTRICT sv = model->surfmesh.data_svector3f;
- const float * RESTRICT tv = model->surfmesh.data_tvector3f;
- for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, b++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3)
- {
- const float * RESTRICT m = boneposerelative[*b];
- vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
- vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
- vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
- normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
- normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
- normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
- svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
- svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
- svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
- tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
- tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
- tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
- }
- return;
- }
- for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
- {
- const float * RESTRICT m = boneposerelative[*b];
- vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
- vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
- vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
- normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
- normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
- normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
- }
- }
- else
- {
- for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
- {
- const float * RESTRICT m = boneposerelative[*b];
- vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
- vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
- vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
- }
- }
- }
- else if (normal3f)
- {
- const float * RESTRICT n = model->surfmesh.data_normal3f;
- const unsigned short * RESTRICT b = model->surfmesh.blends;
- for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
- {
- const float * RESTRICT m = boneposerelative[*b];
- normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
- normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
- normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
- }
- }
-
- if (svector3f)
- {
- const float * RESTRICT sv = model->surfmesh.data_svector3f;
- const unsigned short * RESTRICT b = model->surfmesh.blends;
- for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
- {
- const float * RESTRICT m = boneposerelative[*b];
- svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
- svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
- svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
- }
- }
-
- if (tvector3f)
- {
- const float * RESTRICT tv = model->surfmesh.data_tvector3f;
- const unsigned short * RESTRICT b = model->surfmesh.blends;
- for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
- {
- const float * RESTRICT m = boneposerelative[*b];
- tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
- tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
- tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
- }
- }
-}
-