BGE Animations: BGEDeformVerts() now handles normals instead of relying on BL_MeshDeformer::RecalcNormals(), which BlenderDeformVerts() still uses. As expected, the BGEDeformVerts() version isn't as accurate, but it avoids a sqrt per vertex. This gives about a 15~20% improvement in time spent on the rasterizer in my test scene, which resulted in about 5 more fps. However, the main reason for the new normal code is it will be easier to do on the GPU (doesn't rely on neighbor information).

This commit is contained in:
Mitchell Stokes 2011-08-01 23:02:10 +00:00
parent 3e85ec432e
commit 03c1585e3a
2 changed files with 36 additions and 11 deletions

@ -80,6 +80,7 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj,
m_releaseobject(false),
m_poseApplied(false),
m_recalcNormal(true),
m_copyNormals(false),
m_dfnrToPC(NULL)
{
copy_m4_m4(m_obmat, bmeshobj->obmat);
@ -99,6 +100,7 @@ BL_SkinDeformer::BL_SkinDeformer(
//m_defbase(&bmeshobj_old->defbase),
m_releaseobject(release_object),
m_recalcNormal(recalc_normal),
m_copyNormals(false),
m_dfnrToPC(NULL)
{
// this is needed to ensure correct deformation of mesh:
@ -161,9 +163,14 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
for(i=it.startvertex; i<it.endvertex; i++) {
RAS_TexVert& v = it.vertex[i];
v.SetXYZ(m_transverts[v.getOrigIndex()]);
if (m_copyNormals)
v.SetNormal(m_transnors[v.getOrigIndex()]);
}
}
}
if (m_copyNormals)
m_copyNormals = false;
}
return true;
}
@ -200,6 +207,11 @@ void BL_SkinDeformer::BlenderDeformVerts()
// restore matrix
copy_m4_m4(m_objMesh->obmat, obmat);
#ifdef __NLA_DEFNORMALS
if (m_recalcNormal)
RecalcNormals();
#endif
}
void BL_SkinDeformer::BGEDeformVerts()
@ -230,15 +242,17 @@ void BL_SkinDeformer::BGEDeformVerts()
for (int i=0; i<m_bmesh->totvert; ++i)
{
float contrib = 0.f, weight;
float contrib = 0.f, weight, max_weight=0.f;
Bone *bone;
bPoseChannel *pchan=NULL;
MDeformVert *dvert;
Eigen::Vector4f co(0.f, 0.f, 0.f, 1.f);
Eigen::Map<Eigen::Vector3f> norm(m_transnors[i]);
Eigen::Vector4f vec(0, 0, 0, 1);
co[0] = m_transverts[i][0];
co[1] = m_transverts[i][1];
co[2] = m_transverts[i][2];
Eigen::Matrix4f norm_chan_mat;
Eigen::Vector4f co(m_transverts[i][0],
m_transverts[i][1],
m_transverts[i][2],
1.f);
dvert = dverts+i;
@ -259,15 +273,26 @@ void BL_SkinDeformer::BGEDeformVerts()
Eigen::Vector4f cop(co);
Eigen::Matrix4f chan_mat = Eigen::Matrix4f::Map((float*)pchan->chan_mat);
// Update Vertex Position
cop = chan_mat*cop;
vec += (cop - co)*weight;
// Save the most influential channel so we can use it to update the vertex normal
if (weight > max_weight)
{
max_weight = weight;
norm_chan_mat = chan_mat;
}
contrib += weight;
}
}
}
// Update Vertex Normal
norm = norm_chan_mat.corner<3, 3>(Eigen::TopLeft)*norm;
if (contrib > 0.0001f)
{
vec *= 1.f/contrib;
@ -278,6 +303,7 @@ void BL_SkinDeformer::BGEDeformVerts()
m_transverts[i][1] = co[1];
m_transverts[i][2] = co[2];
}
m_copyNormals = true;
}
bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
@ -291,7 +317,10 @@ bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
/* duplicate */
for (int v =0; v<m_bmesh->totvert; v++)
{
VECCOPY(m_transverts[v], m_bmesh->mvert[v].co);
VECCOPY(m_transnors[v], m_bmesh->mvert[v].no);
}
}
m_armobj->ApplyPose();
@ -306,11 +335,6 @@ bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
BlenderDeformVerts();
}
#ifdef __NLA_DEFNORMALS
if (m_recalcNormal)
RecalcNormals();
#endif
/* Update the current frame */
m_lastArmaUpdate=m_armobj->GetLastFrame();

@ -109,6 +109,7 @@ protected:
bool m_releaseobject;
bool m_poseApplied;
bool m_recalcNormal;
bool m_copyNormals; // dirty flag so we know if Apply() needs to copy normal information (used for BGEDeformVerts())
struct bPoseChannel** m_dfnrToPC;
void BlenderDeformVerts();