genesis-3d_engine/Engine/addons/resource/meshSpliter.cc

769 lines
22 KiB
C++
Raw Permalink Normal View History

/****************************************************************************
Copyright (c) 2011-2013,WebJet Business Division,CYOU
http://www.genesis-3d.com.cn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "stdneb.h"
#include "meshSpliter.h"
#include "RenderSystem.h"
//#define __DEBUG_MESHSPLITER__
//#define __DEBUG_MESHSPLITER_Print__
namespace Resources
{
//---------------------------------------------------------------------
__ImplementClass(MeshSpliter,'MHSP',Core::RefCounted);
__ImplementImageSingleton(MeshSpliter);
//---------------------------------------------------------------------
MeshSpliter::MeshSpliter():mMaxBoneBySubmesh( (128-16)/4 ),
mbInit(false)
{
__ConstructImageSingleton;
}
MeshSpliter::~MeshSpliter()
{
__DestructImageSingleton;
}
void MeshSpliter::Init()
{
if ( mbInit )
{
return;
}
mbInit = true;
#if RENDERDEVICE_OPENGLES
mMaxBoneBySubmesh = (RenderBase::GraphicCardCapability::s_mMaxUniformVectors-16)/4;
#else
mMaxBoneBySubmesh = 60;
#endif
#ifdef __DEBUG_MESHSPLITER__
mMaxBoneBySubmesh = 30;
#endif
}
void MeshSpliter::DebugPrint(GPtr<MeshRes>& pMesh)
{
#ifdef __DEBUG_MESHSPLITER_Print__
if ( pMesh->GetAffectedBonesIndex(0).Size() == 0 )
{
return;
}
mMeshRes=pMesh;
//debug=============
n_printf("meshID %s===================================\n",pMesh->GetMeshID().Get());
n_printf("submesh===================================\n");
for ( IndexT i = 0; i < mMeshRes->mSubMeshs.Size(); i++ )
{
n_printf("sub%d: \n",i);
n_printf("first index %d\n",mMeshRes->mSubMeshs[i].FirstIndex);
n_printf("number index %d\n",mMeshRes->mSubMeshs[i].numIndex);
n_printf("first vertex %d\n",mMeshRes->mSubMeshs[i].firstVertex);
n_printf("number vertex %d:\n",mMeshRes->mSubMeshs[i].numVertex);
}
n_printf("affected bone===================================\n");
for ( IndexT i = 0; i < mMeshRes->mAffectedBonesIndex.Size(); i++ )
{
Util::Array<uchar> affectedIdx = mMeshRes->mAffectedBonesIndex[i];
n_printf("sub%d------------------ \n",i);
for ( IndexT j = 0; j < affectedIdx.Size(); j++ )
{
uchar uVal = affectedIdx[j];
n_printf("%d\n",uVal);
}
}
n_printf("bone info===================================\n");
for ( IndexT i = 0; i < mMeshRes->mBoneInfo.Size(); i++ )
{
n_printf("mBoneInfo[%d]: ",i);
for ( IndexT j = 0; j < 4; j++ )
{
IndexT val = mMeshRes->mBoneInfo[i].boneIndex[j];
n_printf("%d ",val);
}
n_printf("\n");
}
n_printf("IB ===================================\n");
for ( IndexT i = 0; i < mMeshRes->mIndex16.Size(); i++ )
{
n_printf("Index16: ");
IndexT val = mMeshRes->mIndex16[i];
n_printf("%d ",val);
n_printf("\n");
}
/* n_printf("VB ===================================\n");
for ( IndexT i = 0; i < mMeshRes->mPosition.Size(); i++ )
{
n_printf("vbData: ");
Math::float3& v3Val = mMeshRes->mPosition[i];
n_printf("%f,%f,%f \n",v3Val.x(),v3Val.y(),v3Val.z());
}*/
//====================
#endif
}
void MeshSpliter::DoWork(GPtr<MeshRes>& pMesh)
{
#if RENDERDEVICE_OPENGLES
#ifdef __DEBUG_MESHSPLITER__
static bool bSkip = false;
#ifdef __GENESIS_EDITOR__
bSkip = true;
#endif
if ( bSkip )
{
return;
}
//if ( pMesh->GetMeshID() != "body_di" )
//{
// return;
//}
n_printf("meshspliter editor======================\n");
DebugPrint(pMesh);
#endif
DoWork_1(pMesh);
#ifdef __DEBUG_MESHSPLITER__
n_printf("meshspliter after======================\n");
DebugPrint(pMesh);
#endif
#endif
}
//------------------------------------------------------------------------
void MeshSpliter::DoWork_1(GPtr<MeshRes>& pMesh)
{
if ( pMesh->GetAffectedBonesIndex(0).Size() == 0 )
{
return;
}
if ( !_IsNeedSplit(pMesh) )
{
return;
}
mMeshRes=pMesh;
mSubmeshMapWorkPart.Clear();
SubMeshArray allSubMeshArray;
bool bSuc(false);
bSuc = _SplitMesh(mMeshRes,allSubMeshArray);
if ( !bSuc )
{
return;
}
#ifdef __DEBUG_MESHSPLITER_Print__
n_printf("meshspliter meshid %s======================\n",pMesh->GetMeshID().Get());
n_printf("meshspliter before======================\n");
DebugPrint(pMesh);
#endif
MeshReviseWorkspace workspace;
workspace.Init(mMeshRes);
// update AffectedBonesIndex
//_UpdateAffectedBonesIndex(mMeshRes->mSubMeshs,workspace);
_RestoreRawBoneInfo(mMeshRes->mSubMeshs,workspace);
_SplitVertexs(allSubMeshArray,workspace);
//update
//debug start==============================
//allSubMeshArray.EraseIndex(1);
//mMeshRes->mSummeshUsedMaterial[0] = 0;
//debug end==============================
mMeshRes->mSubMeshs.Swap(allSubMeshArray);
}
//-------------------------------------------------------------------------
bool MeshSpliter::_IsNeedSplit(GPtr<MeshRes>& pMesh)
{
SizeT oldSubmeshCount =pMesh->GetSubMeshCount();
for ( SizeT i = 0; i < oldSubmeshCount; ++i )
{
Util::Array<uchar>& affectdBones = pMesh->GetAffectedBonesIndex(i);
if ( affectdBones.Size() > mMaxBoneBySubmesh )
{
n_warning("dynamic split bone,cur device support boneNum:%d,mesh boneNum:%d,meshID:%s",mMaxBoneBySubmesh,affectdBones.Size(),pMesh->GetMeshID().Get());
return true;
}
}
return false;
}
//--------------------------------------------------------------------------
bool MeshSpliter::_SplitMesh(GPtr<MeshRes>& pMesh,SubMeshArray& mergeResult)
{
bool bSuc(false);
SizeT oldSubmeshCount =pMesh->GetSubMeshCount();
for ( SizeT i = 0; i < oldSubmeshCount; ++i )
{
SubMesh* pSubMesh= pMesh->GetSubMesh(i);
Util::Array<uchar>& affectdBones = pMesh->GetAffectedBonesIndex(i);
bSuc |= _TrySplitSubmesh(i,pSubMesh,affectdBones);
}
// submesh<73>ϲ<EFBFBD>
_MergeSubmeshes(mergeResult,mSubmeshMapWorkPart);
// add materialIdx used by submesh
mMeshRes->mSummeshUsedMaterial.Resize(oldSubmeshCount,1);
for ( SizeT i = 0; i < oldSubmeshCount; ++i )
{
IndexT keyIdx = mSubmeshMapWorkPart.FindIndex(i);
if ( keyIdx != InvalidIndex )
{// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
mMeshRes->mSummeshUsedMaterial[i] = mSubmeshMapWorkPart[i].Size();
}
}
return bSuc;
}
bool MeshSpliter::_TrySplitSubmesh(int iSubmesh,SubMesh* pSubmesh,Util::Array<uchar>& affectdBones)
{
int nSubmesh_bones = affectdBones.Size();
if ( nSubmesh_bones <= mMaxBoneBySubmesh )
{// no need split
return false;
}
// ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int numIndex = pSubmesh->numIndex;
IndexT begin = pSubmesh->FirstIndex;
IndexT end = begin + pSubmesh->numIndex;
int curIndexByNewSubmesh = begin;
n_assert(numIndex%3 == 0);
Util::FixedArray<uint> aVertex;
aVertex.Resize(3);
SubMeshArray aSubmesh;
StdSetHelper helperSet;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ<EFBFBD><CEBB><EFBFBD>ж<EFBFBD><D0B6>Ƿ񳬳<C7B7>subMesh<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (IndexT iIndex = begin; iIndex < end; iIndex += 3)
{
aVertex[0] = _GetVertexIndex(iIndex);
aVertex[1] = _GetVertexIndex(iIndex+1);
aVertex[2] = _GetVertexIndex(iIndex+2);
if ( _IsOverMaxBonesByTri(aVertex,helperSet) )
{
// add one new submesh
SubMesh newSubmesh;
newSubmesh.FirstIndex = curIndexByNewSubmesh;
//newSubmesh.numIndex = (iIndex - 1) - curIndexByNewSubmesh + 1;
newSubmesh.numIndex = (iIndex-1) - curIndexByNewSubmesh + 1;
curIndexByNewSubmesh = newSubmesh.FirstIndex + newSubmesh.numIndex;
aSubmesh.Append(newSubmesh);
helperSet.clear();
iIndex -= 3;
}
}
// <20><><EFBFBD><EFBFBD>old submesh <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>new submesh <20><>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭsubmesh
IndexT endIdxByOldSubmesh = pSubmesh->FirstIndex + pSubmesh->numIndex -1;
if ( curIndexByNewSubmesh-1 < endIdxByOldSubmesh)
{//<2F><><EFBFBD><EFBFBD>Ƭ
// add one new submesh by left
SubMesh newSubmesh;
newSubmesh.FirstIndex = curIndexByNewSubmesh ;
newSubmesh.numIndex = endIdxByOldSubmesh - newSubmesh.FirstIndex + 1;
aSubmesh.Append(newSubmesh);
}
n_assert(aSubmesh.Size() >= 2); //<2F><>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ( aSubmesh.Size() > 0 )
{
mSubmeshMapWorkPart.Add(iSubmesh,aSubmesh);
}
return true;
}
int MeshSpliter::_GetSubmeshFirstIndex(int iSubmesh)
{
int firstIndex = 0;
for ( int i = 0; i < iSubmesh; ++i)
{
firstIndex += mMeshRes->GetSubMesh(i)->numIndex;
}
return firstIndex;
}
bool MeshSpliter::_IsOverMaxBonesByTri(Util::FixedArray<uint>& aVertex,StdSetHelper& helperSet)
{
n_assert(aVertex.Size() == 3);
BoneInfoData::Elem* boneInfo = (BoneInfoData::Elem*)mMeshRes->GetDataImpl(VertexIndex::egBoneInfo,0);
for ( IndexT iVet = 0; iVet < aVertex.Size(); ++iVet )
{
uint iVetex = aVertex[iVet];
// һ<><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD>ͷӰ<CDB7><D3B0>
for ( int i = 0; i < 4; ++i )
{
ushort usIdxValue = boneInfo[iVetex].boneIndex[i]; // <20><>BoneInfoData<74><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
helperSet.insert(usIdxValue);
if ( (IndexT)helperSet.size() >= mMaxBoneBySubmesh )
{
return true;
}
}
}
return false;
}
#ifdef __DEBUG_MESHSPLITER__
typedef std::set<IndexT> StdSetIdx;
typedef std::map<IndexT,StdSetIdx> StdMapIdx;
static StdMapIdx g_stdMapIdx;
bool PreSubMeshHaveIVetIdx(IndexT iSubmesh,IndexT iVet)
{
for ( IndexT i = 0; i< iSubmesh; i++ )
{
StdSetIdx& oSet = g_stdMapIdx[i];
return (oSet.count(iVet) == 1);
}
return false;
}
#endif
void MeshSpliter::_RestoreRawBoneInfo(SubMeshArray& arrayRawSubmeshs, MeshReviseWorkspace& workspace)
{
#ifdef __DEBUG_MESHSPLITER__
g_stdMapIdx.clear();
#endif
// <20>ָ<EFBFBD>ԭʼ<D4AD><CABC><EFBFBD><EFBFBD>ֵ
workspace.mRestoreBoneInfo = mMeshRes->mBoneInfo;
IndexT boneIdxOffset(0);
for ( IndexT iSubmesh = 0; iSubmesh < (IndexT)arrayRawSubmeshs.Size(); ++iSubmesh )
{
std::set<IndexT> stdSetModifedIdx;
if ( iSubmesh >= 1 )
{
boneIdxOffset += mMeshRes->GetAffectedBonesIndex(iSubmesh-1).Size();
}
IndexT begin = arrayRawSubmeshs[iSubmesh].FirstIndex;
IndexT end = begin + arrayRawSubmeshs[iSubmesh].numIndex;
for ( IndexT i = begin; i < end; i++ )
{
IndexT iVet = _GetVertexIndex(i);
#ifdef __DEBUG_MESHSPLITER__
if ( iSubmesh >= 1 && PreSubMeshHaveIVetIdx(iSubmesh,iVet) )
{
n_error("pre submesh have ivet!!");
}
g_stdMapIdx[iSubmesh].insert(iVet);
#endif
if ( stdSetModifedIdx.count(iVet) == 1 )
{
continue;
}
stdSetModifedIdx.insert(iVet);
for ( int j = 0; j < 4; j++ )
{
workspace.mRestoreBoneInfo[iVet].boneIndex[j] = workspace.mRestoreBoneInfo[iVet].boneIndex[j] + boneIdxOffset;
}
}
}
}
void MeshSpliter::_MergeSubmeshes(SubMeshArray& outResult, Util::Dictionary<IndexT,SubMeshArray>& aNewSubmesh)
{
SubMeshArray& oldSubmesh = mMeshRes->mSubMeshs;
for ( IndexT i = 0; i < oldSubmesh.Size(); i++ )
{
IndexT keyIdx = aNewSubmesh.FindIndex(i);
if ( keyIdx != InvalidIndex )
{// <20><>submesh <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
outResult.AppendArray( aNewSubmesh.ValueAtIndex(keyIdx) );
}
else
{// <20><><EFBFBD><EFBFBD>old submesh
outResult.Append( oldSubmesh[i]);
}
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>======================================================================
void MeshSpliter::_SplitVertexs(SubMeshArray& allSubMeshArray,MeshReviseWorkspace& workspace)
{// vertex<65><78><EFBFBD><EFBFBD>
/*
* <EFBFBD><EFBFBD>allSubMeshArray<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>׼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>clone<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 1.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>vertexBuffer<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>vertexcolor,norma<EFBFBD>ȶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD>IndexBuffer<EFBFBD><EFBFBD>
* 2.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>vertexBuffer<EFBFBD><EFBFBD>Indexbuffer
* 3.<EFBFBD><EFBFBD><EFBFBD><EFBFBD>submesh<EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>firstVertex<EFBFBD><EFBFBD>numVertex,firstIndex,numIndex<EFBFBD><EFBFBD>
* remark:ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>£<EFBFBD>clone<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>
*/
n_assert(allSubMeshArray.Size() >= 1);
n_printf("=====================submeshID: %s \n",mMeshRes->meshId.Get());
//Util::Array<StdMapVertexArrayIdx> ssvaVertexIdx;
std::vector<StdMapVertexArrayIdx> ssvaVertexIdx;
Util::Array<IndexT> helperAfftectedBone;
std::vector<uint> subIndexVB;
StdMapVertexArrayIdx emptyMap;
emptyMap.clear();
//ssvaVertexIdx.Resize(allSubMeshArray.Size(),emptyMap);
ssvaVertexIdx.resize(allSubMeshArray.Size(),emptyMap);
//workspace
Util::Array<uchar> emptArrayUChar;
workspace.mAffectedBoneIndex.Resize(allSubMeshArray.Size(),emptArrayUChar);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30>submesh<73>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>submesh<73>й<EFBFBD><D0B9>õĶ<C3B5><C4B6>
IndexT begin = allSubMeshArray[0].FirstIndex;
IndexT end = begin + allSubMeshArray[0].numIndex;
IndexT vertexCountDebug = 0;
IndexT iSub(0);
for ( IndexT i = begin; i < end; i++ )
{
IndexT rawVertexIdx = _GetVertexIndex(i);
_MakeAffectedBoneAndBoneInfo(iSub,rawVertexIdx,rawVertexIdx,workspace,helperAfftectedBone);
//std::vector< uint >itFindRaw = std::find(subIndexVB.begin(),subIndexVB.end(),rawVertexIdx);
//if ( itFindRaw == subIndexVB.end() )
//{
subIndexVB.push_back(rawVertexIdx);
//}
ssvaVertexIdx[iSub].insert(std::make_pair(rawVertexIdx,-1));
}
helperAfftectedBone.Clear();
// update submesh vertexIdx vertexNum
std::sort(subIndexVB.begin(), subIndexVB.end());
allSubMeshArray[0].firstVertex = subIndexVB.front();
allSubMeshArray[0].numVertex = subIndexVB.back() - subIndexVB.front() + 1;
subIndexVB.clear();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>submesh<73><68><EFBFBD>õĶ<C3B5><C4B6><EFBFBD>
for ( IndexT iSub = 1; iSub < allSubMeshArray.Size(); ++iSub )
{
subIndexVB.clear();
helperAfftectedBone.Clear();
IndexT begin = allSubMeshArray[iSub].FirstIndex;
IndexT end = begin + allSubMeshArray[iSub].numIndex;
for ( IndexT indexIdx = begin; indexIdx < end; indexIdx++ )
{
IndexT rawVertexIdx = _GetVertexIndex(indexIdx);
bool bNeedClone = _HaveVertexIdx(ssvaVertexIdx,iSub,rawVertexIdx);
StdMapVertexArrayIdx::iterator itFind = ssvaVertexIdx[iSub].find(rawVertexIdx);
bool bHadCloned = ( ( itFind != ssvaVertexIdx[iSub].end() ) && ( itFind->second != (uint)-1) ) ;
// clone vertex
if ( bNeedClone )
{
if ( !bHadCloned )
{// <20><>ǰsubmesh<73>е<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><>Ҫclone
IndexT lastVertexIdx = workspace.AddVertex(rawVertexIdx);
workspace.SetIBValue(indexIdx,lastVertexIdx);
ssvaVertexIdx[iSub].insert(std::make_pair(rawVertexIdx,lastVertexIdx));
subIndexVB.push_back(lastVertexIdx);
_MakeAffectedBoneAndBoneInfo(iSub,rawVertexIdx,lastVertexIdx,workspace,helperAfftectedBone);
}
else
{// had cloned ֱ<><D6B1>ָ<EFBFBD><D6B8><EFBFBD>Ǹ<EFBFBD><C7B8><EFBFBD><EFBFBD><EFBFBD>
workspace.SetIBValue(indexIdx,itFind->second);
//subIndexVB.push_back(itFind->second);
}
}
else
{
//
ssvaVertexIdx[iSub].insert(std::make_pair(rawVertexIdx,-1));
subIndexVB.push_back(rawVertexIdx);
_MakeAffectedBoneAndBoneInfo(iSub,rawVertexIdx,rawVertexIdx,workspace,helperAfftectedBone);
}
}
// update submesh vertexIdx vertexNum
std::sort(subIndexVB.begin(), subIndexVB.end());
allSubMeshArray[iSub].firstVertex = subIndexVB.front();
allSubMeshArray[iSub].numVertex = subIndexVB.back() - subIndexVB.front() + 1;
}
workspace.Swap();
}
//------------------------------------------------------------------------
void MeshSpliter::_MakeAffectedBoneAndBoneInfo(IndexT iSub,IndexT rawVertexIdx,IndexT newVertexIdx,MeshReviseWorkspace& workspace,Util::Array<IndexT>& helperAfftectedBone)
{
// <20><><EFBFBD><EFBFBD>ԭʼaffectedBone<6E><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>workspace<63>е<EFBFBD>affectedbone<6E><65>
// <20><><EFBFBD><EFBFBD>workspace<63>е<EFBFBD>affectedbone <20><><EFBFBD><EFBFBD>boneInfo<66>е<EFBFBD>boneidxΪ<78><CEAA>Ⱦ<EFBFBD><C8BE>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for ( int j = 0; j < 4; j++ )
{
// <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>boneIndex
IndexT idxAffetedBone = workspace.mRestoreBoneInfo[rawVertexIdx].boneIndex[j];
//
IndexT affectedBoneValue = _GetRawAffectedBonesValue(mMeshRes->mAffectedBonesIndex,idxAffetedBone);
if ( helperAfftectedBone.FindIndex(affectedBoneValue) == InvalidIndex )
{// û<>У<EFBFBD>׷<EFBFBD><D7B7>
helperAfftectedBone.Append(affectedBoneValue);
// make affecteBone
workspace.mAffectedBoneIndex[iSub].Append( (uchar)affectedBoneValue );
IndexT lastIdxAffectedBoneIndex = workspace.mAffectedBoneIndex[iSub].Size() - 1;
// make boneInfo<66>е<EFBFBD>boneIndex
workspace.mBoneInfo[newVertexIdx].boneIndex[j] = lastIdxAffectedBoneIndex;
}
else
{// <20>У<EFBFBD><D0A3><EFBFBD>Ҫ<EFBFBD>޸<EFBFBD>boneInfo<66>е<EFBFBD>boneIndex
IndexT idxFind = workspace.mAffectedBoneIndex[iSub].FindIndex(affectedBoneValue);
n_assert(idxFind != InvalidIndex); //idxFind <20><> helperAfftectedBone.FindIndex(affectedBoneValue)<29><><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD>
// make boneInfo<66>е<EFBFBD>boneIndex
workspace.mBoneInfo[newVertexIdx].boneIndex[j] = idxFind;
}
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>======================================================================
IndexT MeshSpliter::_GetVertexIndex(IndexT idxAtIndexArray)
{
Index16Container::value_type* index16;
Index32Container::value_type* index32;
if ( mMeshRes->IsUseIndex16() )
{
index16 = mMeshRes->GetIndex16();
}
else
{
index32 = mMeshRes->GetIndex32();
}
IndexT iVet = mMeshRes->IsUseIndex16() ? index16[idxAtIndexArray] : index32[idxAtIndexArray];
return iVet;
}
//-------------------------------------------------------------------------
void MeshSpliter::_GetAffectedBonesIndex(FixedArrayBonesIndex& outAffectedBonesIndex, IndexT idxAtVertexArray,MeshReviseWorkspace& workspace)
{
outAffectedBonesIndex.Resize(4);
for ( int i = 0; i < 4; i++ )
{
outAffectedBonesIndex[i] = workspace.mRestoreBoneInfo[idxAtVertexArray].boneIndex[i];
}
}
//------------------------------------------------------------------------
bool MeshSpliter::_HaveVertexIdx(std::vector<StdMapVertexArrayIdx> ssvaVertexIdx, IndexT end, IndexT testVal)
{
for ( IndexT iSub = 0; iSub < end; iSub++ )
{
if ( ssvaVertexIdx[iSub].find(testVal) != ssvaVertexIdx[iSub].end() )
{
return true;
}
}
return false;
}
//------------------------------------------------------------------------
IndexT MeshSpliter::_GetRawAffectedBonesValue(AffectedBonesIndex& rawAffectedBones, IndexT restoreBoneIdx)
{
IndexT totalIdx(0),preTotalNum(0);
for ( IndexT i = 0; i < rawAffectedBones.Size(); i++ )
{
if ( i >= 1 )
{
preTotalNum += rawAffectedBones[i-1].Size();
}
totalIdx += rawAffectedBones[i].Size();
if ( restoreBoneIdx <totalIdx )
{
return rawAffectedBones[i][restoreBoneIdx - preTotalNum];
}
}
n_assert(0);
return InvalidIndex;
}
//-------------------------------------------------------------------------
MeshReviseWorkspace::MeshReviseWorkspace()
{
}
MeshReviseWorkspace::~MeshReviseWorkspace()
{
}
//-------------------------------------------------------------------------
void MeshReviseWorkspace::Init(GPtr<MeshRes>& pMesh)
{
mMeshRes = pMesh;
mbUseIndex16 = mMeshRes->IsUseIndex16();
// clone IB
if ( mbUseIndex16 )
{
mIndex16 = mMeshRes->mIndex16;
}
else
{
mIndex32 = mMeshRes->mIndex32;
}
// clone VB
// position
mPosition = mMeshRes->mPosition;
// color
mColor = mMeshRes->mColor;
// other...
mTexCoords = mMeshRes->mTexCoords;
mNormal = mMeshRes->mNormal;
mTangent = mMeshRes->mTangent;
mBiNormal = mMeshRes->mBiNormal;
mBoneInfo = mMeshRes->mBoneInfo;
}
//-------------------------------------------------------------------------
void MeshReviseWorkspace::Reserve(int num)
{
}
//-------------------------------------------------------------------------
IndexT MeshReviseWorkspace::AddVertex(int rawVetexArrayIdx)
{// <20><>ԭʼvb<76>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// position
if(rawVetexArrayIdx < mMeshRes->mPosition.Size())
mPosition.Append( mMeshRes->mPosition[rawVetexArrayIdx] );
// color
if(rawVetexArrayIdx < mMeshRes->mColor.Size())
mColor.Append( mMeshRes->mColor[rawVetexArrayIdx] );
// other...
for ( IndexT i = 0 ; i < mMeshRes->mTexCoords.Size(); ++i )
{
TexCoordData& texcoordRht = mMeshRes->mTexCoords[i];
TexCoordData& texcoord = mTexCoords[i];
texcoord.Append(texcoordRht[rawVetexArrayIdx]);
}
if(rawVetexArrayIdx < mMeshRes->mNormal.Size())
mNormal.Append( mMeshRes->mNormal[rawVetexArrayIdx] );
if(rawVetexArrayIdx < mMeshRes->mTangent.Size())
mTangent.Append( mMeshRes->mTangent[rawVetexArrayIdx] );
if(rawVetexArrayIdx < mMeshRes->mBiNormal.Size())
mBiNormal.Append( mMeshRes->mBiNormal[rawVetexArrayIdx] );
if(rawVetexArrayIdx < mMeshRes->mBoneInfo.Size())
mBoneInfo.Append( mMeshRes->mBoneInfo[rawVetexArrayIdx] );
return mPosition.Size() - 1;
}
//------------------------------------------------------------------------
void MeshReviseWorkspace::Swap()
{
if ( mbUseIndex16 )
{
mIndex16.Swap( mMeshRes->mIndex16);
}
else
{
mIndex32.Swap( mMeshRes->mIndex32);
}
mPosition.Swap(mMeshRes->mPosition);
mColor.Swap(mMeshRes->mColor);
mTexCoords.Swap(mMeshRes->mTexCoords);
mNormal.Swap(mMeshRes->mNormal);
mTangent.Swap(mMeshRes->mTangent);
mBiNormal.Swap(mMeshRes->mBiNormal);
mBoneInfo.Swap(mMeshRes->mBoneInfo);
mAffectedBoneIndex.Swap(mMeshRes->mAffectedBonesIndex);
n_assert(mMeshRes->Validate());
}
//-------------------------------------------------------------------------
void MeshReviseWorkspace::AddIndex(IndexT newIndexArrayIdxValue)
{
if ( mbUseIndex16 )
{
mIndex16.Append( (ushort)newIndexArrayIdxValue );
}
else
{
mIndex32.Append( newIndexArrayIdxValue );
}
}
//------------------------------------------------------------------------
void MeshReviseWorkspace::SetIBValue(IndexT indexIB,IndexT val)
{
if ( mbUseIndex16 )
{
mIndex16[indexIB] = (ushort)val;
}
else
{
mIndex32[indexIB] = val;
}
}
//-------------------------------------------------------------------------
IndexT MeshReviseWorkspace::GetVertexArraySize()
{
return mPosition.Size();
}
}