Added support for model skinning

This commit is contained in:
parax0
2016-04-27 04:27:57 -06:00
parent c5ff634cd1
commit 98059cedaa
81 changed files with 802 additions and 245 deletions

View File

@@ -160,6 +160,46 @@ void CModel::DrawWireframe(FRenderOptions Options, CColor WireColor /*= CColor::
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void CModel::SetSkin(CSkin *pSkin)
{
if (mpSkin != pSkin)
{
const FVertexDescription kBoneFlags = (eBoneIndices | eBoneWeights);
mpSkin = pSkin;
mVBO.SetSkin(pSkin);
ClearGLBuffer();
if (pSkin && !mVBO.VertexDesc().HasAllFlags(kBoneFlags))
mVBO.SetVertexDesc(mVBO.VertexDesc() | kBoneFlags);
else if (!pSkin && mVBO.VertexDesc().HasAnyFlags(kBoneFlags))
mVBO.SetVertexDesc(mVBO.VertexDesc() & ~kBoneFlags);
for (u32 iSet = 0; iSet < mMaterialSets.size(); iSet++)
{
CMaterialSet *pSet = mMaterialSets[iSet];
for (u32 iMat = 0; iMat < pSet->NumMaterials(); iMat++)
{
CMaterial *pMat = pSet->MaterialByIndex(iMat);
FVertexDescription VtxDesc = pMat->VtxDesc();
if (pSkin && !VtxDesc.HasAllFlags(kBoneFlags))
{
VtxDesc |= kBoneFlags;
pMat->SetVertexDescription(VtxDesc);
}
else if (!pSkin && VtxDesc.HasAnyFlags(kBoneFlags))
{
VtxDesc &= ~kBoneFlags;
pMat->SetVertexDescription(VtxDesc);
}
}
}
}
}
u32 CModel::GetMatSetCount()
{
return mMaterialSets.size();

View File

@@ -4,6 +4,7 @@
#include "CBasicModel.h"
#include "SSurface.h"
#include "Core/Resource/CMaterialSet.h"
#include "Core/Resource/CSkin.h"
#include "Core/OpenGL/CIndexBuffer.h"
#include "Core/OpenGL/GLCommon.h"
#include "Core/Render/FRenderOptions.h"
@@ -13,6 +14,7 @@ class CModel : public CBasicModel
friend class CModelLoader;
friend class CModelCooker;
TResPtr<CSkin> mpSkin;
std::vector<CMaterialSet*> mMaterialSets;
std::vector<std::vector<CIndexBuffer>> mSurfaceIndexBuffers;
bool mHasOwnMaterials;
@@ -28,6 +30,7 @@ public:
void Draw(FRenderOptions Options, u32 MatSet);
void DrawSurface(FRenderOptions Options, u32 Surface, u32 MatSet);
void DrawWireframe(FRenderOptions Options, CColor WireColor = CColor::skWhite);
void SetSkin(CSkin *pSkin);
u32 GetMatSetCount();
u32 GetMatCount();
@@ -37,6 +40,8 @@ public:
bool HasTransparency(u32 MatSet);
bool IsSurfaceTransparent(u32 Surface, u32 MatSet);
bool IsSkinned() const { return (mpSkin != nullptr); }
private:
CIndexBuffer* InternalGetIBO(u32 Surface, EGXPrimitiveType Primitive);
};

View File

@@ -4,6 +4,10 @@
#include <Common/CColor.h>
#include <Math/CVector2f.h>
#include <Math/CVector3f.h>
#include <array>
typedef std::array<u32, 4> TBoneIndices;
typedef std::array<float, 4> TBoneWeights;
class CVertex
{
@@ -14,6 +18,8 @@ public:
CVector3f Normal;
CColor Color[2];
CVector2f Tex[8];
TBoneIndices BoneIndices;
TBoneWeights BoneWeights;
u8 MatrixIndices[8];
CVertex() {}
@@ -35,7 +41,9 @@ public:
(Tex[4] == rkOther.Tex[4]) &&
(Tex[5] == rkOther.Tex[5]) &&
(Tex[6] == rkOther.Tex[6]) &&
(Tex[7] == rkOther.Tex[7]));
(Tex[7] == rkOther.Tex[7]) &&
(BoneIndices == rkOther.BoneIndices) &&
(BoneWeights == rkOther.BoneWeights));
}
};

View File

@@ -0,0 +1,32 @@
#include "EVertexAttribute.h"
#include <Common/Log.h>
const u32 gkNumVertexAttribs = 22;
u32 VertexAttributeSize(EVertexAttribute Attrib)
{
switch (Attrib)
{
case ePosition:
case eNormal:
return 0x0C;
case eColor0:
case eColor1:
case eBoneWeights:
return 0x10;
case eTex0:
case eTex1:
case eTex2:
case eTex3:
case eTex4:
case eTex5:
case eTex6:
case eTex7:
return 0x08;
case eBoneIndices:
return 0x04;
default:
Log::Error("AttributeSize(): Unknown vertex attribute: " + TString::FromInt32(Attrib, 0, 10));
return 0x00;
}
}

View File

@@ -6,28 +6,33 @@
enum EVertexAttribute
{
eNoAttributes = 0x0,
ePosition = 0x3,
eNormal = 0xC,
eColor0 = 0x30,
eColor1 = 0xC0,
eTex0 = 0x300,
eTex1 = 0xC00,
eTex2 = 0x3000,
eTex3 = 0xC000,
eTex4 = 0x30000,
eTex5 = 0xC0000,
eTex6 = 0x300000,
eTex7 = 0xC00000,
ePosMtx = 0x1000000,
eTex0Mtx = 0x2000000,
eTex1Mtx = 0x4000000,
eTex2Mtx = 0x8000000,
eTex3Mtx = 0x10000000,
eTex4Mtx = 0x20000000,
eTex5Mtx = 0x40000000,
eTex6Mtx = 0x80000000
ePosition = 0x1,
eNormal = 0x2,
eColor0 = 0x4,
eColor1 = 0x8,
eTex0 = 0x10,
eTex1 = 0x20,
eTex2 = 0x40,
eTex3 = 0x80,
eTex4 = 0x100,
eTex5 = 0x200,
eTex6 = 0x400,
eTex7 = 0x800,
eBoneIndices = 0x1000,
eBoneWeights = 0x2000,
ePosMtx = 0x4000,
eTex0Mtx = 0x8000,
eTex1Mtx = 0x10000,
eTex2Mtx = 0x20000,
eTex3Mtx = 0x40000,
eTex4Mtx = 0x80000,
eTex5Mtx = 0x100000,
eTex6Mtx = 0x200000
};
DECLARE_FLAGS(EVertexAttribute, FVertexDescription)
extern const u32 gkNumVertexAttribs;
u32 VertexAttributeSize(EVertexAttribute Attrib);
#endif // EVERTEXATTRIBUTE