186 lines
5.8 KiB
C++
186 lines
5.8 KiB
C++
#include "stdafx.h"
|
|
#include "CrySkinMorphBuilder.h"
|
|
#include "CrySkinMorph.h"
|
|
|
|
CrySkinMorphBuilder::CrySkinMorphBuilder(const ICrySkinSource* pGeometry, const Matrix44* pMatInvDef, unsigned numBones):
|
|
CrySkinBuilderBase (pGeometry),
|
|
m_pMatInvDef(pMatInvDef),
|
|
m_numBones(numBones)
|
|
{
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// initializes the given skin out of the given morph target
|
|
void CrySkinMorphBuilder::initSkinMorph (const SMeshMorphTargetVertex* pMorphVerts, unsigned numMorphVerts, class CrySkinMorph* pSkin)
|
|
{
|
|
m_pMorphVerts = pMorphVerts;
|
|
m_numMorphVerts = numMorphVerts;
|
|
m_pSkinTarget = pSkin;
|
|
pSkin->m_numDests = m_pGeometry->numVertices();
|
|
|
|
if (!numMorphVerts)
|
|
{
|
|
pSkin->clear();
|
|
return;
|
|
}
|
|
|
|
findAffectingBoneRange();
|
|
|
|
makeMorphBoneVertexArray();
|
|
|
|
calculateNumMorphLinks();
|
|
|
|
validate();
|
|
|
|
// for aux ints, we need, for each bone:
|
|
// 2 ints for group headers
|
|
// for each smooth link,
|
|
// 1 int for index of the target vertex
|
|
unsigned numAuxInts = 2 * (m_numAffectingBones - m_nFirstAffectingBone) + m_numMorphSmoothLinks;
|
|
|
|
pSkin->init (m_numMorphRigidLinks + m_numMorphSmoothLinks,
|
|
numAuxInts,
|
|
m_nFirstAffectingBone,
|
|
m_numAffectingBones);
|
|
|
|
CrySkinStreams stream, streamBegin, streamEnd;
|
|
streamBegin.pAux = pSkin->m_arrAux.begin();
|
|
streamBegin.pVert = pSkin->m_arrVertices.begin();
|
|
stream = streamBegin;
|
|
streamEnd.pAux = streamBegin.pAux + numAuxInts;
|
|
streamEnd.pVert = streamBegin.pVert + m_numMorphRigidLinks + m_numMorphSmoothLinks;
|
|
|
|
for (unsigned nBone = m_nFirstAffectingBone; nBone < m_numAffectingBones; ++nBone)
|
|
{
|
|
// for each bone, fill the three groups
|
|
// we start from the rigid vertices
|
|
fillRigidGroup (stream, nBone);
|
|
assert (stream.pAux <= streamEnd.pAux);
|
|
assert (stream.pVert <= streamEnd.pVert);
|
|
fillSmoothGroup (stream, nBone);
|
|
// only when we processed the last bone, we should have the pAux pointing to the end
|
|
assert (stream.pAux <= streamEnd.pAux);
|
|
assert (stream.pVert <= streamEnd.pVert);
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// for the given morph target(source) finds and initializes the
|
|
// m_nFirstAffectingBone and m_numAffectingBones
|
|
void CrySkinMorphBuilder::findAffectingBoneRange()
|
|
{
|
|
// init - find the first vertex binding info
|
|
const CryVertexBinding* pLinks = &m_pGeometry->getLink(m_pMorphVerts[0].nVertexId);
|
|
m_nFirstAffectingBone = pLinks->minBoneID();
|
|
m_numAffectingBones = pLinks->maxBoneID()+1;
|
|
|
|
// find all the other vertex binding info and init the bone range
|
|
for (unsigned nMorphVert = 1; nMorphVert < m_numMorphVerts; ++nMorphVert)
|
|
{
|
|
unsigned nGeomVert = m_pMorphVerts[nMorphVert].nVertexId;
|
|
pLinks = &m_pGeometry->getLink(nGeomVert);
|
|
m_nFirstAffectingBone = min (m_nFirstAffectingBone, pLinks->minBoneID());
|
|
m_numAffectingBones = max(m_numAffectingBones, pLinks->maxBoneID()+1);
|
|
}
|
|
|
|
assert (m_nFirstAffectingBone < m_numAffectingBones);
|
|
assert (m_numAffectingBones <= m_numBones);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// calculates the number of rigid and smooth links
|
|
// m_numMorphRigidLinks and m_numMorphSmoothLinks
|
|
void CrySkinMorphBuilder::calculateNumMorphLinks()
|
|
{
|
|
m_numMorphRigidLinks = 0;
|
|
m_numMorphSmoothLinks = 0;
|
|
for (unsigned nMorphVert = 0; nMorphVert < m_numMorphVerts; ++nMorphVert)
|
|
{
|
|
unsigned nGeomVert = m_pMorphVerts[nMorphVert].nVertexId;
|
|
const CryVertexBinding* pLinks = &m_pGeometry->getLink(nGeomVert);
|
|
|
|
if (pLinks->size() == 1)
|
|
++m_numMorphRigidLinks;
|
|
else
|
|
m_numMorphSmoothLinks += (unsigned)pLinks->size();
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// calculates the vertex list of each bone, taking only those vertices
|
|
// present in the morph vertex array
|
|
void CrySkinMorphBuilder::makeMorphBoneVertexArray()
|
|
{
|
|
m_arrBoneVerts.clear();
|
|
m_arrBoneVerts.resize (m_numAffectingBones);
|
|
for (unsigned nMorphVert = 0; nMorphVert < m_numMorphVerts; ++nMorphVert)
|
|
{
|
|
unsigned nGeomVert = m_pMorphVerts[nMorphVert].nVertexId;
|
|
const CryVertexBinding* pLinks = &m_pGeometry->getLink(nGeomVert);
|
|
// the morph vertex target in the object coordinates
|
|
Vec3d ptMorphOffset = m_pMorphVerts[nMorphVert].ptVertex - m_pGeometry->getVertex(nGeomVert);
|
|
|
|
if (pLinks->size() == 1)
|
|
{
|
|
unsigned nBone = (*pLinks)[0].BoneID;
|
|
CrySkinRigidVertex v;
|
|
v.nDest = nGeomVert;
|
|
// transform the point into the bone coordinates
|
|
|
|
//CHANGED_BY_IVO - INVALID CHANGE, PLEASE REVISE
|
|
v.pt = m_pMatInvDef[nBone].TransformVectorOLD (ptMorphOffset);
|
|
//v.pt = GetTransposed44(m_pMatInvDef[nBone])*(ptMorphOffset);
|
|
|
|
m_arrBoneVerts[nBone].arrRigid.push_back(v);
|
|
}
|
|
else
|
|
{
|
|
for (unsigned nLink = 0; nLink < pLinks->size(); ++nLink)
|
|
{
|
|
unsigned nBone = (*pLinks)[nLink].BoneID;
|
|
CrySkinSmoothVertex v;
|
|
v.fWeight = (*pLinks)[nLink].Blending;
|
|
v.nDest = nGeomVert;
|
|
|
|
v.pt = m_pMatInvDef[nBone].TransformVectorOLD (ptMorphOffset);
|
|
|
|
m_arrBoneVerts[nBone].arrSmooth.push_back(v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CrySkinMorphBuilder::validate()
|
|
{
|
|
#ifdef _DEBUG
|
|
unsigned nBone;
|
|
for (nBone = 0; nBone < m_nFirstAffectingBone;++nBone)
|
|
assert (m_arrBoneVerts[nBone].empty());
|
|
assert (!m_arrBoneVerts[m_nFirstAffectingBone].empty());
|
|
#endif
|
|
}
|
|
|
|
|
|
// fills in the group of aux ints for the given bone (the smooth vertex group)
|
|
// returns the pointer to the next available auxint after the group
|
|
void CrySkinMorphBuilder::fillSmoothGroup (CrySkinStreams& streams, unsigned nBone)
|
|
{
|
|
CrySkinSmoothVertexArray& arrSmooth = m_arrBoneVerts[nBone].arrSmooth;
|
|
|
|
// the group starts with the number of rigid vertices belonging to this bone
|
|
*streams.pAux++ = (CrySkinAuxInt)arrSmooth.size();
|
|
|
|
CrySkinSmoothVertexArray::const_iterator it = arrSmooth.begin(), itEnd = it + arrSmooth.size();
|
|
|
|
for (; it != itEnd; ++it)
|
|
{
|
|
it->build (*streams.pVert++);
|
|
*streams.pAux++ = it->nDest;
|
|
}
|
|
}
|