Transform normals using the original bone matrix instead of the inverse of the
transpose. This assumes orthogonal transformations (which we have exclusively, as far as I can tell), but is significantly faster, because calculating the inverse is slow. This was SVN commit r3041.
This commit is contained in:
parent
b5c489e1d5
commit
b10534d224
@ -27,8 +27,8 @@
|
||||
// Constructor
|
||||
CModel::CModel()
|
||||
: m_Parent(0), m_Flags(0), m_Anim(0), m_AnimTime(0),
|
||||
m_BoneMatrices(0), m_InvBoneMatrices(0),
|
||||
m_PositionValid(false), m_ShadingColor(1,1,1,1)
|
||||
m_BoneMatrices(0), m_InvTranspBoneMatrices(0),
|
||||
m_PositionValid(false), m_InvTranspValid(false), m_ShadingColor(1,1,1,1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ CModel::~CModel()
|
||||
void CModel::ReleaseData()
|
||||
{
|
||||
delete[] m_BoneMatrices;
|
||||
delete[] m_InvBoneMatrices;
|
||||
delete[] m_InvTranspBoneMatrices;
|
||||
for (size_t i=0;i<m_Props.size();i++) {
|
||||
delete m_Props[i].m_Model;
|
||||
}
|
||||
@ -86,7 +86,7 @@ bool CModel::InitModel(CModelDefPtr modeldef)
|
||||
if (numBones != 0) {
|
||||
// allocate matrices for bone transformations
|
||||
m_BoneMatrices=new CMatrix3D[numBones];
|
||||
m_InvBoneMatrices=new CMatrix3D[numBones];
|
||||
m_InvTranspBoneMatrices=new CMatrix3D[numBones];
|
||||
// store default pose until animation assigned
|
||||
CBoneState* defpose=modeldef->GetBones();
|
||||
for (uint i=0;i<numBones;i++) {
|
||||
@ -94,7 +94,7 @@ bool CModel::InitModel(CModelDefPtr modeldef)
|
||||
m.SetIdentity();
|
||||
m.Rotate(defpose[i].m_Rotation);
|
||||
m.Translate(defpose[i].m_Translation);
|
||||
m.GetInverse(m_InvBoneMatrices[i]);
|
||||
m_InvTranspValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,11 +315,11 @@ void CModel::ValidatePosition()
|
||||
const CMatrix3D& transform=GetTransform();
|
||||
for (size_t i=0;i<m_pModelDef->GetNumBones();i++) {
|
||||
m_BoneMatrices[i].Concatenate(transform);
|
||||
m_BoneMatrices[i].GetInverse(m_InvBoneMatrices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
m_PositionValid = true;
|
||||
m_InvTranspValid = false;
|
||||
|
||||
// re-position and validate all props
|
||||
for (size_t j = 0; j < m_Props.size(); ++j)
|
||||
@ -338,6 +338,24 @@ void CModel::ValidatePosition()
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CalcInvTranspBoneMatrices
|
||||
void CModel::CalcInvTranspBoneMatrices()
|
||||
{
|
||||
debug_assert(m_BoneMatrices);
|
||||
|
||||
PROFILE( "invert transpose bone matrices" );
|
||||
|
||||
CMatrix3D tmp;
|
||||
for(size_t i = 0; i < m_pModelDef->GetNumBones(); ++i)
|
||||
{
|
||||
m_BoneMatrices[i].GetInverse(tmp);
|
||||
tmp.GetTranspose(m_InvTranspBoneMatrices[i]);
|
||||
}
|
||||
|
||||
m_InvTranspValid = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetAnimation: set the given animation as the current animation on this model;
|
||||
// return false on error, else true
|
||||
|
@ -105,10 +105,12 @@ public:
|
||||
debug_assert(m_PositionValid);
|
||||
return m_BoneMatrices;
|
||||
}
|
||||
// return the models inverted bone matrices
|
||||
const CMatrix3D* GetInvBoneMatrices() {
|
||||
// return the models inverted transposed bone matrices for normal transformation
|
||||
const CMatrix3D* GetInvTranspBoneMatrices() {
|
||||
debug_assert(m_PositionValid);
|
||||
return m_InvBoneMatrices;
|
||||
if (!m_InvTranspValid)
|
||||
CalcInvTranspBoneMatrices();
|
||||
return m_InvTranspBoneMatrices;
|
||||
}
|
||||
|
||||
// load raw animation frame animation from given file, and build a
|
||||
@ -142,6 +144,12 @@ private:
|
||||
*/
|
||||
void InvalidatePosition();
|
||||
|
||||
/**
|
||||
* CalcInvTranspBoneMatrices: Calc inverse transpose bone matrices
|
||||
* from bone matrices.
|
||||
*/
|
||||
void CalcInvTranspBoneMatrices();
|
||||
|
||||
/**
|
||||
* m_Parent: If non-null, m_Parent points to the model that we
|
||||
* are attached to.
|
||||
@ -170,8 +178,8 @@ private:
|
||||
float m_AnimTime;
|
||||
// current state of all bones on this model; null if associated modeldef isn't skeletal
|
||||
CMatrix3D* m_BoneMatrices;
|
||||
// inverse of the above world space transform of the above matrices
|
||||
CMatrix3D* m_InvBoneMatrices;
|
||||
// inverse of the transpose of the above matrices
|
||||
CMatrix3D* m_InvTranspBoneMatrices;
|
||||
// list of current props on model
|
||||
std::vector<Prop> m_Props;
|
||||
|
||||
@ -181,6 +189,12 @@ private:
|
||||
*/
|
||||
bool m_PositionValid;
|
||||
|
||||
/**
|
||||
* m_InvTranspValid: true if m_InvTranspBoneMatrices match the current
|
||||
* m_BoneMatrices
|
||||
*/
|
||||
bool m_InvTranspValid;
|
||||
|
||||
// modulating color
|
||||
CColor m_ShadingColor;
|
||||
};
|
||||
|
@ -52,7 +52,7 @@ static void SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices,CVect
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SkinPoint: skin the vertex normal using it's blend data and given bone matrices
|
||||
static void SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices,CVector3D& result)
|
||||
static void SkinNormal(const SModelVertex& vertex, const CMatrix3D* invtranspmatrices, CVector3D& result)
|
||||
{
|
||||
CVector3D tmp;
|
||||
const SVertexBlend& blend=vertex.m_Blend;
|
||||
@ -60,13 +60,13 @@ static void SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices,C
|
||||
// must have at least one valid bone if we're using SkinNormal
|
||||
debug_assert(blend.m_Bone[0]!=0xff);
|
||||
|
||||
const CMatrix3D& m=invmatrices[blend.m_Bone[0]];
|
||||
m.RotateTransposed(vertex.m_Norm,result);
|
||||
const CMatrix3D& m = invtranspmatrices[blend.m_Bone[0]];
|
||||
m.Rotate(vertex.m_Norm, result);
|
||||
result*=blend.m_Weight[0];
|
||||
|
||||
for (u32 i=1; i<SVertexBlend::SIZE && vertex.m_Blend.m_Bone[i]!=0xff; i++) {
|
||||
const CMatrix3D& m=invmatrices[blend.m_Bone[i]];
|
||||
m.RotateTransposed(vertex.m_Norm,tmp);
|
||||
const CMatrix3D& m = invtranspmatrices[blend.m_Bone[i]];
|
||||
m.Rotate(vertex.m_Norm,tmp);
|
||||
result+=tmp*blend.m_Weight[i];
|
||||
}
|
||||
}
|
||||
@ -89,11 +89,27 @@ void ModelRenderer::BuildPositionAndNormals(
|
||||
{
|
||||
// boned model - calculate skinned vertex positions/normals
|
||||
PROFILE( "skinning bones" );
|
||||
const CMatrix3D* invbonematrices = model->GetInvBoneMatrices();
|
||||
const CMatrix3D* invtranspbonematrices;
|
||||
|
||||
// Analytic geometry tells us that normal vectors need to be
|
||||
// multiplied by the inverse of the transpose. However, calculating
|
||||
// the inverse is slow, and analytic geometry also tells us that
|
||||
// for orthogonal matrices, the inverse is equal to the transpose,
|
||||
// so the inverse of the transpose is, in fact, the original matrix.
|
||||
//
|
||||
// The "fast normals" code assumes that bone transformation contain
|
||||
// no "weird" transformations like shears or non-uniform scaling
|
||||
// (actually, the entire code assumes no scaling) and thus gets
|
||||
// around the slow calculation of the inverse.
|
||||
if (g_Renderer.m_FastNormals)
|
||||
invtranspbonematrices = bonematrices;
|
||||
else
|
||||
invtranspbonematrices = model->GetInvTranspBoneMatrices();
|
||||
|
||||
for (size_t j=0; j<numVertices; j++)
|
||||
{
|
||||
SkinPoint(vertices[j],bonematrices,Position[j]);
|
||||
SkinNormal(vertices[j],invbonematrices,Normal[j]);
|
||||
SkinNormal(vertices[j],invtranspbonematrices,Normal[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -68,6 +68,7 @@ CRenderer::CRenderer()
|
||||
m_ShadowMap=0;
|
||||
|
||||
m_SortAllTransparent = false;
|
||||
m_FastNormals = true;
|
||||
|
||||
m_VertexShader = 0;
|
||||
|
||||
@ -1594,6 +1595,7 @@ void CRenderer::ScriptingInit()
|
||||
AddProperty(L"fastPlayerColor", &CRenderer::JSI_GetFastPlayerColor, &CRenderer::JSI_SetFastPlayerColor);
|
||||
AddProperty(L"renderpath", &CRenderer::JSI_GetRenderPath, &CRenderer::JSI_SetRenderPath);
|
||||
AddProperty(L"sortAllTransparent", &CRenderer::m_SortAllTransparent);
|
||||
AddProperty(L"fastNormals", &CRenderer::m_FastNormals);
|
||||
|
||||
CJSObject<CRenderer>::ScriptingInit("Renderer");
|
||||
}
|
||||
|
@ -396,6 +396,14 @@ protected:
|
||||
* batching renderer when possible.
|
||||
*/
|
||||
bool m_SortAllTransparent;
|
||||
|
||||
|
||||
/**
|
||||
* m_FastNormals: Use faster normal transformation in the
|
||||
* software transform by multiplying with the bone matrix itself
|
||||
* instead of the transpose of the inverse.
|
||||
*/
|
||||
bool m_FastNormals;
|
||||
|
||||
// State used by LoadWaterTextures with progressive loading
|
||||
uint cur_loading_water_tex;
|
||||
|
Loading…
Reference in New Issue
Block a user