Inline common vector/matrix operations, for performance.

Remove some redundant vector methods.
Compute skinning for positions and normals simultaneously.
(These changes reduce skinning cost by >50%.)

This was SVN commit r8170.
This commit is contained in:
Ykkrosh 2010-09-24 16:54:20 +00:00
parent 46b79f8a6d
commit ede71ea791
9 changed files with 157 additions and 158 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -89,6 +89,46 @@ CVector3D CModelDef::SkinNormal(const SModelVertex& vtx,
return result;
}
void CModelDef::SkinPointsAndNormals(
size_t numVertices,
const VertexArrayIterator<CVector3D>& Position,
const VertexArrayIterator<CVector3D>& Normal,
const SModelVertex* vertices,
const CMatrix3D newPoseMatrices[],
const CMatrix3D inverseBindMatrices[])
{
for (size_t j = 0; j < numVertices; ++j)
{
const SModelVertex vtx = vertices[j];
CVector3D pos(0, 0, 0);
CVector3D normal(0, 0, 0);
for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i)
{
CVector3D posBindSpace = inverseBindMatrices[vtx.m_Blend.m_Bone[i]].Transform(vtx.m_Coords);
CVector3D normBindSpace = inverseBindMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm);
CVector3D posWorldSpace = newPoseMatrices[vtx.m_Blend.m_Bone[i]].Transform(posBindSpace);
CVector3D normWorldSpace = newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(normBindSpace);
pos += posWorldSpace * vtx.m_Blend.m_Weight[i];
normal += normWorldSpace * vtx.m_Blend.m_Weight[i];
}
// If there was more than one influence, the result is probably not going
// to be of unit length (since it's a weighted sum of several independent
// unit vectors), so we need to normalise it.
// (It's fairly common to only have one influence, so it seems sensible to
// optimise that case a bit.)
if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence
normal.Normalize();
Position[j] = pos;
Normal[j] = normal;
}
}
// CModelDef Constructor
CModelDef::CModelDef()
: m_NumVertices(0), m_pVertices(0), m_NumFaces(0), m_pFaces(0), m_NumBones(0), m_Bones(0),

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -26,6 +26,7 @@
#include "maths/Vector3D.h"
#include "maths/Quaternion.h"
#include "lib/file/vfs/vfs_path.h"
#include "renderer/VertexArray.h"
#include <map>
class CBoneState;
@ -158,6 +159,19 @@ public:
static CVector3D SkinNormal(const SModelVertex& vtx,
const CMatrix3D newPoseMatrices[], const CMatrix3D inverseBindMatrices[]);
/**
* Transform vertices' positions and normals.
* (This is equivalent to looping over SkinPoint and SkinNormal,
* but slightly more efficient.)
*/
static void SkinPointsAndNormals(
size_t numVertices,
const VertexArrayIterator<CVector3D>& Position,
const VertexArrayIterator<CVector3D>& Normal,
const SModelVertex* vertices,
const CMatrix3D newPoseMatrices[],
const CMatrix3D inverseBindMatrices[]);
/**
* Register renderer private data. Use the key to
* distinguish between private data used by different render paths.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -340,22 +340,6 @@ CVector3D CMatrix3D::GetIn () const
return Temp;
}
//Transform a vector by this matrix
CVector3D CMatrix3D::Transform (const CVector3D &vector) const
{
CVector3D result;
Transform(vector,result);
return result;
}
void CMatrix3D::Transform(const CVector3D& vector,CVector3D& result) const
{
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
}
//Transform a vector by this matrix
CVector4D CMatrix3D::Transform(const CVector4D &vector) const
{
@ -372,21 +356,6 @@ void CMatrix3D::Transform(const CVector4D& vector,CVector4D& result) const
result[3] = _41*vector[0] + _42*vector[1] + _43*vector[2] + _44*vector[3];
}
//Only rotate (not translate) a vector by this matrix
CVector3D CMatrix3D::Rotate(const CVector3D& vector) const
{
CVector3D result;
Rotate(vector,result);
return result;
}
void CMatrix3D::Rotate(const CVector3D& vector,CVector3D& result) const
{
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
}
///////////////////////////////////////////////////////////////////////////////
// RotateTransposed: rotate a vector by the transpose of this matrix
CVector3D CMatrix3D::RotateTransposed(const CVector3D& vector) const

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -23,7 +23,8 @@
#ifndef INCLUDED_MATRIX3D
#define INCLUDED_MATRIX3D
class CVector3D;
#include "maths/Vector3D.h"
class CVector4D;
class CQuaternion;
@ -137,14 +138,39 @@ public:
CQuaternion GetRotation() const;
// transform a 3D vector by this matrix
void Transform(const CVector3D &vector,CVector3D& result) const;
CVector3D Transform(const CVector3D &vector) const;
// transform a 4D vector by this matrix
void Transform(const CVector4D &vector,CVector4D& result) const;
CVector4D Transform(const CVector4D &vector) const;
CVector3D Transform (const CVector3D &vector) const
{
CVector3D result;
Transform(vector, result);
return result;
}
void Transform(const CVector3D& vector, CVector3D& result) const
{
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
}
// rotate a vector by this matrix
void Rotate(const CVector3D& vector,CVector3D& result) const;
CVector3D Rotate(const CVector3D& vector) const;
CVector3D Rotate(const CVector3D& vector) const
{
CVector3D result;
Rotate(vector, result);
return result;
}
void Rotate(const CVector3D& vector, CVector3D& result) const
{
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
}
// transform a 4D vector by this matrix
void Transform(const CVector4D& vector,CVector4D& result) const;
CVector4D Transform(const CVector4D& vector) const;
// rotate a vector by the transpose of this matrix
void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
CVector3D RotateTransposed(const CVector3D& vector) const;

View File

@ -29,7 +29,6 @@
CPlane::CPlane ()
{
m_Norm.Clear ();
m_Dist = 0.0f;
}

View File

@ -23,14 +23,13 @@
const float EPSILON=0.0001f;
CQuaternion::CQuaternion()
CQuaternion::CQuaternion() :
m_W(1)
{
m_V.Clear();
m_W = 1;
}
CQuaternion::CQuaternion(float x, float y, float z, float w)
: m_V(x, y, z), m_W(w)
CQuaternion::CQuaternion(float x, float y, float z, float w) :
m_V(x, y, z), m_W(w)
{
}
@ -109,13 +108,13 @@ void CQuaternion::FromEulerAngles (float x, float y, float z)
sp = sinf(y * 0.5f);
sy = sinf(z * 0.5f);
QRoll.m_V.Set (sr,0,0);
QRoll.m_V = CVector3D(sr, 0, 0);
QRoll.m_W = cr;
QPitch.m_V.Set (0,sp,0);
QPitch.m_V = CVector3D(0, sp, 0);
QPitch.m_W = cp;
QYaw.m_V.Set (0,0,sy);
QYaw.m_V = CVector3D(0, 0, sy);
QYaw.m_W = cy;
(*this) = QYaw * QPitch * QRoll;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -45,77 +45,6 @@ int CVector3D::operator ! () const
return 1;
}
bool CVector3D::operator== (const CVector3D &vector) const
{
return (X == vector.X && Y == vector.Y && Z == vector.Z);
}
//vector addition
CVector3D CVector3D::operator + (const CVector3D &vector) const
{
return CVector3D(X+vector.X, Y+vector.Y, Z+vector.Z);
}
//vector addition/assignment
CVector3D &CVector3D::operator += (const CVector3D &vector)
{
X += vector.X;
Y += vector.Y;
Z += vector.Z;
return *this;
}
//vector subtraction
CVector3D CVector3D::operator - (const CVector3D &vector) const
{
return CVector3D(X-vector.X, Y-vector.Y, Z-vector.Z);
}
//vector negation
CVector3D CVector3D::operator-() const
{
return CVector3D(-X, -Y, -Z);
}
//vector subtrcation/assignment
CVector3D &CVector3D::operator -= (const CVector3D &vector)
{
X -= vector.X;
Y -= vector.Y;
Z -= vector.Z;
return *this;
}
//scalar multiplication
CVector3D CVector3D::operator * (float value) const
{
return CVector3D(X*value, Y*value, Z*value);
}
//scalar multiplication/assignment
CVector3D& CVector3D::operator *= (float value)
{
X *= value;
Y *= value;
Z *= value;
return *this;
}
void CVector3D::Set (float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
void CVector3D::Clear ()
{
X = Y = Z = 0.0f;
}
//Dot product
float CVector3D::Dot (const CVector3D &vector) const
{
return ( X * vector.X +
@ -123,7 +52,6 @@ float CVector3D::Dot (const CVector3D &vector) const
Z * vector.Z );
}
//Cross product
CVector3D CVector3D::Cross (const CVector3D &vector) const
{
CVector3D Temp;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -31,47 +31,74 @@ class CVector3D
float X, Y, Z;
public:
CVector3D () : X(0.0f), Y(0.0f), Z(0.0f) {}
CVector3D (float x, float y, float z) : X(x), Y(y), Z(z) {}
CVector3D (const CFixedVector3D& v);
CVector3D() : X(0.0f), Y(0.0f), Z(0.0f) {}
CVector3D(float x, float y, float z) : X(x), Y(y), Z(z) {}
CVector3D(const CFixedVector3D& v);
int operator!() const;
float& operator[](int index) { return *((&X)+index); }
const float& operator[](int index) const { return *((&X)+index); }
//vector equality (testing float equality, so please be careful if necessary)
bool operator== (const CVector3D &vector) const;
bool operator!= (const CVector3D &vector) const { return !operator==(vector); }
// vector equality (testing float equality, so please be careful if necessary)
bool operator==(const CVector3D &vector) const
{
return (X == vector.X && Y == vector.Y && Z == vector.Z);
}
//vector addition
CVector3D operator + (const CVector3D &vector) const ;
//vector addition/assignment
CVector3D &operator += (const CVector3D &vector);
bool operator!=(const CVector3D& vector) const
{
return !operator==(vector);
}
//vector subtraction
CVector3D operator - (const CVector3D &vector) const ;
//vector subtraction/assignment
CVector3D &operator -= (const CVector3D &vector);
//scalar multiplication
CVector3D operator * (float value) const ;
//scalar multiplication/assignment
CVector3D& operator *= (float value);
CVector3D operator+(const CVector3D& vector) const
{
return CVector3D(X + vector.X, Y + vector.Y, Z + vector.Z);
}
// negation
CVector3D operator-() const;
CVector3D& operator+=(const CVector3D& vector)
{
X += vector.X;
Y += vector.Y;
Z += vector.Z;
return *this;
}
CVector3D operator-(const CVector3D& vector) const
{
return CVector3D(X - vector.X, Y - vector.Y, Z - vector.Z);
}
CVector3D& operator-=(const CVector3D& vector)
{
X -= vector.X;
Y -= vector.Y;
Z -= vector.Z;
return *this;
}
CVector3D operator*(float value) const
{
return CVector3D(X * value, Y * value, Z * value);
}
CVector3D& operator*=(float value)
{
X *= value;
Y *= value;
Z *= value;
return *this;
}
CVector3D operator-() const
{
return CVector3D(-X, -Y, -Z);
}
public:
void Set (float x, float y, float z);
void Clear ();
//Dot product
float Dot (const CVector3D &vector) const;
//Cross product
CVector3D Cross (const CVector3D &vector) const;
//Returns length of the vector
float Length () const;
float LengthSquared () const;
void Normalize ();

View File

@ -86,11 +86,8 @@ void ModelRenderer::BuildPositionAndNormals(
return;
}
for (size_t j=0; j<numVertices; j++)
{
Position[j] = CModelDef::SkinPoint(vertices[j], model->GetAnimatedBoneMatrices(), model->GetInverseBindBoneMatrices());
Normal[j] = CModelDef::SkinNormal(vertices[j], model->GetAnimatedBoneMatrices(), model->GetInverseBindBoneMatrices());
}
CModelDef::SkinPointsAndNormals(numVertices, Position, Normal, vertices, model->GetAnimatedBoneMatrices(), model->GetInverseBindBoneMatrices());
}
else
{