From b10534d224b86bfa8ce5a9cec1225fcf7c17bcb6 Mon Sep 17 00:00:00 2001 From: prefect Date: Fri, 28 Oct 2005 19:25:47 +0000 Subject: [PATCH] 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. --- source/graphics/Model.cpp | 30 ++++++++++++++++++++++++------ source/graphics/Model.h | 24 +++++++++++++++++++----- source/renderer/ModelRenderer.cpp | 30 +++++++++++++++++++++++------- source/renderer/Renderer.cpp | 2 ++ source/renderer/Renderer.h | 8 ++++++++ 5 files changed, 76 insertions(+), 18 deletions(-) diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 82524ac1f9..b27b377085 100755 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -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;iGetBones(); for (uint i=0;iGetNumBones();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 diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 5fa94224cf..35dd589fbc 100755 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -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 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; }; diff --git a/source/renderer/ModelRenderer.cpp b/source/renderer/ModelRenderer.cpp index 0d1f5fe9c3..967345647e 100644 --- a/source/renderer/ModelRenderer.cpp +++ b/source/renderer/ModelRenderer.cpp @@ -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; iGetInvBoneMatrices(); + 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::ScriptingInit("Renderer"); } diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h index 2d09ad99ab..2149e0f1fc 100755 --- a/source/renderer/Renderer.h +++ b/source/renderer/Renderer.h @@ -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;