mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-26 07:34:52 +01:00
996 lines
35 KiB
C++
996 lines
35 KiB
C++
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
#include <Engine/StdH.h>
|
|
#include "Mesh.h"
|
|
|
|
#define MESH_VERSION 12
|
|
#define MESH_ID "MESH"
|
|
|
|
#include <Engine/Base/Stream.h>
|
|
#include <Engine/Base/Console.h>
|
|
#include <Engine/Ska/StringTable.h>
|
|
#include <Engine/Math/Projection.h>
|
|
#include <Engine/Graphics/DrawPort.h>
|
|
#include <Engine/Graphics/Shader.h>
|
|
#include <Engine/Templates/StaticArray.h>
|
|
#include <Engine/Templates/StaticArray.cpp>
|
|
#include <Engine/Templates/Stock_CShader.h>
|
|
|
|
INDEX AreVerticesDiferent(INDEX iCurentIndex, INDEX iLastIndex);
|
|
|
|
struct VertexLocator
|
|
{
|
|
INDEX vl_iIndex;
|
|
INDEX vl_iSubIndex;
|
|
};
|
|
|
|
struct SortArray
|
|
{
|
|
INDEX sa_iNewIndex;
|
|
INDEX sa_iSurfaceIndex;
|
|
CStaticArray<struct VertexLocator> sa_aWeightMapList;
|
|
CStaticArray<struct VertexLocator> sa_aMorphMapList;
|
|
};
|
|
|
|
static CStaticArray <struct SortArray> _aSortArray;
|
|
CStaticArray <INDEX> _aiOptimizedIndex;
|
|
CStaticArray <INDEX> _aiSortedIndex;
|
|
|
|
MeshLOD *pMeshLOD;// curent mesh lod (for quick sort)
|
|
MeshLOD mshOptimized;
|
|
|
|
CMesh::CMesh()
|
|
{
|
|
}
|
|
|
|
CMesh::~CMesh()
|
|
{
|
|
}
|
|
|
|
// release old shader and obtain new shader for mesh surface (expand ShaderParams if needed)
|
|
void ChangeSurfaceShader_t(MeshSurface &msrf,CTString fnNewShader)
|
|
{
|
|
CShader *pShaderNew = _pShaderStock->Obtain_t(fnNewShader);
|
|
ASSERT(pShaderNew!=NULL);
|
|
if(msrf.msrf_pShader!=NULL) _pShaderStock->Release(msrf.msrf_pShader);
|
|
msrf.msrf_pShader = pShaderNew;
|
|
// get new shader description
|
|
ShaderDesc shDesc;
|
|
msrf.msrf_pShader->GetShaderDesc(shDesc);
|
|
// if needed expand size of arrays for new shader
|
|
// reset new values!!!!
|
|
INDEX ctOldTextureIDs = msrf.msrf_ShadingParams.sp_aiTextureIDs.Count();
|
|
INDEX ctNewTextureIDs = shDesc.sd_astrTextureNames.Count();
|
|
INDEX ctOldUVMaps = msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count();
|
|
INDEX ctNewUVMaps = shDesc.sd_astrTexCoordNames.Count();
|
|
INDEX ctOldColors = msrf.msrf_ShadingParams.sp_acolColors.Count();
|
|
INDEX ctNewColors = shDesc.sd_astrColorNames.Count();
|
|
INDEX ctOldFloats = msrf.msrf_ShadingParams.sp_afFloats.Count();
|
|
INDEX ctNewFloats = shDesc.sd_astrFloatNames.Count();
|
|
if(ctOldTextureIDs<ctNewTextureIDs) {
|
|
// expand texture IDs array
|
|
msrf.msrf_ShadingParams.sp_aiTextureIDs.Expand(ctNewTextureIDs);
|
|
// set new texture IDs to 0
|
|
for(INDEX itx=ctOldTextureIDs;itx<ctNewTextureIDs;itx++) {
|
|
msrf.msrf_ShadingParams.sp_aiTextureIDs[itx] = -1;
|
|
}
|
|
}
|
|
// expand array of uvmaps if needed
|
|
if(ctOldUVMaps<ctNewUVMaps) {
|
|
// expand uvmaps IDs array
|
|
msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Expand(ctNewUVMaps);
|
|
// set new uvmaps indices to 0
|
|
for(INDEX itxc=ctOldUVMaps;itxc<ctNewUVMaps;itxc++) {
|
|
msrf.msrf_ShadingParams.sp_aiTexCoordsIndex[itxc] = 0;
|
|
}
|
|
}
|
|
// expand array of colors if needed
|
|
if(ctOldColors<ctNewColors) {
|
|
// expand color array
|
|
msrf.msrf_ShadingParams.sp_acolColors.Expand(ctNewColors);
|
|
// set new colors indices white
|
|
for(INDEX icol=ctOldUVMaps;icol<ctNewColors;icol++) {
|
|
msrf.msrf_ShadingParams.sp_acolColors[icol] = 0xFFFFFFFF;
|
|
}
|
|
}
|
|
// expand array of floats if needed
|
|
if(ctOldFloats<ctNewFloats) {
|
|
// expand float array
|
|
msrf.msrf_ShadingParams.sp_afFloats.Expand(ctNewFloats);
|
|
// set new floats to 0
|
|
for(INDEX ifl=ctOldFloats;ifl<ctNewFloats;ifl++) {
|
|
msrf.msrf_ShadingParams.sp_afFloats[ifl] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// quck sort func for comparing vertices
|
|
static int qsort_CompareArray(const void *pVx1, const void *pVx2)
|
|
{
|
|
INDEX *n1 = ((INDEX*)pVx1);
|
|
INDEX *n2 = ((INDEX*)pVx2);
|
|
return AreVerticesDiferent(*n1,*n2);
|
|
}
|
|
// clear array of sort vertices
|
|
void ClearSortArray(INDEX ctOldVertices)
|
|
{
|
|
for(int iv=0;iv<ctOldVertices;iv++)
|
|
{
|
|
_aSortArray[iv].sa_aWeightMapList.Clear();
|
|
_aSortArray[iv].sa_aMorphMapList.Clear();
|
|
}
|
|
_aiOptimizedIndex.Clear();
|
|
_aiSortedIndex.Clear();
|
|
_aSortArray.Clear();
|
|
}
|
|
// optimize mesh
|
|
void CMesh::Optimize(void)
|
|
{
|
|
INDEX ctmshlods = msh_aMeshLODs.Count();
|
|
for(int imshlod=0;imshlod<ctmshlods;imshlod++)
|
|
{
|
|
// optimize each lod in mesh
|
|
OptimizeLod(msh_aMeshLODs[imshlod]);
|
|
}
|
|
}
|
|
// optimize lod of mesh
|
|
void CMesh::OptimizeLod(MeshLOD &mLod)
|
|
{
|
|
INDEX ctVertices = mLod.mlod_aVertices.Count();
|
|
INDEX ctSurfaces = mLod.mlod_aSurfaces.Count();
|
|
INDEX ctUVMaps = mLod.mlod_aUVMaps.Count();
|
|
INDEX ctWeightMaps = mLod.mlod_aWeightMaps.Count();
|
|
INDEX ctMorphMaps = mLod.mlod_aMorphMaps.Count();
|
|
|
|
if(ctVertices<=0) return;
|
|
|
|
// create array for sorting
|
|
_aSortArray.New(ctVertices);
|
|
_aiSortedIndex.New(ctVertices);
|
|
_aiOptimizedIndex.New(ctVertices);
|
|
// put original vertex indices in SortArray
|
|
for(int iv=0;iv<ctVertices;iv++)
|
|
{
|
|
_aiSortedIndex[iv] = iv;
|
|
}
|
|
// loop each surface and expand SurfaceList in SortArray
|
|
int is;
|
|
for(is=0;is<ctSurfaces;is++)
|
|
{
|
|
INDEX ctts=mLod.mlod_aSurfaces[is].msrf_aTriangles.Count();
|
|
for(int its=0;its<ctts;its++)
|
|
{
|
|
MeshTriangle &mtTriangle = mLod.mlod_aSurfaces[is].msrf_aTriangles[its];
|
|
|
|
_aSortArray[mtTriangle.iVertex[0]].sa_iSurfaceIndex = is;
|
|
_aSortArray[mtTriangle.iVertex[1]].sa_iSurfaceIndex = is;
|
|
_aSortArray[mtTriangle.iVertex[2]].sa_iSurfaceIndex = is;
|
|
}
|
|
}
|
|
// loop each weightmap and expand sa_aWeightMapList in SortArray
|
|
for(INDEX iw=0;iw<ctWeightMaps;iw++)
|
|
{
|
|
// loop each wertex weight array in weight map array
|
|
INDEX ctwm = mLod.mlod_aWeightMaps[iw].mwm_aVertexWeight.Count();
|
|
for(INDEX iwm=0;iwm<ctwm;iwm++)
|
|
{
|
|
MeshVertexWeight &mwwWeight = mLod.mlod_aWeightMaps[iw].mwm_aVertexWeight[iwm];
|
|
// get curent list num of weightmaps
|
|
INDEX ctWeightMapList = _aSortArray[mwwWeight.mww_iVertex].sa_aWeightMapList.Count();
|
|
// expand array of sufrace lists for 1
|
|
_aSortArray[mwwWeight.mww_iVertex].sa_aWeightMapList.Expand(ctWeightMapList+1);
|
|
// set vl_iIndex to index of surface
|
|
// set vl_iSubIndex to index in triangle set
|
|
VertexLocator &vxLoc = _aSortArray[mwwWeight.mww_iVertex].sa_aWeightMapList[ctWeightMapList];
|
|
vxLoc.vl_iIndex = iw;
|
|
vxLoc.vl_iSubIndex = iwm;
|
|
}
|
|
}
|
|
// loop each morphmap and expand sa_aMorphMapList in SortArray
|
|
for(INDEX im=0;im<ctMorphMaps;im++)
|
|
{
|
|
// loop each morph map in array
|
|
INDEX ctmm = mLod.mlod_aMorphMaps[im].mmp_aMorphMap.Count();
|
|
for(INDEX imm=0;imm<ctmm;imm++)
|
|
{
|
|
MeshVertexMorph &mwmMorph = mLod.mlod_aMorphMaps[im].mmp_aMorphMap[imm];
|
|
// get curent list num of morphmaps
|
|
INDEX ctMorphMapList = _aSortArray[mwmMorph.mwm_iVxIndex].sa_aMorphMapList.Count();
|
|
// expand array of sufrace lists for 1
|
|
_aSortArray[mwmMorph.mwm_iVxIndex].sa_aMorphMapList.Expand(ctMorphMapList+1);
|
|
// set vl_iIndex to index of surface
|
|
// set vl_iSubIndex to index in triangle set
|
|
VertexLocator &vxLoc = _aSortArray[mwmMorph.mwm_iVxIndex].sa_aMorphMapList[ctMorphMapList];
|
|
vxLoc.vl_iIndex = im;
|
|
vxLoc.vl_iSubIndex = imm;
|
|
}
|
|
}
|
|
// set global pMeshLOD pointer used by quicksort
|
|
pMeshLOD = &mLod;
|
|
// sort array
|
|
qsort(&_aiSortedIndex[0],ctVertices,sizeof(&_aiSortedIndex[0]),qsort_CompareArray);
|
|
|
|
// compare vertices
|
|
INDEX iDiferentVertices = 1;
|
|
INDEX iLastIndex = _aiSortedIndex[0];
|
|
_aSortArray[iLastIndex].sa_iNewIndex = 0;
|
|
_aiOptimizedIndex[0] = iLastIndex;
|
|
|
|
for(INDEX isa=1;isa<ctVertices;isa++)
|
|
{
|
|
INDEX iCurentIndex = _aiSortedIndex[isa];
|
|
// check if vertices are diferent
|
|
if(AreVerticesDiferent(iLastIndex,iCurentIndex))
|
|
{
|
|
// add Curent index to Optimized index array
|
|
_aiOptimizedIndex[iDiferentVertices] = iCurentIndex;
|
|
iDiferentVertices++;
|
|
iLastIndex = iCurentIndex;
|
|
}
|
|
_aSortArray[iCurentIndex].sa_iNewIndex = iDiferentVertices-1;
|
|
}
|
|
|
|
// create new mesh
|
|
INDEX ctNewVertices = iDiferentVertices;
|
|
mshOptimized.mlod_aVertices.New(ctNewVertices);
|
|
mshOptimized.mlod_aNormals.New(ctNewVertices);
|
|
mshOptimized.mlod_aUVMaps.New(ctUVMaps);
|
|
for(INDEX iuvm=0;iuvm<ctUVMaps;iuvm++)
|
|
{
|
|
mshOptimized.mlod_aUVMaps[iuvm].muv_aTexCoords.New(ctNewVertices);
|
|
}
|
|
|
|
// add new vertices and normals to mshOptimized
|
|
for(INDEX iNewVx=0;iNewVx<ctNewVertices;iNewVx++)
|
|
{
|
|
mshOptimized.mlod_aVertices[iNewVx] = mLod.mlod_aVertices[_aiOptimizedIndex[iNewVx]];
|
|
mshOptimized.mlod_aNormals[iNewVx] = mLod.mlod_aNormals[_aiOptimizedIndex[iNewVx]];
|
|
for(INDEX iuvm=0;iuvm<ctUVMaps;iuvm++)
|
|
{
|
|
//???
|
|
mshOptimized.mlod_aUVMaps[iuvm].muv_iID = mLod.mlod_aUVMaps[iuvm].muv_iID;
|
|
mshOptimized.mlod_aUVMaps[iuvm].muv_aTexCoords[iNewVx] = mLod.mlod_aUVMaps[iuvm].muv_aTexCoords[_aiOptimizedIndex[iNewVx]];
|
|
}
|
|
}
|
|
// remap surface triangles
|
|
for(is=0;is<ctSurfaces;is++)
|
|
{
|
|
MeshSurface &msrf = mLod.mlod_aSurfaces[is];
|
|
INDEX iMinIndex = ctNewVertices+1;
|
|
INDEX iMaxIndex = -1;
|
|
INDEX ctts=msrf.msrf_aTriangles.Count();
|
|
// for each triangle in this surface
|
|
INDEX its;
|
|
for(its=0;its<ctts;its++)
|
|
{
|
|
MeshTriangle &mtTriangle = msrf.msrf_aTriangles[its];
|
|
// for each vertex in triangle
|
|
for(INDEX iv=0;iv<3;iv++)
|
|
{
|
|
mtTriangle.iVertex[iv] = _aSortArray[mtTriangle.iVertex[iv]].sa_iNewIndex;
|
|
// find first index in this surface
|
|
if(mtTriangle.iVertex[iv]<iMinIndex) iMinIndex = mtTriangle.iVertex[iv];
|
|
// find last index in this surface
|
|
if(mtTriangle.iVertex[iv]>iMaxIndex) iMaxIndex = mtTriangle.iVertex[iv];
|
|
}
|
|
}
|
|
// remember first index in vertices array
|
|
msrf.msrf_iFirstVertex = iMinIndex;
|
|
// remember vertices count
|
|
msrf.msrf_ctVertices = iMaxIndex-iMinIndex+1;
|
|
|
|
// for each triangle in surface
|
|
for(its=0;its<ctts;its++)
|
|
{
|
|
MeshTriangle &mtTriangle = msrf.msrf_aTriangles[its];
|
|
// for each vertex in triangle
|
|
for(INDEX iv=0;iv<3;iv++)
|
|
{
|
|
// substract vertex index in triangle with first vertex in surface
|
|
mtTriangle.iVertex[iv] -= msrf.msrf_iFirstVertex;
|
|
ASSERT(mtTriangle.iVertex[iv]<msrf.msrf_ctVertices);
|
|
}
|
|
}
|
|
}
|
|
|
|
// remap weightmaps
|
|
mshOptimized.mlod_aWeightMaps.New(ctWeightMaps);
|
|
// expand wertex veights array for each vertex
|
|
INDEX ivx;
|
|
for(ivx=0;ivx<ctNewVertices;ivx++)
|
|
{
|
|
INDEX ioptVx = _aiOptimizedIndex[ivx];
|
|
for(INDEX iwl=0;iwl<_aSortArray[ioptVx].sa_aWeightMapList.Count();iwl++)
|
|
{
|
|
VertexLocator &wml = _aSortArray[ioptVx].sa_aWeightMapList[iwl];
|
|
INDEX wmIndex = wml.vl_iIndex;
|
|
INDEX wwIndex = wml.vl_iSubIndex;
|
|
INDEX ctww = mshOptimized.mlod_aWeightMaps[wmIndex].mwm_aVertexWeight.Count();
|
|
MeshWeightMap &mwm = mshOptimized.mlod_aWeightMaps[wmIndex];
|
|
MeshVertexWeight &mww = mLod.mlod_aWeightMaps[wmIndex].mwm_aVertexWeight[wwIndex];
|
|
|
|
mwm.mwm_iID = mLod.mlod_aWeightMaps[wmIndex].mwm_iID;
|
|
mwm.mwm_aVertexWeight.Expand(ctww+1);
|
|
mwm.mwm_aVertexWeight[ctww].mww_fWeight = mww.mww_fWeight;
|
|
mwm.mwm_aVertexWeight[ctww].mww_iVertex = ivx;
|
|
}
|
|
}
|
|
|
|
// remap morphmaps
|
|
mshOptimized.mlod_aMorphMaps.New(ctMorphMaps);
|
|
// expand morph maps array for each vertex
|
|
for(ivx=0;ivx<ctNewVertices;ivx++)
|
|
{
|
|
INDEX ioptVx = _aiOptimizedIndex[ivx];
|
|
for(INDEX iml=0;iml<_aSortArray[ioptVx].sa_aMorphMapList.Count();iml++)
|
|
{
|
|
VertexLocator &mml = _aSortArray[ioptVx].sa_aMorphMapList[iml];
|
|
INDEX mmIndex = mml.vl_iIndex;
|
|
INDEX mwmIndex = mml.vl_iSubIndex;
|
|
INDEX ctmwm = mshOptimized.mlod_aMorphMaps[mmIndex].mmp_aMorphMap.Count();
|
|
MeshMorphMap &mmm = mshOptimized.mlod_aMorphMaps[mmIndex];
|
|
MeshVertexMorph &mwm = mLod.mlod_aMorphMaps[mmIndex].mmp_aMorphMap[mwmIndex];
|
|
|
|
mmm.mmp_iID = mLod.mlod_aMorphMaps[mmIndex].mmp_iID;
|
|
mmm.mmp_bRelative = mLod.mlod_aMorphMaps[mmIndex].mmp_bRelative;
|
|
|
|
mmm.mmp_aMorphMap.Expand(ctmwm+1);
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_iVxIndex = ivx;
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_x = mwm.mwm_x;
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_y = mwm.mwm_y;
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_z = mwm.mwm_z;
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_nx = mwm.mwm_nx;
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_ny = mwm.mwm_ny;
|
|
mmm.mmp_aMorphMap[ctmwm].mwm_nz = mwm.mwm_nz;
|
|
}
|
|
}
|
|
|
|
mLod.mlod_aVertices.CopyArray(mshOptimized.mlod_aVertices);
|
|
mLod.mlod_aNormals.CopyArray(mshOptimized.mlod_aNormals);
|
|
mLod.mlod_aMorphMaps.CopyArray(mshOptimized.mlod_aMorphMaps);
|
|
mLod.mlod_aWeightMaps.CopyArray(mshOptimized.mlod_aWeightMaps);
|
|
mLod.mlod_aUVMaps.CopyArray(mshOptimized.mlod_aUVMaps);
|
|
|
|
// clear memory
|
|
ClearSortArray(ctVertices);
|
|
mshOptimized.mlod_aVertices.Clear();
|
|
mshOptimized.mlod_aNormals.Clear();
|
|
mshOptimized.mlod_aWeightMaps.Clear();
|
|
mshOptimized.mlod_aMorphMaps.Clear();
|
|
mshOptimized.mlod_aUVMaps.Clear();
|
|
}
|
|
|
|
INDEX AreVerticesDiferent(INDEX iCurentIndex, INDEX iLastIndex)
|
|
{
|
|
#define CHECK(x,y) if(((x)-(y))!=0) return (INDEX) ((x)-(y))
|
|
#define CHECKF(x,y) if(((x)-(y))!=0) return (INDEX) Sgn((x)-(y))
|
|
|
|
// check surfaces
|
|
CHECK(_aSortArray[iCurentIndex].sa_iSurfaceIndex,_aSortArray[iLastIndex].sa_iSurfaceIndex);
|
|
// check vertices
|
|
CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].y,pMeshLOD->mlod_aVertices[iLastIndex].y);
|
|
CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].x,pMeshLOD->mlod_aVertices[iLastIndex].x);
|
|
CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].z,pMeshLOD->mlod_aVertices[iLastIndex].z);
|
|
// check normals
|
|
CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].ny,pMeshLOD->mlod_aNormals[iLastIndex].ny);
|
|
CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].nx,pMeshLOD->mlod_aNormals[iLastIndex].nx);
|
|
CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].nz,pMeshLOD->mlod_aNormals[iLastIndex].nz);
|
|
// check uvmaps
|
|
INDEX ctUVMaps = pMeshLOD->mlod_aUVMaps.Count();
|
|
for(INDEX iuvm=0;iuvm<ctUVMaps;iuvm++)
|
|
{
|
|
CHECKF(pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iCurentIndex].u,pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iLastIndex].u);
|
|
CHECKF(pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iCurentIndex].v,pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iLastIndex].v);
|
|
}
|
|
// count weight and morph maps
|
|
INDEX ctwmCurent = _aSortArray[iCurentIndex].sa_aWeightMapList.Count();
|
|
INDEX ctwmLast = _aSortArray[iLastIndex].sa_aWeightMapList.Count();
|
|
INDEX ctmmCurent = _aSortArray[iCurentIndex].sa_aMorphMapList.Count();
|
|
INDEX ctmmLast = _aSortArray[iLastIndex].sa_aMorphMapList.Count();
|
|
// check if vertices have same weight and morph maps count
|
|
CHECK(ctwmCurent,ctwmLast);
|
|
CHECK(ctmmCurent,ctmmLast);
|
|
// check if vertices have same weight map factors
|
|
for(INDEX iwm=0;iwm<ctwmCurent;iwm++)
|
|
{
|
|
// get weight map indices
|
|
INDEX iwmCurent = _aSortArray[iCurentIndex].sa_aWeightMapList[iwm].vl_iIndex;
|
|
INDEX iwmLast = _aSortArray[iLastIndex].sa_aWeightMapList[iwm].vl_iIndex;
|
|
// get wertex weight indices
|
|
INDEX iwwCurent = _aSortArray[iCurentIndex].sa_aWeightMapList[iwm].vl_iSubIndex;
|
|
INDEX iwwLast = _aSortArray[iLastIndex].sa_aWeightMapList[iwm].vl_iSubIndex;
|
|
// if weight map factors are diferent
|
|
CHECKF(pMeshLOD->mlod_aWeightMaps[iwmCurent].mwm_aVertexWeight[iwwCurent].mww_fWeight,pMeshLOD->mlod_aWeightMaps[iwmLast].mwm_aVertexWeight[iwwLast].mww_fWeight);
|
|
}
|
|
|
|
// check if vertices have same morph map factors
|
|
for(INDEX imm=0;imm<ctmmCurent;imm++)
|
|
{
|
|
// get morph map indices
|
|
INDEX immCurent = _aSortArray[iCurentIndex].sa_aMorphMapList[imm].vl_iIndex;
|
|
INDEX immLast = _aSortArray[iLastIndex].sa_aMorphMapList[imm].vl_iIndex;
|
|
// get mesh vertex morph indices
|
|
INDEX imwmCurent = _aSortArray[iCurentIndex].sa_aMorphMapList[imm].vl_iSubIndex;
|
|
INDEX imwmLast = _aSortArray[iLastIndex].sa_aMorphMapList[imm].vl_iSubIndex;
|
|
|
|
// if mesh morph map params are diferent return
|
|
CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_x,
|
|
pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_x);
|
|
CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_y,
|
|
pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_y);
|
|
CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_z,
|
|
pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_z);
|
|
CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_nx,
|
|
pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_nx);
|
|
CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_ny,
|
|
pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_ny);
|
|
CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_nz,
|
|
pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_nz);
|
|
}
|
|
return 0;
|
|
}
|
|
// normalize weights in mlod
|
|
void CMesh::NormalizeWeightsInLod(MeshLOD &mlod)
|
|
{
|
|
CStaticArray<float> aWeightFactors;
|
|
int ctvtx = mlod.mlod_aVertices.Count();
|
|
int ctwm = mlod.mlod_aWeightMaps.Count();
|
|
// create array for weights
|
|
aWeightFactors.New(ctvtx);
|
|
memset(&aWeightFactors[0],0,sizeof(aWeightFactors[0])*ctvtx);
|
|
int iwm;
|
|
for(iwm=0;iwm<ctwm;iwm++)
|
|
{
|
|
MeshWeightMap &mwm = mlod.mlod_aWeightMaps[iwm];
|
|
for(int iww=0;iww<mwm.mwm_aVertexWeight.Count();iww++)
|
|
{
|
|
MeshVertexWeight &mwh = mwm.mwm_aVertexWeight[iww];
|
|
aWeightFactors[mwh.mww_iVertex] += mwh.mww_fWeight;
|
|
}
|
|
}
|
|
|
|
for(iwm=0;iwm<ctwm;iwm++)
|
|
{
|
|
MeshWeightMap &mwm = mlod.mlod_aWeightMaps[iwm];
|
|
for(int iww=0;iww<mwm.mwm_aVertexWeight.Count();iww++)
|
|
{
|
|
MeshVertexWeight &mwh = mwm.mwm_aVertexWeight[iww];
|
|
mwh.mww_fWeight /= aWeightFactors[mwh.mww_iVertex];
|
|
}
|
|
}
|
|
// clear weight array
|
|
aWeightFactors.Clear();
|
|
}
|
|
// normalize weights in mesh
|
|
void CMesh::NormalizeWeights()
|
|
{
|
|
INDEX ctmlods = msh_aMeshLODs.Count();
|
|
for(INDEX imlod=0;imlod<ctmlods;imlod++)
|
|
{
|
|
// normalize each lod
|
|
NormalizeWeightsInLod(msh_aMeshLODs[imlod]);
|
|
}
|
|
}
|
|
// add new mesh lod to mesh
|
|
void CMesh::AddMeshLod(MeshLOD &mlod)
|
|
{
|
|
INDEX ctmlods = msh_aMeshLODs.Count();
|
|
msh_aMeshLODs.Expand(ctmlods+1);
|
|
msh_aMeshLODs[ctmlods] = mlod;
|
|
}
|
|
// remove mesh lod from mesh
|
|
void CMesh::RemoveMeshLod(MeshLOD *pmlodRemove)
|
|
{
|
|
INDEX ctmlod = msh_aMeshLODs.Count();
|
|
// create temp space for skeleton lods
|
|
CStaticArray<struct MeshLOD> aTempMLODs;
|
|
aTempMLODs.New(ctmlod-1);
|
|
INDEX iIndexSrc=0;
|
|
|
|
// for each skeleton lod in skeleton
|
|
for(INDEX imlod=0;imlod<ctmlod;imlod++)
|
|
{
|
|
MeshLOD *pmlod = &msh_aMeshLODs[imlod];
|
|
// copy all skeleton lods except the selected one
|
|
if(pmlod != pmlodRemove)
|
|
{
|
|
aTempMLODs[iIndexSrc] = *pmlod;
|
|
iIndexSrc++;
|
|
}
|
|
}
|
|
// copy temp array of skeleton lods back in skeleton
|
|
msh_aMeshLODs.CopyArray(aTempMLODs);
|
|
// clear temp skleletons lods array
|
|
aTempMLODs.Clear();
|
|
}
|
|
// write to stream
|
|
void CMesh::Write_t(CTStream *ostrFile)
|
|
{
|
|
INDEX ctmlods = msh_aMeshLODs.Count();
|
|
|
|
// write id
|
|
ostrFile->WriteID_t(CChunkID(MESH_ID));
|
|
// write version
|
|
(*ostrFile)<<(INDEX)MESH_VERSION;
|
|
// write mlod count
|
|
(*ostrFile)<<ctmlods;
|
|
// for each lod in mesh
|
|
for(INDEX imlod=0;imlod<ctmlods;imlod++) {
|
|
MeshLOD &mLod = msh_aMeshLODs[imlod];
|
|
|
|
INDEX ctVx = mLod.mlod_aVertices.Count(); // vertex count
|
|
INDEX ctUV = mLod.mlod_aUVMaps.Count(); // uvmaps count
|
|
INDEX ctSf = mLod.mlod_aSurfaces.Count(); // surfaces count
|
|
INDEX ctWM = mLod.mlod_aWeightMaps.Count(); // weight maps count
|
|
INDEX ctMM = mLod.mlod_aMorphMaps.Count(); // morph maps count
|
|
// write source file name
|
|
(*ostrFile)<<mLod.mlod_fnSourceFile;
|
|
// write max distance
|
|
(*ostrFile)<<mLod.mlod_fMaxDistance;
|
|
// write flags
|
|
(*ostrFile)<<mLod.mlod_ulFlags;
|
|
|
|
// write wertex count
|
|
(*ostrFile)<<ctVx;
|
|
// write wertices
|
|
ostrFile->Write_t(&mLod.mlod_aVertices[0],sizeof(MeshVertex)*ctVx);
|
|
// write normals
|
|
ostrFile->Write_t(&mLod.mlod_aNormals[0],sizeof(MeshNormal)*ctVx);
|
|
|
|
// write uvmaps count
|
|
(*ostrFile)<<ctUV;
|
|
// write uvmaps
|
|
for(int iuv=0;iuv<ctUV;iuv++) {
|
|
// write uvmap ID
|
|
CTString strNameID = ska_GetStringFromTable(mLod.mlod_aUVMaps[iuv].muv_iID);
|
|
(*ostrFile)<<strNameID;
|
|
// write uvmaps texcordinates
|
|
ostrFile->Write_t(&mLod.mlod_aUVMaps[iuv].muv_aTexCoords[0],sizeof(MeshTexCoord)*ctVx);
|
|
}
|
|
|
|
// write surfaces count
|
|
ostrFile->Write_t(&ctSf,sizeof(INDEX));
|
|
// write surfaces
|
|
for(INDEX isf=0;isf<ctSf;isf++) {
|
|
MeshSurface &msrf = mLod.mlod_aSurfaces[isf];
|
|
INDEX ctTris = msrf.msrf_aTriangles.Count();
|
|
CTString strSurfaceID = ska_GetStringFromTable(msrf.msrf_iSurfaceID);
|
|
// write surface ID
|
|
(*ostrFile)<<strSurfaceID;
|
|
// write first vertex
|
|
(*ostrFile)<<msrf.msrf_iFirstVertex;
|
|
// write vertices count
|
|
(*ostrFile)<<msrf.msrf_ctVertices;
|
|
// write tris count
|
|
(*ostrFile)<<ctTris;
|
|
// write triangles
|
|
ostrFile->Write_t(&mLod.mlod_aSurfaces[isf].msrf_aTriangles[0],sizeof(MeshTriangle)*ctTris);
|
|
|
|
// write bool that this surface has a shader
|
|
INDEX bShaderExists = (msrf.msrf_pShader!=NULL);
|
|
(*ostrFile)<<bShaderExists;
|
|
if(bShaderExists) {
|
|
// get shader decription
|
|
ShaderDesc shDesc;
|
|
msrf.msrf_pShader->GetShaderDesc(shDesc);
|
|
INDEX cttx=shDesc.sd_astrTextureNames.Count();
|
|
INDEX cttc=shDesc.sd_astrTexCoordNames.Count();
|
|
INDEX ctcol=shDesc.sd_astrColorNames.Count();
|
|
INDEX ctfl=shDesc.sd_astrFloatNames.Count();
|
|
// data count must be at same as size defined in shader or higher
|
|
ASSERT(cttx<=msrf.msrf_ShadingParams.sp_aiTextureIDs.Count());
|
|
ASSERT(cttc<=msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count());
|
|
ASSERT(ctcol<=msrf.msrf_ShadingParams.sp_acolColors.Count());
|
|
ASSERT(ctfl<=msrf.msrf_ShadingParams.sp_afFloats.Count());
|
|
ASSERT(msrf.msrf_pShader->GetShaderDesc!=NULL);
|
|
// write texture count
|
|
(*ostrFile)<<cttx;
|
|
// write texture coords count
|
|
(*ostrFile)<<cttc;
|
|
// write color count
|
|
(*ostrFile)<<ctcol;
|
|
// write float count
|
|
(*ostrFile)<<ctfl;
|
|
|
|
ASSERT(msrf.msrf_pShader!=NULL);
|
|
// write shader name
|
|
CTString strShaderName;
|
|
strShaderName = msrf.msrf_pShader->GetName();
|
|
(*ostrFile)<<strShaderName;
|
|
// write shader texture IDs
|
|
for(INDEX itx=0;itx<cttx;itx++)
|
|
{
|
|
INDEX iTexID = msrf.msrf_ShadingParams.sp_aiTextureIDs[itx];
|
|
(*ostrFile)<<ska_GetStringFromTable(iTexID);
|
|
}
|
|
// write shader texture coords indices
|
|
for(INDEX itc=0;itc<cttc;itc++)
|
|
{
|
|
INDEX iTexCoorsIndex = msrf.msrf_ShadingParams.sp_aiTexCoordsIndex[itc];
|
|
(*ostrFile)<<iTexCoorsIndex;
|
|
}
|
|
// write shader colors
|
|
for(INDEX icol=0;icol<ctcol;icol++)
|
|
{
|
|
COLOR colColor = msrf.msrf_ShadingParams.sp_acolColors[icol];
|
|
(*ostrFile)<<colColor;
|
|
}
|
|
// write shader floats
|
|
for(INDEX ifl=0;ifl<ctfl;ifl++)
|
|
{
|
|
FLOAT fFloat = msrf.msrf_ShadingParams.sp_afFloats[ifl];
|
|
(*ostrFile)<<fFloat;
|
|
}
|
|
// write shader flags
|
|
ULONG ulFlags = msrf.msrf_ShadingParams.sp_ulFlags;
|
|
(*ostrFile)<<ulFlags;
|
|
}
|
|
}
|
|
|
|
// write weightmaps count
|
|
(*ostrFile)<<ctWM;
|
|
// for each weightmap in array
|
|
for(INDEX iwm=0;iwm<ctWM;iwm++)
|
|
{
|
|
INDEX ctWw = mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight.Count();
|
|
// write wertex weight map ID
|
|
CTString pstrNameID = ska_GetStringFromTable(mLod.mlod_aWeightMaps[iwm].mwm_iID);
|
|
(*ostrFile)<<pstrNameID;
|
|
// write wertex weights count
|
|
(*ostrFile)<<ctWw;
|
|
// write wertex weights
|
|
ostrFile->Write_t(&mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight[0],sizeof(MeshVertexWeight)*ctWw);
|
|
}
|
|
|
|
// write morphmaps count
|
|
(*ostrFile)<<ctMM;
|
|
for(INDEX imm=0;imm<ctMM;imm++)
|
|
{
|
|
INDEX ctms = mLod.mlod_aMorphMaps[imm].mmp_aMorphMap.Count();
|
|
// write ID
|
|
CTString pstrNameID = ska_GetStringFromTable(mLod.mlod_aMorphMaps[imm].mmp_iID);
|
|
(*ostrFile)<<pstrNameID;
|
|
// write bRelative
|
|
(*ostrFile)<<mLod.mlod_aMorphMaps[imm].mmp_bRelative;
|
|
//ostrFile->Write_t(&mLod.mlod_aMorphMaps[imm].mmp_bRelative,sizeof(BOOL));
|
|
// write morph sets count
|
|
ostrFile->Write_t(&ctms,sizeof(INDEX));
|
|
// write morph sets
|
|
ostrFile->Write_t(&mLod.mlod_aMorphMaps[imm].mmp_aMorphMap[0],sizeof(MeshVertexMorph)*ctms);
|
|
}
|
|
}
|
|
}
|
|
|
|
//read from stream
|
|
void CMesh::Read_t(CTStream *istrFile)
|
|
{
|
|
INDEX ctmlods;
|
|
INDEX iFileVersion;
|
|
// read chunk id
|
|
istrFile->ExpectID_t(CChunkID(MESH_ID));
|
|
// check file version
|
|
(*istrFile)>>iFileVersion;
|
|
|
|
// if file version is not 11 nor 12
|
|
if(iFileVersion != 11 && iFileVersion!=12) {
|
|
ThrowF_t(TRANS("File '%s'.\nInvalid Mesh file version.\nExpected Ver \"%d\" but found \"%d\"\n"),
|
|
(const char*)istrFile->GetDescription(),MESH_VERSION,iFileVersion);
|
|
return;
|
|
}
|
|
|
|
// read mlod count
|
|
(*istrFile)>>ctmlods;
|
|
// for each lod in mesh
|
|
for(INDEX imlod=0;imlod<ctmlods;imlod++) {
|
|
// expand mlod count for one
|
|
INDEX ctMeshLODs = msh_aMeshLODs.Count();
|
|
msh_aMeshLODs.Expand(ctMeshLODs+1);
|
|
MeshLOD &mLod = msh_aMeshLODs[ctMeshLODs];
|
|
|
|
INDEX ctVx; // vertex count
|
|
INDEX ctUV; // uvmaps count
|
|
INDEX ctSf; // surfaces count
|
|
INDEX ctWM; // weight maps count
|
|
INDEX ctMM; // morph maps count
|
|
|
|
// read source file name
|
|
(*istrFile)>>mLod.mlod_fnSourceFile;
|
|
// read max distance
|
|
(*istrFile)>>mLod.mlod_fMaxDistance;
|
|
// read flags
|
|
(*istrFile)>>mLod.mlod_ulFlags;
|
|
|
|
// :)
|
|
if(iFileVersion<=11) {
|
|
mLod.mlod_ulFlags = 0;
|
|
}
|
|
if(mLod.mlod_ulFlags==0xCDCDCDCD) {
|
|
mLod.mlod_ulFlags = 0;
|
|
}
|
|
|
|
|
|
// read vertex count
|
|
(*istrFile)>>ctVx;
|
|
// create vertex and normal arrays
|
|
mLod.mlod_aVertices.New(ctVx);
|
|
mLod.mlod_aNormals.New(ctVx);
|
|
// read vertices
|
|
for (INDEX i = 0; i < ctVx; i++)
|
|
(*istrFile)>>mLod.mlod_aVertices[i];
|
|
// read normals
|
|
for (INDEX i = 0; i < ctVx; i++)
|
|
(*istrFile)>>mLod.mlod_aNormals[i];
|
|
|
|
// read uvmaps count
|
|
(*istrFile)>>ctUV;
|
|
// create array for uvmaps
|
|
mLod.mlod_aUVMaps.New(ctUV);
|
|
// read uvmaps
|
|
for(int iuv=0;iuv<ctUV;iuv++) {
|
|
// read uvmap ID
|
|
CTString strNameID;
|
|
(*istrFile)>>strNameID;
|
|
mLod.mlod_aUVMaps[iuv].muv_iID = ska_GetIDFromStringTable(strNameID);
|
|
// create array for uvmaps texcordinates
|
|
mLod.mlod_aUVMaps[iuv].muv_aTexCoords.New(ctVx);
|
|
// read uvmap texcordinates
|
|
for (INDEX i = 0; i < ctVx; i++)
|
|
(*istrFile)>>mLod.mlod_aUVMaps[iuv].muv_aTexCoords[i];
|
|
}
|
|
// read surfaces count
|
|
(*istrFile)>>ctSf;
|
|
// create array for surfaces
|
|
mLod.mlod_aSurfaces.New(ctSf);
|
|
// read surfaces
|
|
for(INDEX isf=0;isf<ctSf;isf++) {
|
|
INDEX ctTris;
|
|
MeshSurface &msrf = mLod.mlod_aSurfaces[isf];
|
|
// read surface ID
|
|
CTString strSurfaceID;
|
|
(*istrFile)>>strSurfaceID;
|
|
msrf.msrf_iSurfaceID = ska_GetIDFromStringTable(strSurfaceID);
|
|
// read first vertex
|
|
(*istrFile)>>msrf.msrf_iFirstVertex;
|
|
// read vertices count
|
|
(*istrFile)>>msrf.msrf_ctVertices;
|
|
// read tris count
|
|
(*istrFile)>>ctTris;
|
|
// create triangles array
|
|
mLod.mlod_aSurfaces[isf].msrf_aTriangles.New(ctTris);
|
|
// read triangles
|
|
for (INDEX i = 0; i < ctTris; i++)
|
|
(*istrFile)>>mLod.mlod_aSurfaces[isf].msrf_aTriangles[i];
|
|
|
|
// read bool that this surface has a shader
|
|
INDEX bShaderExists;
|
|
(*istrFile)>>bShaderExists;
|
|
// if shader exists read its params
|
|
if(bShaderExists) {
|
|
INDEX cttx,cttc,ctcol,ctfl;
|
|
// read texture count
|
|
(*istrFile)>>cttx;
|
|
// read texture coords count
|
|
(*istrFile)>>cttc;
|
|
// read color count
|
|
(*istrFile)>>ctcol;
|
|
// read float count
|
|
(*istrFile)>>ctfl;
|
|
|
|
//CShader *pshMeshShader = NULL;
|
|
ShaderParams *pshpShaderParams = NULL;
|
|
CShader shDummyShader; // dummy shader if shader is not found
|
|
ShaderParams shpDummyShaderParams;// dummy shader params if shader is not found
|
|
// read shader name
|
|
CTString strShaderName;
|
|
(*istrFile)>>strShaderName;
|
|
// try to load shader
|
|
try{
|
|
msrf.msrf_pShader = _pShaderStock->Obtain_t(strShaderName);
|
|
//pshMeshShader = msrf.msrf_pShader;
|
|
pshpShaderParams = &msrf.msrf_ShadingParams;
|
|
} catch(char *strErr) {
|
|
CPrintF("%s\n",strErr);
|
|
msrf.msrf_pShader = NULL;
|
|
//pshMeshShader = &shDummyShader;
|
|
pshpShaderParams = &shpDummyShaderParams;
|
|
}
|
|
|
|
// if mesh shader exisits
|
|
if(msrf.msrf_pShader!=NULL) {
|
|
// get shader description
|
|
ShaderDesc shDesc;
|
|
msrf.msrf_pShader->GetShaderDesc(shDesc);
|
|
// check if saved params count match shader params count
|
|
if(shDesc.sd_astrTextureNames.Count() != cttx) ThrowF_t("File '%s'\nWrong texture count %d",(const char*)GetName(),cttx);
|
|
if(shDesc.sd_astrTexCoordNames.Count() != cttc) ThrowF_t("File '%s'\nWrong uvmaps count %d",(const char*)GetName(),cttc);
|
|
if(shDesc.sd_astrColorNames.Count() != ctcol) ThrowF_t("File '%s'\nWrong colors count %d",(const char*)GetName(),ctcol);
|
|
if(shDesc.sd_astrFloatNames.Count() != ctfl) ThrowF_t("File '%s'\nWrong floats count %d",(const char*)GetName(),ctfl);
|
|
}
|
|
|
|
// create arrays for shader params
|
|
pshpShaderParams->sp_aiTextureIDs.New(cttx);
|
|
pshpShaderParams->sp_aiTexCoordsIndex.New(cttc);
|
|
pshpShaderParams->sp_acolColors.New(ctcol);
|
|
pshpShaderParams->sp_afFloats.New(ctfl);
|
|
|
|
// read shader texture IDs
|
|
for(INDEX itx=0;itx<cttx;itx++) {
|
|
CTString strTexID;
|
|
(*istrFile)>>strTexID;
|
|
INDEX iTexID = ska_GetIDFromStringTable(strTexID);
|
|
pshpShaderParams->sp_aiTextureIDs[itx] = iTexID;
|
|
}
|
|
// read shader texture coords indices
|
|
for(INDEX itc=0;itc<cttc;itc++) {
|
|
INDEX iTexCoorsIndex;
|
|
(*istrFile)>>iTexCoorsIndex;
|
|
pshpShaderParams->sp_aiTexCoordsIndex[itc] = iTexCoorsIndex;
|
|
}
|
|
// read shader colors
|
|
for(INDEX icol=0;icol<ctcol;icol++) {
|
|
COLOR colColor;
|
|
(*istrFile)>>colColor;
|
|
pshpShaderParams->sp_acolColors[icol] = colColor;
|
|
}
|
|
// read shader floats
|
|
for(INDEX ifl=0;ifl<ctfl;ifl++) {
|
|
FLOAT fFloat;
|
|
(*istrFile)>>fFloat;
|
|
pshpShaderParams->sp_afFloats[ifl] = fFloat;
|
|
}
|
|
// there were no flags in shader before ver 12
|
|
if(iFileVersion>11) {
|
|
ULONG ulFlags;
|
|
(*istrFile)>>ulFlags;
|
|
pshpShaderParams->sp_ulFlags = ulFlags;
|
|
} else {
|
|
pshpShaderParams->sp_ulFlags = 0;
|
|
}
|
|
} else {
|
|
// this surface does not have shader
|
|
msrf.msrf_pShader=NULL;
|
|
}
|
|
}
|
|
|
|
// read weightmaps count
|
|
(*istrFile)>>ctWM;
|
|
// create weightmap array
|
|
mLod.mlod_aWeightMaps.New(ctWM);
|
|
// read each weightmap
|
|
for(INDEX iwm=0;iwm<ctWM;iwm++) {
|
|
// read weightmap ID
|
|
CTString pstrNameID;
|
|
(*istrFile)>>pstrNameID;
|
|
mLod.mlod_aWeightMaps[iwm].mwm_iID = ska_GetIDFromStringTable(pstrNameID);
|
|
// read wertex weight count
|
|
INDEX ctWw;
|
|
(*istrFile)>>ctWw;
|
|
// create wertex weight array
|
|
mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight.New(ctWw);
|
|
// read wertex weights
|
|
for (INDEX i = 0; i < ctWw; i++)
|
|
(*istrFile)>>mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight[i];
|
|
}
|
|
|
|
// read morphmap count
|
|
(*istrFile)>>ctMM;
|
|
// create morphmaps array
|
|
mLod.mlod_aMorphMaps.New(ctMM);
|
|
// read morphmaps
|
|
for(INDEX imm=0;imm<ctMM;imm++) {
|
|
// read morphmap ID
|
|
CTString pstrNameID;
|
|
(*istrFile)>>pstrNameID;
|
|
mLod.mlod_aMorphMaps[imm].mmp_iID = ska_GetIDFromStringTable(pstrNameID);
|
|
// read bRelative
|
|
(*istrFile)>>mLod.mlod_aMorphMaps[imm].mmp_bRelative;
|
|
// read morph sets count
|
|
INDEX ctms;
|
|
(*istrFile)>>ctms;
|
|
// create morps sets array
|
|
mLod.mlod_aMorphMaps[imm].mmp_aMorphMap.New(ctms);
|
|
// read morph sets
|
|
for (INDEX i = 0; i < ctms; i++)
|
|
(*istrFile)>>mLod.mlod_aMorphMaps[imm].mmp_aMorphMap[i];
|
|
}
|
|
}
|
|
}
|
|
// clear mesh
|
|
void CMesh::Clear(void)
|
|
{
|
|
// for each LOD
|
|
INDEX ctmlod = msh_aMeshLODs.Count();
|
|
for (INDEX imlod=0; imlod<ctmlod; imlod++)
|
|
{
|
|
// for each surface, clear the triangles list
|
|
MeshLOD &mlod = msh_aMeshLODs[imlod];
|
|
INDEX ctsrf = mlod.mlod_aSurfaces.Count();
|
|
for (INDEX isrf=0;isrf<ctsrf;isrf++)
|
|
{
|
|
MeshSurface &msrf = mlod.mlod_aSurfaces[isrf];
|
|
msrf.msrf_aTriangles.Clear();
|
|
// release shader form stock
|
|
if(msrf.msrf_pShader!=NULL) _pShaderStock->Release(msrf.msrf_pShader);
|
|
msrf.msrf_pShader = NULL;
|
|
}
|
|
// clear the surfaces array
|
|
mlod.mlod_aSurfaces.Clear();
|
|
// for each uvmap, clear the texcord list
|
|
INDEX ctuvm = mlod.mlod_aUVMaps.Count();
|
|
for (INDEX iuvm=0;iuvm<ctuvm;iuvm++)
|
|
{
|
|
mlod.mlod_aUVMaps[iuvm].muv_aTexCoords.Clear();
|
|
}
|
|
// clear the uvmaps array
|
|
mlod.mlod_aUVMaps.Clear();
|
|
// clear the vertices array
|
|
mlod.mlod_aVertices.Clear();
|
|
// clear the normals array
|
|
mlod.mlod_aNormals.Clear();
|
|
}
|
|
// in the end, clear all LODs
|
|
msh_aMeshLODs.Clear();
|
|
}
|
|
|
|
// Count used memory
|
|
SLONG CMesh::GetUsedMemory(void)
|
|
{
|
|
SLONG slMemoryUsed = sizeof(*this);
|
|
INDEX ctmlods = msh_aMeshLODs.Count();
|
|
for(INDEX imlod=0;imlod<ctmlods;imlod++) {
|
|
MeshLOD &mlod = msh_aMeshLODs[imlod];
|
|
slMemoryUsed+=sizeof(mlod);
|
|
slMemoryUsed+=mlod.mlod_aVertices.Count() * sizeof(MeshVertex);
|
|
slMemoryUsed+=mlod.mlod_aNormals.Count() * sizeof(MeshNormal);
|
|
|
|
// for each uvmap
|
|
INDEX ctuvmaps = mlod.mlod_aUVMaps.Count();
|
|
for(INDEX iuvm=0;iuvm<ctuvmaps;iuvm++) {
|
|
MeshUVMap &uvmap = mlod.mlod_aUVMaps[iuvm];
|
|
slMemoryUsed+=sizeof(uvmap);
|
|
slMemoryUsed+=uvmap.muv_aTexCoords.Count() * sizeof(MeshTexCoord);
|
|
}
|
|
|
|
// for each surface
|
|
INDEX ctmsrf = mlod.mlod_aSurfaces.Count();
|
|
for(INDEX imsrf=0;imsrf<ctmsrf;imsrf++) {
|
|
MeshSurface &msrf = mlod.mlod_aSurfaces[imsrf];
|
|
slMemoryUsed+=sizeof(msrf);
|
|
slMemoryUsed+=msrf.msrf_aTriangles.Count() * sizeof(MeshTriangle);
|
|
slMemoryUsed+=sizeof(ShaderParams);
|
|
slMemoryUsed+=sizeof(INDEX) * msrf.msrf_ShadingParams.sp_aiTextureIDs.Count();
|
|
slMemoryUsed+=sizeof(INDEX) * msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count();
|
|
slMemoryUsed+=sizeof(COLOR) * msrf.msrf_ShadingParams.sp_acolColors.Count();
|
|
slMemoryUsed+=sizeof(FLOAT) * msrf.msrf_ShadingParams.sp_afFloats.Count();
|
|
}
|
|
// for each weight map
|
|
INDEX ctwm = mlod.mlod_aWeightMaps.Count();
|
|
for(INDEX iwm=0;iwm<ctwm;iwm++) {
|
|
MeshWeightMap &mwm = mlod.mlod_aWeightMaps[iwm];
|
|
slMemoryUsed+=sizeof(mwm);
|
|
slMemoryUsed+=mwm.mwm_aVertexWeight.Count() * sizeof(MeshVertexWeight);
|
|
}
|
|
// for each morphmap
|
|
INDEX ctmm = mlod.mlod_aMorphMaps.Count();
|
|
for(INDEX imm=0;imm<ctmm;imm++) {
|
|
MeshMorphMap &mmm = mlod.mlod_aMorphMaps[imm];
|
|
slMemoryUsed+=sizeof(mmm);
|
|
slMemoryUsed+=mmm.mmp_aMorphMap.Count() * sizeof(MeshVertexMorph);
|
|
}
|
|
}
|
|
return slMemoryUsed;
|
|
}
|