forked from 0ad/0ad
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:
parent
46b79f8a6d
commit
ede71ea791
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
CPlane::CPlane ()
|
||||
{
|
||||
m_Norm.Clear ();
|
||||
m_Dist = 0.0f;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 ();
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user