Mesh.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include "Mesh.h"
  14. #define MESH_VERSION 12
  15. #define MESH_ID "MESH"
  16. #include <Engine/Base/Stream.h>
  17. #include <Engine/Base/Console.h>
  18. #include <Engine/Ska/StringTable.h>
  19. #include <Engine/Math/Projection.h>
  20. #include <Engine/Graphics/DrawPort.h>
  21. #include <Engine/Graphics/Shader.h>
  22. #include <Engine/Templates/StaticArray.h>
  23. #include <Engine/Templates/StaticArray.cpp>
  24. #include <Engine/Templates/Stock_CShader.h>
  25. INDEX AreVerticesDiferent(INDEX iCurentIndex, INDEX iLastIndex);
  26. struct VertexLocator
  27. {
  28. INDEX vl_iIndex;
  29. INDEX vl_iSubIndex;
  30. };
  31. struct SortArray
  32. {
  33. INDEX sa_iNewIndex;
  34. INDEX sa_iSurfaceIndex;
  35. CStaticArray<struct VertexLocator> sa_aWeightMapList;
  36. CStaticArray<struct VertexLocator> sa_aMorphMapList;
  37. };
  38. CStaticArray <struct SortArray> _aSortArray;
  39. CStaticArray <INDEX> _aiOptimizedIndex;
  40. CStaticArray <INDEX> _aiSortedIndex;
  41. MeshLOD *pMeshLOD;// curent mesh lod (for quick sort)
  42. MeshLOD mshOptimized;
  43. CMesh::CMesh()
  44. {
  45. }
  46. CMesh::~CMesh()
  47. {
  48. }
  49. // release old shader and obtain new shader for mesh surface (expand ShaderParams if needed)
  50. void ChangeSurfaceShader_t(MeshSurface &msrf,CTString fnNewShader)
  51. {
  52. CShader *pShaderNew = _pShaderStock->Obtain_t(fnNewShader);
  53. ASSERT(pShaderNew!=NULL);
  54. if(msrf.msrf_pShader!=NULL) _pShaderStock->Release(msrf.msrf_pShader);
  55. msrf.msrf_pShader = pShaderNew;
  56. // get new shader description
  57. ShaderDesc shDesc;
  58. msrf.msrf_pShader->GetShaderDesc(shDesc);
  59. // if needed expand size of arrays for new shader
  60. // reset new values!!!!
  61. INDEX ctOldTextureIDs = msrf.msrf_ShadingParams.sp_aiTextureIDs.Count();
  62. INDEX ctNewTextureIDs = shDesc.sd_astrTextureNames.Count();
  63. INDEX ctOldUVMaps = msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count();
  64. INDEX ctNewUVMaps = shDesc.sd_astrTexCoordNames.Count();
  65. INDEX ctOldColors = msrf.msrf_ShadingParams.sp_acolColors.Count();
  66. INDEX ctNewColors = shDesc.sd_astrColorNames.Count();
  67. INDEX ctOldFloats = msrf.msrf_ShadingParams.sp_afFloats.Count();
  68. INDEX ctNewFloats = shDesc.sd_astrFloatNames.Count();
  69. if(ctOldTextureIDs<ctNewTextureIDs) {
  70. // expand texture IDs array
  71. msrf.msrf_ShadingParams.sp_aiTextureIDs.Expand(ctNewTextureIDs);
  72. // set new texture IDs to 0
  73. for(INDEX itx=ctOldTextureIDs;itx<ctNewTextureIDs;itx++) {
  74. msrf.msrf_ShadingParams.sp_aiTextureIDs[itx] = -1;
  75. }
  76. }
  77. // expand array of uvmaps if needed
  78. if(ctOldUVMaps<ctNewUVMaps) {
  79. // expand uvmaps IDs array
  80. msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Expand(ctNewUVMaps);
  81. // set new uvmaps indices to 0
  82. for(INDEX itxc=ctOldUVMaps;itxc<ctNewUVMaps;itxc++) {
  83. msrf.msrf_ShadingParams.sp_aiTexCoordsIndex[itxc] = 0;
  84. }
  85. }
  86. // expand array of colors if needed
  87. if(ctOldColors<ctNewColors) {
  88. // expand color array
  89. msrf.msrf_ShadingParams.sp_acolColors.Expand(ctNewColors);
  90. // set new colors indices white
  91. for(INDEX icol=ctOldUVMaps;icol<ctNewColors;icol++) {
  92. msrf.msrf_ShadingParams.sp_acolColors[icol] = 0xFFFFFFFF;
  93. }
  94. }
  95. // expand array of floats if needed
  96. if(ctOldFloats<ctNewFloats) {
  97. // expand float array
  98. msrf.msrf_ShadingParams.sp_afFloats.Expand(ctNewFloats);
  99. // set new floats to 0
  100. for(INDEX ifl=ctOldFloats;ifl<ctNewFloats;ifl++) {
  101. msrf.msrf_ShadingParams.sp_afFloats[ifl] = 1;
  102. }
  103. }
  104. }
  105. // quck sort func for comparing vertices
  106. static int qsort_CompareArray(const void *pVx1, const void *pVx2)
  107. {
  108. INDEX *n1 = ((INDEX*)pVx1);
  109. INDEX *n2 = ((INDEX*)pVx2);
  110. return AreVerticesDiferent(*n1,*n2);
  111. }
  112. // clear array of sort vertices
  113. void ClearSortArray(INDEX ctOldVertices)
  114. {
  115. for(int iv=0;iv<ctOldVertices;iv++)
  116. {
  117. _aSortArray[iv].sa_aWeightMapList.Clear();
  118. _aSortArray[iv].sa_aMorphMapList.Clear();
  119. }
  120. _aiOptimizedIndex.Clear();
  121. _aiSortedIndex.Clear();
  122. _aSortArray.Clear();
  123. }
  124. // optimize mesh
  125. void CMesh::Optimize(void)
  126. {
  127. INDEX ctmshlods = msh_aMeshLODs.Count();
  128. for(int imshlod=0;imshlod<ctmshlods;imshlod++)
  129. {
  130. // optimize each lod in mesh
  131. OptimizeLod(msh_aMeshLODs[imshlod]);
  132. }
  133. }
  134. // optimize lod of mesh
  135. void CMesh::OptimizeLod(MeshLOD &mLod)
  136. {
  137. INDEX ctVertices = mLod.mlod_aVertices.Count();
  138. INDEX ctSurfaces = mLod.mlod_aSurfaces.Count();
  139. INDEX ctUVMaps = mLod.mlod_aUVMaps.Count();
  140. INDEX ctWeightMaps = mLod.mlod_aWeightMaps.Count();
  141. INDEX ctMorphMaps = mLod.mlod_aMorphMaps.Count();
  142. if(ctVertices<=0) return;
  143. // create array for sorting
  144. _aSortArray.New(ctVertices);
  145. _aiSortedIndex.New(ctVertices);
  146. _aiOptimizedIndex.New(ctVertices);
  147. // put original vertex indices in SortArray
  148. for(int iv=0;iv<ctVertices;iv++)
  149. {
  150. _aiSortedIndex[iv] = iv;
  151. }
  152. // loop each surface and expand SurfaceList in SortArray
  153. int is=0;
  154. for(;is<ctSurfaces;is++)
  155. {
  156. INDEX ctts=mLod.mlod_aSurfaces[is].msrf_aTriangles.Count();
  157. for(int its=0;its<ctts;its++)
  158. {
  159. MeshTriangle &mtTriangle = mLod.mlod_aSurfaces[is].msrf_aTriangles[its];
  160. _aSortArray[mtTriangle.iVertex[0]].sa_iSurfaceIndex = is;
  161. _aSortArray[mtTriangle.iVertex[1]].sa_iSurfaceIndex = is;
  162. _aSortArray[mtTriangle.iVertex[2]].sa_iSurfaceIndex = is;
  163. }
  164. }
  165. // loop each weightmap and expand sa_aWeightMapList in SortArray
  166. for(INDEX iw=0;iw<ctWeightMaps;iw++)
  167. {
  168. // loop each wertex weight array in weight map array
  169. INDEX ctwm = mLod.mlod_aWeightMaps[iw].mwm_aVertexWeight.Count();
  170. for(INDEX iwm=0;iwm<ctwm;iwm++)
  171. {
  172. MeshVertexWeight &mwwWeight = mLod.mlod_aWeightMaps[iw].mwm_aVertexWeight[iwm];
  173. // get curent list num of weightmaps
  174. INDEX ctWeightMapList = _aSortArray[mwwWeight.mww_iVertex].sa_aWeightMapList.Count();
  175. // expand array of sufrace lists for 1
  176. _aSortArray[mwwWeight.mww_iVertex].sa_aWeightMapList.Expand(ctWeightMapList+1);
  177. // set vl_iIndex to index of surface
  178. // set vl_iSubIndex to index in triangle set
  179. VertexLocator &vxLoc = _aSortArray[mwwWeight.mww_iVertex].sa_aWeightMapList[ctWeightMapList];
  180. vxLoc.vl_iIndex = iw;
  181. vxLoc.vl_iSubIndex = iwm;
  182. }
  183. }
  184. // loop each morphmap and expand sa_aMorphMapList in SortArray
  185. for(INDEX im=0;im<ctMorphMaps;im++)
  186. {
  187. // loop each morph map in array
  188. INDEX ctmm = mLod.mlod_aMorphMaps[im].mmp_aMorphMap.Count();
  189. for(INDEX imm=0;imm<ctmm;imm++)
  190. {
  191. MeshVertexMorph &mwmMorph = mLod.mlod_aMorphMaps[im].mmp_aMorphMap[imm];
  192. // get curent list num of morphmaps
  193. INDEX ctMorphMapList = _aSortArray[mwmMorph.mwm_iVxIndex].sa_aMorphMapList.Count();
  194. // expand array of sufrace lists for 1
  195. _aSortArray[mwmMorph.mwm_iVxIndex].sa_aMorphMapList.Expand(ctMorphMapList+1);
  196. // set vl_iIndex to index of surface
  197. // set vl_iSubIndex to index in triangle set
  198. VertexLocator &vxLoc = _aSortArray[mwmMorph.mwm_iVxIndex].sa_aMorphMapList[ctMorphMapList];
  199. vxLoc.vl_iIndex = im;
  200. vxLoc.vl_iSubIndex = imm;
  201. }
  202. }
  203. // set global pMeshLOD pointer used by quicksort
  204. pMeshLOD = &mLod;
  205. // sort array
  206. qsort(&_aiSortedIndex[0],ctVertices,sizeof(&_aiSortedIndex[0]),qsort_CompareArray);
  207. // compare vertices
  208. INDEX iDiferentVertices = 1;
  209. INDEX iLastIndex = _aiSortedIndex[0];
  210. _aSortArray[iLastIndex].sa_iNewIndex = 0;
  211. _aiOptimizedIndex[0] = iLastIndex;
  212. for(INDEX isa=1;isa<ctVertices;isa++)
  213. {
  214. INDEX iCurentIndex = _aiSortedIndex[isa];
  215. // check if vertices are diferent
  216. if(AreVerticesDiferent(iLastIndex,iCurentIndex))
  217. {
  218. // add Curent index to Optimized index array
  219. _aiOptimizedIndex[iDiferentVertices] = iCurentIndex;
  220. iDiferentVertices++;
  221. iLastIndex = iCurentIndex;
  222. }
  223. _aSortArray[iCurentIndex].sa_iNewIndex = iDiferentVertices-1;
  224. }
  225. // create new mesh
  226. INDEX ctNewVertices = iDiferentVertices;
  227. mshOptimized.mlod_aVertices.New(ctNewVertices);
  228. mshOptimized.mlod_aNormals.New(ctNewVertices);
  229. mshOptimized.mlod_aUVMaps.New(ctUVMaps);
  230. for(INDEX iuvm=0;iuvm<ctUVMaps;iuvm++)
  231. {
  232. mshOptimized.mlod_aUVMaps[iuvm].muv_aTexCoords.New(ctNewVertices);
  233. }
  234. // add new vertices and normals to mshOptimized
  235. for(INDEX iNewVx=0;iNewVx<ctNewVertices;iNewVx++)
  236. {
  237. mshOptimized.mlod_aVertices[iNewVx] = mLod.mlod_aVertices[_aiOptimizedIndex[iNewVx]];
  238. mshOptimized.mlod_aNormals[iNewVx] = mLod.mlod_aNormals[_aiOptimizedIndex[iNewVx]];
  239. for(INDEX iuvm=0;iuvm<ctUVMaps;iuvm++)
  240. {
  241. //???
  242. mshOptimized.mlod_aUVMaps[iuvm].muv_iID = mLod.mlod_aUVMaps[iuvm].muv_iID;
  243. mshOptimized.mlod_aUVMaps[iuvm].muv_aTexCoords[iNewVx] = mLod.mlod_aUVMaps[iuvm].muv_aTexCoords[_aiOptimizedIndex[iNewVx]];
  244. }
  245. }
  246. // remap surface triangles
  247. for(is=0;is<ctSurfaces;is++)
  248. {
  249. MeshSurface &msrf = mLod.mlod_aSurfaces[is];
  250. INDEX iMinIndex = ctNewVertices+1;
  251. INDEX iMaxIndex = -1;
  252. INDEX ctts=msrf.msrf_aTriangles.Count();
  253. // for each triangle in this surface
  254. INDEX its=0;
  255. for(;its<ctts;its++)
  256. {
  257. MeshTriangle &mtTriangle = msrf.msrf_aTriangles[its];
  258. // for each vertex in triangle
  259. for(INDEX iv=0;iv<3;iv++)
  260. {
  261. mtTriangle.iVertex[iv] = _aSortArray[mtTriangle.iVertex[iv]].sa_iNewIndex;
  262. // find first index in this surface
  263. if(mtTriangle.iVertex[iv]<iMinIndex) iMinIndex = mtTriangle.iVertex[iv];
  264. // find last index in this surface
  265. if(mtTriangle.iVertex[iv]>iMaxIndex) iMaxIndex = mtTriangle.iVertex[iv];
  266. }
  267. }
  268. // remember first index in vertices array
  269. msrf.msrf_iFirstVertex = iMinIndex;
  270. // remember vertices count
  271. msrf.msrf_ctVertices = iMaxIndex-iMinIndex+1;
  272. // for each triangle in surface
  273. for(its=0;its<ctts;its++)
  274. {
  275. MeshTriangle &mtTriangle = msrf.msrf_aTriangles[its];
  276. // for each vertex in triangle
  277. for(INDEX iv=0;iv<3;iv++)
  278. {
  279. // substract vertex index in triangle with first vertex in surface
  280. mtTriangle.iVertex[iv] -= msrf.msrf_iFirstVertex;
  281. ASSERT(mtTriangle.iVertex[iv]<msrf.msrf_ctVertices);
  282. }
  283. }
  284. }
  285. // remap weightmaps
  286. mshOptimized.mlod_aWeightMaps.New(ctWeightMaps);
  287. // expand wertex veights array for each vertex
  288. INDEX ivx=0;
  289. for(;ivx<ctNewVertices;ivx++)
  290. {
  291. INDEX ioptVx = _aiOptimizedIndex[ivx];
  292. for(INDEX iwl=0;iwl<_aSortArray[ioptVx].sa_aWeightMapList.Count();iwl++)
  293. {
  294. VertexLocator &wml = _aSortArray[ioptVx].sa_aWeightMapList[iwl];
  295. INDEX wmIndex = wml.vl_iIndex;
  296. INDEX wwIndex = wml.vl_iSubIndex;
  297. INDEX ctww = mshOptimized.mlod_aWeightMaps[wmIndex].mwm_aVertexWeight.Count();
  298. MeshWeightMap &mwm = mshOptimized.mlod_aWeightMaps[wmIndex];
  299. MeshVertexWeight &mww = mLod.mlod_aWeightMaps[wmIndex].mwm_aVertexWeight[wwIndex];
  300. mwm.mwm_iID = mLod.mlod_aWeightMaps[wmIndex].mwm_iID;
  301. mwm.mwm_aVertexWeight.Expand(ctww+1);
  302. mwm.mwm_aVertexWeight[ctww].mww_fWeight = mww.mww_fWeight;
  303. mwm.mwm_aVertexWeight[ctww].mww_iVertex = ivx;
  304. }
  305. }
  306. // remap morphmaps
  307. mshOptimized.mlod_aMorphMaps.New(ctMorphMaps);
  308. // expand morph maps array for each vertex
  309. for(ivx=0;ivx<ctNewVertices;ivx++)
  310. {
  311. INDEX ioptVx = _aiOptimizedIndex[ivx];
  312. for(INDEX iml=0;iml<_aSortArray[ioptVx].sa_aMorphMapList.Count();iml++)
  313. {
  314. VertexLocator &mml = _aSortArray[ioptVx].sa_aMorphMapList[iml];
  315. INDEX mmIndex = mml.vl_iIndex;
  316. INDEX mwmIndex = mml.vl_iSubIndex;
  317. INDEX ctmwm = mshOptimized.mlod_aMorphMaps[mmIndex].mmp_aMorphMap.Count();
  318. MeshMorphMap &mmm = mshOptimized.mlod_aMorphMaps[mmIndex];
  319. MeshVertexMorph &mwm = mLod.mlod_aMorphMaps[mmIndex].mmp_aMorphMap[mwmIndex];
  320. mmm.mmp_iID = mLod.mlod_aMorphMaps[mmIndex].mmp_iID;
  321. mmm.mmp_bRelative = mLod.mlod_aMorphMaps[mmIndex].mmp_bRelative;
  322. mmm.mmp_aMorphMap.Expand(ctmwm+1);
  323. mmm.mmp_aMorphMap[ctmwm].mwm_iVxIndex = ivx;
  324. mmm.mmp_aMorphMap[ctmwm].mwm_x = mwm.mwm_x;
  325. mmm.mmp_aMorphMap[ctmwm].mwm_y = mwm.mwm_y;
  326. mmm.mmp_aMorphMap[ctmwm].mwm_z = mwm.mwm_z;
  327. mmm.mmp_aMorphMap[ctmwm].mwm_nx = mwm.mwm_nx;
  328. mmm.mmp_aMorphMap[ctmwm].mwm_ny = mwm.mwm_ny;
  329. mmm.mmp_aMorphMap[ctmwm].mwm_nz = mwm.mwm_nz;
  330. }
  331. }
  332. mLod.mlod_aVertices.CopyArray(mshOptimized.mlod_aVertices);
  333. mLod.mlod_aNormals.CopyArray(mshOptimized.mlod_aNormals);
  334. mLod.mlod_aMorphMaps.CopyArray(mshOptimized.mlod_aMorphMaps);
  335. mLod.mlod_aWeightMaps.CopyArray(mshOptimized.mlod_aWeightMaps);
  336. mLod.mlod_aUVMaps.CopyArray(mshOptimized.mlod_aUVMaps);
  337. // clear memory
  338. ClearSortArray(ctVertices);
  339. mshOptimized.mlod_aVertices.Clear();
  340. mshOptimized.mlod_aNormals.Clear();
  341. mshOptimized.mlod_aWeightMaps.Clear();
  342. mshOptimized.mlod_aMorphMaps.Clear();
  343. mshOptimized.mlod_aUVMaps.Clear();
  344. }
  345. INDEX AreVerticesDiferent(INDEX iCurentIndex, INDEX iLastIndex)
  346. {
  347. #define CHECK(x,y) if(((x)-(y))!=0) return ((x)-(y))
  348. #define CHECKF(x,y) if(((x)-(y))!=0) return Sgn((x)-(y))
  349. // check surfaces
  350. CHECK(_aSortArray[iCurentIndex].sa_iSurfaceIndex,_aSortArray[iLastIndex].sa_iSurfaceIndex);
  351. // check vertices
  352. CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].y,pMeshLOD->mlod_aVertices[iLastIndex].y);
  353. CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].x,pMeshLOD->mlod_aVertices[iLastIndex].x);
  354. CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].z,pMeshLOD->mlod_aVertices[iLastIndex].z);
  355. // check normals
  356. CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].ny,pMeshLOD->mlod_aNormals[iLastIndex].ny);
  357. CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].nx,pMeshLOD->mlod_aNormals[iLastIndex].nx);
  358. CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].nz,pMeshLOD->mlod_aNormals[iLastIndex].nz);
  359. // check uvmaps
  360. INDEX ctUVMaps = pMeshLOD->mlod_aUVMaps.Count();
  361. for(INDEX iuvm=0;iuvm<ctUVMaps;iuvm++)
  362. {
  363. CHECKF(pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iCurentIndex].u,pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iLastIndex].u);
  364. CHECKF(pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iCurentIndex].v,pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iLastIndex].v);
  365. }
  366. // count weight and morph maps
  367. INDEX ctwmCurent = _aSortArray[iCurentIndex].sa_aWeightMapList.Count();
  368. INDEX ctwmLast = _aSortArray[iLastIndex].sa_aWeightMapList.Count();
  369. INDEX ctmmCurent = _aSortArray[iCurentIndex].sa_aMorphMapList.Count();
  370. INDEX ctmmLast = _aSortArray[iLastIndex].sa_aMorphMapList.Count();
  371. // check if vertices have same weight and morph maps count
  372. CHECK(ctwmCurent,ctwmLast);
  373. CHECK(ctmmCurent,ctmmLast);
  374. // check if vertices have same weight map factors
  375. for(INDEX iwm=0;iwm<ctwmCurent;iwm++)
  376. {
  377. // get weight map indices
  378. INDEX iwmCurent = _aSortArray[iCurentIndex].sa_aWeightMapList[iwm].vl_iIndex;
  379. INDEX iwmLast = _aSortArray[iLastIndex].sa_aWeightMapList[iwm].vl_iIndex;
  380. // get wertex weight indices
  381. INDEX iwwCurent = _aSortArray[iCurentIndex].sa_aWeightMapList[iwm].vl_iSubIndex;
  382. INDEX iwwLast = _aSortArray[iLastIndex].sa_aWeightMapList[iwm].vl_iSubIndex;
  383. // if weight map factors are diferent
  384. CHECKF(pMeshLOD->mlod_aWeightMaps[iwmCurent].mwm_aVertexWeight[iwwCurent].mww_fWeight,pMeshLOD->mlod_aWeightMaps[iwmLast].mwm_aVertexWeight[iwwLast].mww_fWeight);
  385. }
  386. // check if vertices have same morph map factors
  387. for(INDEX imm=0;imm<ctmmCurent;imm++)
  388. {
  389. // get morph map indices
  390. INDEX immCurent = _aSortArray[iCurentIndex].sa_aMorphMapList[imm].vl_iIndex;
  391. INDEX immLast = _aSortArray[iLastIndex].sa_aMorphMapList[imm].vl_iIndex;
  392. // get mesh vertex morph indices
  393. INDEX imwmCurent = _aSortArray[iCurentIndex].sa_aMorphMapList[imm].vl_iSubIndex;
  394. INDEX imwmLast = _aSortArray[iLastIndex].sa_aMorphMapList[imm].vl_iSubIndex;
  395. // if mesh morph map params are diferent return
  396. CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_x,
  397. pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_x);
  398. CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_y,
  399. pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_y);
  400. CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_z,
  401. pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_z);
  402. CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_nx,
  403. pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_nx);
  404. CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_ny,
  405. pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_ny);
  406. CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_nz,
  407. pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_nz);
  408. }
  409. return 0;
  410. }
  411. // normalize weights in mlod
  412. void CMesh::NormalizeWeightsInLod(MeshLOD &mlod)
  413. {
  414. CStaticArray<float> aWeightFactors;
  415. int ctvtx = mlod.mlod_aVertices.Count();
  416. int ctwm = mlod.mlod_aWeightMaps.Count();
  417. // create array for weights
  418. aWeightFactors.New(ctvtx);
  419. memset(&aWeightFactors[0],0,sizeof(aWeightFactors[0])*ctvtx);
  420. int iwm=0;
  421. for(;iwm<ctwm;iwm++)
  422. {
  423. MeshWeightMap &mwm = mlod.mlod_aWeightMaps[iwm];
  424. for(int iww=0;iww<mwm.mwm_aVertexWeight.Count();iww++)
  425. {
  426. MeshVertexWeight &mwh = mwm.mwm_aVertexWeight[iww];
  427. aWeightFactors[mwh.mww_iVertex] += mwh.mww_fWeight;
  428. }
  429. }
  430. for(iwm=0;iwm<ctwm;iwm++)
  431. {
  432. MeshWeightMap &mwm = mlod.mlod_aWeightMaps[iwm];
  433. for(int iww=0;iww<mwm.mwm_aVertexWeight.Count();iww++)
  434. {
  435. MeshVertexWeight &mwh = mwm.mwm_aVertexWeight[iww];
  436. mwh.mww_fWeight /= aWeightFactors[mwh.mww_iVertex];
  437. }
  438. }
  439. // clear weight array
  440. aWeightFactors.Clear();
  441. }
  442. // normalize weights in mesh
  443. void CMesh::NormalizeWeights()
  444. {
  445. INDEX ctmlods = msh_aMeshLODs.Count();
  446. for(INDEX imlod=0;imlod<ctmlods;imlod++)
  447. {
  448. // normalize each lod
  449. NormalizeWeightsInLod(msh_aMeshLODs[imlod]);
  450. }
  451. }
  452. // add new mesh lod to mesh
  453. void CMesh::AddMeshLod(MeshLOD &mlod)
  454. {
  455. INDEX ctmlods = msh_aMeshLODs.Count();
  456. msh_aMeshLODs.Expand(ctmlods+1);
  457. msh_aMeshLODs[ctmlods] = mlod;
  458. }
  459. // remove mesh lod from mesh
  460. void CMesh::RemoveMeshLod(MeshLOD *pmlodRemove)
  461. {
  462. INDEX ctmlod = msh_aMeshLODs.Count();
  463. // create temp space for skeleton lods
  464. CStaticArray<struct MeshLOD> aTempMLODs;
  465. aTempMLODs.New(ctmlod-1);
  466. INDEX iIndexSrc=0;
  467. // for each skeleton lod in skeleton
  468. for(INDEX imlod=0;imlod<ctmlod;imlod++)
  469. {
  470. MeshLOD *pmlod = &msh_aMeshLODs[imlod];
  471. // copy all skeleton lods except the selected one
  472. if(pmlod != pmlodRemove)
  473. {
  474. aTempMLODs[iIndexSrc] = *pmlod;
  475. iIndexSrc++;
  476. }
  477. }
  478. // copy temp array of skeleton lods back in skeleton
  479. msh_aMeshLODs.CopyArray(aTempMLODs);
  480. // clear temp skleletons lods array
  481. aTempMLODs.Clear();
  482. }
  483. // write to stream
  484. void CMesh::Write_t(CTStream *ostrFile)
  485. {
  486. INDEX ctmlods = msh_aMeshLODs.Count();
  487. // write id
  488. ostrFile->WriteID_t(CChunkID(MESH_ID));
  489. // write version
  490. (*ostrFile)<<(INDEX)MESH_VERSION;
  491. // write mlod count
  492. (*ostrFile)<<ctmlods;
  493. // for each lod in mesh
  494. for(INDEX imlod=0;imlod<ctmlods;imlod++) {
  495. MeshLOD &mLod = msh_aMeshLODs[imlod];
  496. INDEX ctVx = mLod.mlod_aVertices.Count(); // vertex count
  497. INDEX ctUV = mLod.mlod_aUVMaps.Count(); // uvmaps count
  498. INDEX ctSf = mLod.mlod_aSurfaces.Count(); // surfaces count
  499. INDEX ctWM = mLod.mlod_aWeightMaps.Count(); // weight maps count
  500. INDEX ctMM = mLod.mlod_aMorphMaps.Count(); // morph maps count
  501. // write source file name
  502. (*ostrFile)<<mLod.mlod_fnSourceFile;
  503. // write max distance
  504. (*ostrFile)<<mLod.mlod_fMaxDistance;
  505. // write flags
  506. (*ostrFile)<<mLod.mlod_ulFlags;
  507. // write wertex count
  508. (*ostrFile)<<ctVx;
  509. // write wertices
  510. ostrFile->Write_t(&mLod.mlod_aVertices[0],sizeof(MeshVertex)*ctVx);
  511. // write normals
  512. ostrFile->Write_t(&mLod.mlod_aNormals[0],sizeof(MeshNormal)*ctVx);
  513. // write uvmaps count
  514. (*ostrFile)<<ctUV;
  515. // write uvmaps
  516. for(int iuv=0;iuv<ctUV;iuv++) {
  517. // write uvmap ID
  518. CTString strNameID = ska_GetStringFromTable(mLod.mlod_aUVMaps[iuv].muv_iID);
  519. (*ostrFile)<<strNameID;
  520. // write uvmaps texcordinates
  521. ostrFile->Write_t(&mLod.mlod_aUVMaps[iuv].muv_aTexCoords[0],sizeof(MeshTexCoord)*ctVx);
  522. }
  523. // write surfaces count
  524. ostrFile->Write_t(&ctSf,sizeof(INDEX));
  525. // write surfaces
  526. for(INDEX isf=0;isf<ctSf;isf++) {
  527. MeshSurface &msrf = mLod.mlod_aSurfaces[isf];
  528. INDEX ctTris = msrf.msrf_aTriangles.Count();
  529. CTString strSurfaceID = ska_GetStringFromTable(msrf.msrf_iSurfaceID);
  530. // write surface ID
  531. (*ostrFile)<<strSurfaceID;
  532. // write first vertex
  533. (*ostrFile)<<msrf.msrf_iFirstVertex;
  534. // write vertices count
  535. (*ostrFile)<<msrf.msrf_ctVertices;
  536. // write tris count
  537. (*ostrFile)<<ctTris;
  538. // write triangles
  539. ostrFile->Write_t(&mLod.mlod_aSurfaces[isf].msrf_aTriangles[0],sizeof(MeshTriangle)*ctTris);
  540. // write bool that this surface has a shader
  541. INDEX bShaderExists = (msrf.msrf_pShader!=NULL);
  542. (*ostrFile)<<bShaderExists;
  543. if(bShaderExists) {
  544. // get shader decription
  545. ShaderDesc shDesc;
  546. msrf.msrf_pShader->GetShaderDesc(shDesc);
  547. INDEX cttx=shDesc.sd_astrTextureNames.Count();
  548. INDEX cttc=shDesc.sd_astrTexCoordNames.Count();
  549. INDEX ctcol=shDesc.sd_astrColorNames.Count();
  550. INDEX ctfl=shDesc.sd_astrFloatNames.Count();
  551. // data count must be at same as size defined in shader or higher
  552. ASSERT(cttx<=msrf.msrf_ShadingParams.sp_aiTextureIDs.Count());
  553. ASSERT(cttc<=msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count());
  554. ASSERT(ctcol<=msrf.msrf_ShadingParams.sp_acolColors.Count());
  555. ASSERT(ctfl<=msrf.msrf_ShadingParams.sp_afFloats.Count());
  556. ASSERT(msrf.msrf_pShader->GetShaderDesc!=NULL);
  557. // write texture count
  558. (*ostrFile)<<cttx;
  559. // write texture coords count
  560. (*ostrFile)<<cttc;
  561. // write color count
  562. (*ostrFile)<<ctcol;
  563. // write float count
  564. (*ostrFile)<<ctfl;
  565. ASSERT(msrf.msrf_pShader!=NULL);
  566. // write shader name
  567. CTString strShaderName;
  568. strShaderName = msrf.msrf_pShader->GetName();
  569. (*ostrFile)<<strShaderName;
  570. // write shader texture IDs
  571. for(INDEX itx=0;itx<cttx;itx++)
  572. {
  573. INDEX iTexID = msrf.msrf_ShadingParams.sp_aiTextureIDs[itx];
  574. (*ostrFile)<<ska_GetStringFromTable(iTexID);
  575. }
  576. // write shader texture coords indices
  577. for(INDEX itc=0;itc<cttc;itc++)
  578. {
  579. INDEX iTexCoorsIndex = msrf.msrf_ShadingParams.sp_aiTexCoordsIndex[itc];
  580. (*ostrFile)<<iTexCoorsIndex;
  581. }
  582. // write shader colors
  583. for(INDEX icol=0;icol<ctcol;icol++)
  584. {
  585. COLOR colColor = msrf.msrf_ShadingParams.sp_acolColors[icol];
  586. (*ostrFile)<<colColor;
  587. }
  588. // write shader floats
  589. for(INDEX ifl=0;ifl<ctfl;ifl++)
  590. {
  591. FLOAT fFloat = msrf.msrf_ShadingParams.sp_afFloats[ifl];
  592. (*ostrFile)<<fFloat;
  593. }
  594. // write shader flags
  595. ULONG ulFlags = msrf.msrf_ShadingParams.sp_ulFlags;
  596. (*ostrFile)<<ulFlags;
  597. }
  598. }
  599. // write weightmaps count
  600. (*ostrFile)<<ctWM;
  601. // for each weightmap in array
  602. for(INDEX iwm=0;iwm<ctWM;iwm++)
  603. {
  604. INDEX ctWw = mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight.Count();
  605. // write wertex weight map ID
  606. CTString pstrNameID = ska_GetStringFromTable(mLod.mlod_aWeightMaps[iwm].mwm_iID);
  607. (*ostrFile)<<pstrNameID;
  608. // write wertex weights count
  609. (*ostrFile)<<ctWw;
  610. // write wertex weights
  611. ostrFile->Write_t(&mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight[0],sizeof(MeshVertexWeight)*ctWw);
  612. }
  613. // write morphmaps count
  614. (*ostrFile)<<ctMM;
  615. for(INDEX imm=0;imm<ctMM;imm++)
  616. {
  617. INDEX ctms = mLod.mlod_aMorphMaps[imm].mmp_aMorphMap.Count();
  618. // write ID
  619. CTString pstrNameID = ska_GetStringFromTable(mLod.mlod_aMorphMaps[imm].mmp_iID);
  620. (*ostrFile)<<pstrNameID;
  621. // write bRelative
  622. (*ostrFile)<<mLod.mlod_aMorphMaps[imm].mmp_bRelative;
  623. //ostrFile->Write_t(&mLod.mlod_aMorphMaps[imm].mmp_bRelative,sizeof(BOOL));
  624. // write morph sets count
  625. ostrFile->Write_t(&ctms,sizeof(INDEX));
  626. // write morph sets
  627. ostrFile->Write_t(&mLod.mlod_aMorphMaps[imm].mmp_aMorphMap[0],sizeof(MeshVertexMorph)*ctms);
  628. }
  629. }
  630. }
  631. //read from stream
  632. void CMesh::Read_t(CTStream *istrFile)
  633. {
  634. INDEX ctmlods;
  635. INDEX iFileVersion;
  636. // read chunk id
  637. istrFile->ExpectID_t(CChunkID(MESH_ID));
  638. // check file version
  639. (*istrFile)>>iFileVersion;
  640. // if file version is not 11 nor 12
  641. if(iFileVersion != 11 && iFileVersion!=12) {
  642. ThrowF_t(TRANS("File '%s'.\nInvalid Mesh file version.\nExpected Ver \"%d\" but found \"%d\"\n"),
  643. (const char*)istrFile->GetDescription(),MESH_VERSION,iFileVersion);
  644. return;
  645. }
  646. // read mlod count
  647. (*istrFile)>>ctmlods;
  648. // for each lod in mesh
  649. for(INDEX imlod=0;imlod<ctmlods;imlod++) {
  650. // expand mlod count for one
  651. INDEX ctMeshLODs = msh_aMeshLODs.Count();
  652. msh_aMeshLODs.Expand(ctMeshLODs+1);
  653. MeshLOD &mLod = msh_aMeshLODs[ctMeshLODs];
  654. INDEX ctVx; // vertex count
  655. INDEX ctUV; // uvmaps count
  656. INDEX ctSf; // surfaces count
  657. INDEX ctWM; // weight maps count
  658. INDEX ctMM; // morph maps count
  659. // read source file name
  660. (*istrFile)>>mLod.mlod_fnSourceFile;
  661. // read max distance
  662. (*istrFile)>>mLod.mlod_fMaxDistance;
  663. // read flags
  664. (*istrFile)>>mLod.mlod_ulFlags;
  665. // :)
  666. if(iFileVersion<=11) {
  667. mLod.mlod_ulFlags = 0;
  668. }
  669. if(mLod.mlod_ulFlags==0xCDCDCDCD) {
  670. mLod.mlod_ulFlags = 0;
  671. }
  672. // read vertex count
  673. (*istrFile)>>ctVx;
  674. // create vertex and normal arrays
  675. mLod.mlod_aVertices.New(ctVx);
  676. mLod.mlod_aNormals.New(ctVx);
  677. // read wertices
  678. istrFile->Read_t(&mLod.mlod_aVertices[0],sizeof(MeshVertex)*ctVx);
  679. // read normals
  680. istrFile->Read_t(&mLod.mlod_aNormals[0],sizeof(MeshNormal)*ctVx);
  681. // read uvmaps count
  682. (*istrFile)>>ctUV;
  683. // create array for uvmaps
  684. mLod.mlod_aUVMaps.New(ctUV);
  685. // read uvmaps
  686. for(int iuv=0;iuv<ctUV;iuv++) {
  687. // read uvmap ID
  688. CTString strNameID;
  689. (*istrFile)>>strNameID;
  690. mLod.mlod_aUVMaps[iuv].muv_iID = ska_GetIDFromStringTable(strNameID);
  691. // create array for uvmaps texcordinates
  692. mLod.mlod_aUVMaps[iuv].muv_aTexCoords.New(ctVx);
  693. // read uvmap texcordinates
  694. istrFile->Read_t(&mLod.mlod_aUVMaps[iuv].muv_aTexCoords[0],sizeof(MeshTexCoord)*ctVx);
  695. }
  696. // read surfaces count
  697. (*istrFile)>>ctSf;
  698. // create array for surfaces
  699. mLod.mlod_aSurfaces.New(ctSf);
  700. // read surfaces
  701. for(INDEX isf=0;isf<ctSf;isf++) {
  702. INDEX ctTris;
  703. MeshSurface &msrf = mLod.mlod_aSurfaces[isf];
  704. // read surface ID
  705. CTString strSurfaceID;
  706. (*istrFile)>>strSurfaceID;
  707. msrf.msrf_iSurfaceID = ska_GetIDFromStringTable(strSurfaceID);
  708. // read first vertex
  709. (*istrFile)>>msrf.msrf_iFirstVertex;
  710. // read vertices count
  711. (*istrFile)>>msrf.msrf_ctVertices;
  712. // read tris count
  713. (*istrFile)>>ctTris;
  714. // create triangles array
  715. mLod.mlod_aSurfaces[isf].msrf_aTriangles.New(ctTris);
  716. // read triangles
  717. istrFile->Read_t(&mLod.mlod_aSurfaces[isf].msrf_aTriangles[0],sizeof(MeshTriangle)*ctTris);
  718. // read bool that this surface has a shader
  719. INDEX bShaderExists;
  720. (*istrFile)>>bShaderExists;
  721. // if shader exists read its params
  722. if(bShaderExists) {
  723. INDEX cttx,cttc,ctcol,ctfl;
  724. // read texture count
  725. (*istrFile)>>cttx;
  726. // read texture coords count
  727. (*istrFile)>>cttc;
  728. // read color count
  729. (*istrFile)>>ctcol;
  730. // read float count
  731. (*istrFile)>>ctfl;
  732. CShader *pshMeshShader = NULL;
  733. ShaderParams *pshpShaderParams = NULL;
  734. CShader shDummyShader; // dummy shader if shader is not found
  735. ShaderParams shpDummyShaderParams;// dummy shader params if shader is not found
  736. // read shader name
  737. CTString strShaderName;
  738. (*istrFile)>>strShaderName;
  739. // try to load shader
  740. try{
  741. msrf.msrf_pShader = _pShaderStock->Obtain_t(strShaderName);
  742. pshMeshShader = msrf.msrf_pShader;
  743. pshpShaderParams = &msrf.msrf_ShadingParams;
  744. } catch(char *strErr) {
  745. CPrintF("%s\n",strErr);
  746. msrf.msrf_pShader = NULL;
  747. pshMeshShader = &shDummyShader;
  748. pshpShaderParams = &shpDummyShaderParams;
  749. }
  750. // if mesh shader exisits
  751. if(msrf.msrf_pShader!=NULL) {
  752. // get shader description
  753. ShaderDesc shDesc;
  754. msrf.msrf_pShader->GetShaderDesc(shDesc);
  755. // check if saved params count match shader params count
  756. if(shDesc.sd_astrTextureNames.Count() != cttx) ThrowF_t("File '%s'\nWrong texture count %d",(const char*)GetName(),cttx);
  757. if(shDesc.sd_astrTexCoordNames.Count() != cttc) ThrowF_t("File '%s'\nWrong uvmaps count %d",(const char*)GetName(),cttc);
  758. if(shDesc.sd_astrColorNames.Count() != ctcol) ThrowF_t("File '%s'\nWrong colors count %d",(const char*)GetName(),ctcol);
  759. if(shDesc.sd_astrFloatNames.Count() != ctfl) ThrowF_t("File '%s'\nWrong floats count %d",(const char*)GetName(),ctfl);
  760. }
  761. // create arrays for shader params
  762. pshpShaderParams->sp_aiTextureIDs.New(cttx);
  763. pshpShaderParams->sp_aiTexCoordsIndex.New(cttc);
  764. pshpShaderParams->sp_acolColors.New(ctcol);
  765. pshpShaderParams->sp_afFloats.New(ctfl);
  766. // read shader texture IDs
  767. for(INDEX itx=0;itx<cttx;itx++) {
  768. CTString strTexID;
  769. (*istrFile)>>strTexID;
  770. INDEX iTexID = ska_GetIDFromStringTable(strTexID);
  771. pshpShaderParams->sp_aiTextureIDs[itx] = iTexID;
  772. }
  773. // read shader texture coords indices
  774. for(INDEX itc=0;itc<cttc;itc++) {
  775. INDEX iTexCoorsIndex;
  776. (*istrFile)>>iTexCoorsIndex;
  777. pshpShaderParams->sp_aiTexCoordsIndex[itc] = iTexCoorsIndex;
  778. }
  779. // read shader colors
  780. for(INDEX icol=0;icol<ctcol;icol++) {
  781. COLOR colColor;
  782. (*istrFile)>>colColor;
  783. pshpShaderParams->sp_acolColors[icol] = colColor;
  784. }
  785. // read shader floats
  786. for(INDEX ifl=0;ifl<ctfl;ifl++) {
  787. FLOAT fFloat;
  788. (*istrFile)>>fFloat;
  789. pshpShaderParams->sp_afFloats[ifl] = fFloat;
  790. }
  791. // there were no flags in shader before ver 12
  792. if(iFileVersion>11) {
  793. ULONG ulFlags;
  794. (*istrFile)>>ulFlags;
  795. pshpShaderParams->sp_ulFlags = ulFlags;
  796. } else {
  797. pshpShaderParams->sp_ulFlags = 0;
  798. }
  799. } else {
  800. // this surface does not have shader
  801. msrf.msrf_pShader=NULL;
  802. }
  803. }
  804. // read weightmaps count
  805. (*istrFile)>>ctWM;
  806. // create weightmap array
  807. mLod.mlod_aWeightMaps.New(ctWM);
  808. // read each weightmap
  809. for(INDEX iwm=0;iwm<ctWM;iwm++) {
  810. // read weightmap ID
  811. CTString pstrNameID;
  812. (*istrFile)>>pstrNameID;
  813. mLod.mlod_aWeightMaps[iwm].mwm_iID = ska_GetIDFromStringTable(pstrNameID);
  814. // read wertex weight count
  815. INDEX ctWw;
  816. (*istrFile)>>ctWw;
  817. // create wertex weight array
  818. mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight.New(ctWw);
  819. // read wertex weights
  820. istrFile->Read_t(&mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight[0],sizeof(MeshVertexWeight)*ctWw);
  821. }
  822. // read morphmap count
  823. (*istrFile)>>ctMM;
  824. // create morphmaps array
  825. mLod.mlod_aMorphMaps.New(ctMM);
  826. // read morphmaps
  827. for(INDEX imm=0;imm<ctMM;imm++) {
  828. // read morphmap ID
  829. CTString pstrNameID;
  830. (*istrFile)>>pstrNameID;
  831. mLod.mlod_aMorphMaps[imm].mmp_iID = ska_GetIDFromStringTable(pstrNameID);
  832. // read bRelative
  833. (*istrFile)>>mLod.mlod_aMorphMaps[imm].mmp_bRelative;
  834. // read morph sets count
  835. INDEX ctms;
  836. (*istrFile)>>ctms;
  837. // create morps sets array
  838. mLod.mlod_aMorphMaps[imm].mmp_aMorphMap.New(ctms);
  839. // read morph sets
  840. istrFile->Read_t(&mLod.mlod_aMorphMaps[imm].mmp_aMorphMap[0],sizeof(MeshVertexMorph)*ctms);
  841. }
  842. }
  843. }
  844. // clear mesh
  845. void CMesh::Clear(void)
  846. {
  847. // for each LOD
  848. INDEX ctmlod = msh_aMeshLODs.Count();
  849. for (INDEX imlod=0; imlod<ctmlod; imlod++)
  850. {
  851. // for each surface, clear the triangles list
  852. MeshLOD &mlod = msh_aMeshLODs[imlod];
  853. INDEX ctsrf = mlod.mlod_aSurfaces.Count();
  854. for (INDEX isrf=0;isrf<ctsrf;isrf++)
  855. {
  856. MeshSurface &msrf = mlod.mlod_aSurfaces[isrf];
  857. msrf.msrf_aTriangles.Clear();
  858. // release shader form stock
  859. if(msrf.msrf_pShader!=NULL) _pShaderStock->Release(msrf.msrf_pShader);
  860. msrf.msrf_pShader = NULL;
  861. }
  862. // clear the surfaces array
  863. mlod.mlod_aSurfaces.Clear();
  864. // for each uvmap, clear the texcord list
  865. INDEX ctuvm = mlod.mlod_aUVMaps.Count();
  866. for (INDEX iuvm=0;iuvm<ctuvm;iuvm++)
  867. {
  868. mlod.mlod_aUVMaps[iuvm].muv_aTexCoords.Clear();
  869. }
  870. // clear the uvmaps array
  871. mlod.mlod_aUVMaps.Clear();
  872. // clear the vertices array
  873. mlod.mlod_aVertices.Clear();
  874. // clear the normals array
  875. mlod.mlod_aNormals.Clear();
  876. }
  877. // in the end, clear all LODs
  878. msh_aMeshLODs.Clear();
  879. }
  880. // Count used memory
  881. SLONG CMesh::GetUsedMemory(void)
  882. {
  883. SLONG slMemoryUsed = sizeof(*this);
  884. INDEX ctmlods = msh_aMeshLODs.Count();
  885. for(INDEX imlod=0;imlod<ctmlods;imlod++) {
  886. MeshLOD &mlod = msh_aMeshLODs[imlod];
  887. slMemoryUsed+=sizeof(mlod);
  888. slMemoryUsed+=mlod.mlod_aVertices.Count() * sizeof(MeshVertex);
  889. slMemoryUsed+=mlod.mlod_aNormals.Count() * sizeof(MeshNormal);
  890. // for each uvmap
  891. INDEX ctuvmaps = mlod.mlod_aUVMaps.Count();
  892. for(INDEX iuvm=0;iuvm<ctuvmaps;iuvm++) {
  893. MeshUVMap &uvmap = mlod.mlod_aUVMaps[iuvm];
  894. slMemoryUsed+=sizeof(uvmap);
  895. slMemoryUsed+=uvmap.muv_aTexCoords.Count() * sizeof(MeshTexCoord);
  896. }
  897. // for each surface
  898. INDEX ctmsrf = mlod.mlod_aSurfaces.Count();
  899. for(INDEX imsrf=0;imsrf<ctmsrf;imsrf++) {
  900. MeshSurface &msrf = mlod.mlod_aSurfaces[imsrf];
  901. slMemoryUsed+=sizeof(msrf);
  902. slMemoryUsed+=msrf.msrf_aTriangles.Count() * sizeof(MeshTriangle);
  903. slMemoryUsed+=sizeof(ShaderParams);
  904. slMemoryUsed+=sizeof(INDEX) * msrf.msrf_ShadingParams.sp_aiTextureIDs.Count();
  905. slMemoryUsed+=sizeof(INDEX) * msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count();
  906. slMemoryUsed+=sizeof(COLOR) * msrf.msrf_ShadingParams.sp_acolColors.Count();
  907. slMemoryUsed+=sizeof(FLOAT) * msrf.msrf_ShadingParams.sp_afFloats.Count();
  908. }
  909. // for each weight map
  910. INDEX ctwm = mlod.mlod_aWeightMaps.Count();
  911. for(INDEX iwm=0;iwm<ctwm;iwm++) {
  912. MeshWeightMap &mwm = mlod.mlod_aWeightMaps[iwm];
  913. slMemoryUsed+=sizeof(mwm);
  914. slMemoryUsed+=mwm.mwm_aVertexWeight.Count() * sizeof(MeshVertexWeight);
  915. }
  916. // for each morphmap
  917. INDEX ctmm = mlod.mlod_aMorphMaps.Count();
  918. for(INDEX imm=0;imm<ctmm;imm++) {
  919. MeshMorphMap &mmm = mlod.mlod_aMorphMaps[imm];
  920. slMemoryUsed+=sizeof(mmm);
  921. slMemoryUsed+=mmm.mmp_aMorphMap.Count() * sizeof(MeshVertexMorph);
  922. }
  923. }
  924. return slMemoryUsed;
  925. }