StatObjConstr.cpp 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. // Original file Copyright Crytek GMBH or its affiliates, used under license.
  13. #include "Cry3DEngine_precompiled.h"
  14. #include "StatObj.h"
  15. #include "IndexedMesh.h"
  16. #include "../RenderDll/Common/Shadow_Renderer.h"
  17. #include <IRenderer.h>
  18. #include <CrySizer.h>
  19. #include "ObjMan.h"
  20. #include "MatMan.h"
  21. #include "RenderMeshMerger.h"
  22. #include <CryPhysicsDeprecation.h>
  23. #define MAX_VERTICES_MERGABLE 15000
  24. #define MAX_TRIS_IN_LOD_0 512
  25. #define TRIS_IN_LOD_WARNING_RAIO (1.5f)
  26. // Minimal ratio of Lod(n-1)/Lod(n) polygons to consider LOD for sub-object merging.
  27. #define MIN_TRIS_IN_MERGED_LOD_RAIO (1.5f)
  28. DEFINE_INTRUSIVE_LINKED_LIST(CStatObj)
  29. //////////////////////////////////////////////////////////////////////////
  30. CStatObj::CStatObj()
  31. {
  32. m_pAsyncUpdateContext = 0;
  33. m_nNodeCount = 0;
  34. m_nMergedMemoryUsage = 0;
  35. m_nUsers = 0; // reference counter
  36. m_nLastDrawMainFrameId = 0;
  37. #ifdef SERVER_CHECKS
  38. m_pMesh = NULL;
  39. #endif
  40. m_nFlags = 0;
  41. #ifdef SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
  42. m_fOcclusionAmount = -1;
  43. m_pHeightmap = NULL;
  44. m_nHeightmapSize = 0;
  45. #endif
  46. m_pLODs = 0;
  47. m_lastBooleanOpScale = 1.f;
  48. m_fGeometricMeanFaceArea = 0.f;
  49. m_fLodDistance = 0.0f;
  50. Init();
  51. }
  52. //////////////////////////////////////////////////////////////////////////
  53. void CStatObj::Init()
  54. {
  55. m_pAsyncUpdateContext = 0;
  56. m_pIndexedMesh = 0;
  57. m_lockIdxMesh = 0;
  58. m_nRenderTrisCount = m_nLoadedTrisCount = m_nLoadedVertexCount = 0;
  59. m_nRenderMatIds = 0;
  60. m_fObjectRadius = 0;
  61. m_fRadiusHors = 0;
  62. m_fRadiusVert = 0;
  63. m_pParentObject = 0;
  64. m_pClonedSourceObject = 0;
  65. m_bVehicleOnlyPhysics = 0;
  66. m_bBreakableByGame = 0;
  67. m_idmatBreakable = -1;
  68. m_nLoadedLodsNum = 1;
  69. m_nMinUsableLod0 = 0;
  70. m_nMaxUsableLod0 = 0;
  71. m_nMaxUsableLod = 0;
  72. m_pLod0 = 0;
  73. m_aiVegetationRadius = -1.0f;
  74. m_phys_mass = -1.0f;
  75. m_phys_density = -1.0f;
  76. m_vBoxMin.Set(0, 0, 0);
  77. m_vBoxMax.Set(0, 0, 0);
  78. m_vVegCenter.Set(0, 0, 0);
  79. m_fGeometricMeanFaceArea = 0.f;
  80. m_fLodDistance = 0.0f;
  81. m_pRenderMesh = 0;
  82. m_bDefaultObject = false;
  83. if (m_pLODs)
  84. {
  85. for (int i = 0; i < MAX_STATOBJ_LODS_NUM; i++)
  86. {
  87. if (m_pLODs[i])
  88. {
  89. m_pLODs[i]->Init();
  90. }
  91. }
  92. }
  93. m_pReadStream = 0;
  94. m_nSubObjectMeshCount = 0;
  95. m_nRenderMeshMemoryUsage = 0;
  96. m_arrRenderMeshesPotentialMemoryUsage[0] = m_arrRenderMeshesPotentialMemoryUsage[1] = -1;
  97. m_bCanUnload = false;
  98. m_bLodsLoaded = false;
  99. m_bDefaultObject = false;
  100. m_bOpenEdgesTested = false;
  101. m_bSubObject = false;
  102. m_bSharesChildren = false;
  103. m_bHasDeformationMorphs = false;
  104. m_bTmpIndexedMesh = false;
  105. m_bMerged = false;
  106. m_bMergedLODs = false;
  107. m_bUnmergable = false;
  108. m_bLowSpecLod0Set = false;
  109. m_bHaveOcclusionProxy = false;
  110. m_bCheckGarbage = false;
  111. m_bLodsAreLoadedFromSeparateFile = false;
  112. m_bNoHitRefinement = false;
  113. m_bDontOccludeExplosions = false;
  114. m_isDeformable = false;
  115. m_isProxyTooBig = false;
  116. m_bHasStreamOnlyCGF = true;
  117. // Assign default material originally.
  118. m_pMaterial = GetMatMan()->GetDefaultMaterial();
  119. m_pLattice = 0;
  120. m_pSpines = 0;
  121. m_nSpines = 0;
  122. m_pBoneMapping = 0;
  123. m_pLastBooleanOp = 0;
  124. m_pMapFaceToFace0 = 0;
  125. m_pClothTangentsData = 0;
  126. m_pSkinInfo = 0;
  127. m_hasClothTangentsData = m_hasSkinInfo = 0;
  128. m_pDelayedSkinParams = 0;
  129. m_arrPhysGeomInfo.m_array.clear();
  130. m_nInitialSubObjHideMask = 0;
  131. #if !defined (_RELEASE)
  132. m_fStreamingStart = 0.0f;
  133. #endif
  134. }
  135. //////////////////////////////////////////////////////////////////////////
  136. CStatObj::~CStatObj()
  137. {
  138. ShutDown();
  139. }
  140. void CStatObj::ShutDown()
  141. {
  142. if (m_pReadStream)
  143. {
  144. // We don't need this stream anymore.
  145. m_pReadStream->Abort();
  146. m_pReadStream = NULL;
  147. }
  148. SAFE_DELETE(m_pAsyncUpdateContext);
  149. // assert (IsHeapValid());
  150. SAFE_DELETE(m_pIndexedMesh);
  151. // assert (IsHeapValid());
  152. for (int n = 0; n < m_arrPhysGeomInfo.GetGeomCount(); n++)
  153. {
  154. if (m_arrPhysGeomInfo[n])
  155. {
  156. if (m_arrPhysGeomInfo[n]->pGeom->GetForeignData() == (void*)this)
  157. {
  158. m_arrPhysGeomInfo[n]->pGeom->SetForeignData(0, 0);
  159. }
  160. // Unregister geometry
  161. CRY_PHYSICS_REPLACEMENT_ASSERT();
  162. }
  163. }
  164. m_arrPhysGeomInfo.m_array.clear();
  165. m_pStreamedRenderMesh = 0;
  166. m_pMergedRenderMesh = 0;
  167. SetRenderMesh(0);
  168. #ifdef SERVER_CHECKS
  169. SAFE_DELETE(m_pMesh);
  170. #endif
  171. // assert (IsHeapValid());
  172. /* // SDynTexture is not accessible for 3dengine
  173. for(int i=0; i<FAR_TEX_COUNT; i++)
  174. if(m_arrSpriteTexPtr[i])
  175. m_arrSpriteTexPtr[i]->ReleaseDynamicRT(true);
  176. for(int i=0; i<FAR_TEX_COUNT_60; i++)
  177. if(m_arrSpriteTexPtr_60[i])
  178. m_arrSpriteTexPtr_60[i]->ReleaseDynamicRT(true);
  179. */
  180. SAFE_RELEASE(m_pLattice);
  181. if (m_pLODs)
  182. {
  183. for (int i = 0; i < MAX_STATOBJ_LODS_NUM; i++)
  184. {
  185. if (m_pLODs[i])
  186. {
  187. if (m_pLODs[i]->m_pParentObject)
  188. {
  189. GetObjManager()->UnregisterForStreaming(m_pLODs[i]->m_pParentObject);
  190. }
  191. else
  192. {
  193. GetObjManager()->UnregisterForStreaming(m_pLODs[i]);
  194. }
  195. // Sub objects do not own the LODs, so they should not delete them.
  196. m_pLODs[i] = 0;
  197. }
  198. }
  199. }
  200. //////////////////////////////////////////////////////////////////////////
  201. // Handle sub-objects and parents.
  202. //////////////////////////////////////////////////////////////////////////
  203. for (size_t i = 0; i < m_subObjects.size(); i++)
  204. {
  205. CStatObj* pChildObj = (CStatObj*)m_subObjects[i].pStatObj;
  206. if (pChildObj)
  207. {
  208. if (!m_bSharesChildren)
  209. {
  210. pChildObj->m_pParentObject = NULL;
  211. }
  212. GetObjManager()->UnregisterForStreaming(pChildObj);
  213. pChildObj->Release();
  214. }
  215. }
  216. m_subObjects.clear();
  217. if (m_pParentObject && !m_pParentObject->m_subObjects.empty())
  218. {
  219. // Remove this StatObject from sub-objects of the parent.
  220. SSubObject* pSubObjects = &m_pParentObject->m_subObjects[0];
  221. for (int i = 0, num = m_pParentObject->m_subObjects.size(); i < num; i++)
  222. {
  223. if (pSubObjects[i].pStatObj == this)
  224. {
  225. m_pParentObject->m_subObjects.erase(m_pParentObject->m_subObjects.begin() + i);
  226. break;
  227. }
  228. }
  229. }
  230. //////////////////////////////////////////////////////////////////////////
  231. if (m_pMapFaceToFace0)
  232. {
  233. delete[] m_pMapFaceToFace0;
  234. }
  235. m_pMapFaceToFace0 = 0;
  236. if (m_hasClothTangentsData && !m_pClonedSourceObject)
  237. {
  238. delete[] m_pClothTangentsData;
  239. }
  240. if (m_hasSkinInfo && !m_pClonedSourceObject)
  241. {
  242. delete[] m_pSkinInfo;
  243. }
  244. m_pClothTangentsData = 0;
  245. m_hasClothTangentsData = 0;
  246. m_pSkinInfo = 0;
  247. m_hasSkinInfo = 0;
  248. SAFE_DELETE(m_pDelayedSkinParams);
  249. SAFE_RELEASE(m_pClonedSourceObject);
  250. #ifdef SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
  251. m_fOcclusionAmount = -1;
  252. SAFE_DELETE_ARRAY(m_pHeightmap);
  253. m_pHeightmap = 0;
  254. #endif
  255. GetObjManager()->UnregisterForStreaming(this);
  256. SAFE_DELETE_ARRAY(m_pLODs);
  257. }
  258. //////////////////////////////////////////////////////////////////////////
  259. int CStatObj::Release()
  260. {
  261. // Has to be thread safe, as it can be called by a worker thread for deferred plane breaks
  262. int newRef = CryInterlockedDecrement(&m_nUsers);
  263. if (newRef <= 1)
  264. {
  265. if (m_pParentObject && m_pParentObject->m_nUsers <= 0)
  266. {
  267. GetObjManager()->CheckForGarbage(m_pParentObject);
  268. }
  269. if (newRef <= 0)
  270. {
  271. GetObjManager()->CheckForGarbage(this);
  272. }
  273. }
  274. return newRef;
  275. }
  276. //////////////////////////////////////////////////////////////////////////
  277. void* CStatObj::operator new ([[maybe_unused]] size_t size)
  278. {
  279. IObjManager* pObjManager = GetObjManager();
  280. assert(size == sizeof(CStatObj));
  281. return pObjManager->AllocateStatObj();
  282. }
  283. void CStatObj::operator delete (void* pToFree)
  284. {
  285. IObjManager* pObjManager = GetObjManager();
  286. pObjManager->FreeStatObj((CStatObj*)pToFree);
  287. }
  288. //////////////////////////////////////////////////////////////////////////
  289. void CStatObj::FreeIndexedMesh()
  290. {
  291. if (!m_lockIdxMesh)
  292. {
  293. WriteLock lock(m_lockIdxMesh);
  294. delete m_pIndexedMesh;
  295. m_pIndexedMesh = 0;
  296. }
  297. }
  298. //////////////////////////////////////////////////////////////////////////
  299. void CStatObj::CalcRadiuses()
  300. {
  301. if (!m_vBoxMin.IsValid() || !m_vBoxMax.IsValid())
  302. {
  303. Error("CStatObj::CalcRadiuses: Invalid bbox, File name: %s", m_szFileName.c_str());
  304. m_vBoxMin.zero();
  305. m_vBoxMax.zero();
  306. }
  307. m_fObjectRadius = m_vBoxMin.GetDistance(m_vBoxMax) * 0.5f;
  308. float dxh = (float)max(fabs(GetBoxMax().x), fabs(GetBoxMin().x));
  309. float dyh = (float)max(fabs(GetBoxMax().y), fabs(GetBoxMin().y));
  310. m_fRadiusHors = (float)sqrt_tpl(dxh * dxh + dyh * dyh);
  311. m_fRadiusVert = (GetBoxMax().z - 0) * 0.5f;// never change this
  312. m_vVegCenter = (m_vBoxMax + m_vBoxMin) * 0.5f;
  313. m_vVegCenter.z = m_fRadiusVert;
  314. }
  315. void CStatObj::MakeRenderMesh()
  316. {
  317. if (gEnv->IsDedicated())
  318. {
  319. return;
  320. }
  321. FUNCTION_PROFILER_3DENGINE;
  322. SetRenderMesh(0);
  323. if (!m_pIndexedMesh || m_pIndexedMesh->GetSubSetCount() == 0)
  324. {
  325. return;
  326. }
  327. CMesh* pMesh = m_pIndexedMesh->GetMesh();
  328. m_nRenderTrisCount = 0;
  329. //////////////////////////////////////////////////////////////////////////
  330. // Initialize Mesh subset material flags.
  331. //////////////////////////////////////////////////////////////////////////
  332. for (int i = 0; i < pMesh->GetSubSetCount(); i++)
  333. {
  334. SMeshSubset& subset = pMesh->m_subsets[i];
  335. if (!(subset.nMatFlags & MTL_FLAG_NODRAW))
  336. {
  337. m_nRenderTrisCount += subset.nNumIndices / 3;
  338. }
  339. }
  340. //////////////////////////////////////////////////////////////////////////
  341. if (!m_nRenderTrisCount)
  342. {
  343. return;
  344. }
  345. if (!(GetFlags() & STATIC_OBJECT_DYNAMIC))
  346. {
  347. m_pRenderMesh = GetRenderer()->CreateRenderMesh("StatObj_Static", GetFilePath(), NULL, eRMT_Static);
  348. }
  349. else
  350. {
  351. m_pRenderMesh = GetRenderer()->CreateRenderMesh("StatObj_Dynamic", GetFilePath(), NULL, eRMT_Dynamic);
  352. m_pRenderMesh->KeepSysMesh(true);
  353. }
  354. SMeshBoneMapping_uint16* const pBoneMap = pMesh->m_pBoneMapping;
  355. pMesh->m_pBoneMapping = 0;
  356. uint32 nFlags = 0;
  357. nFlags |= (!GetCVars()->e_StreamCgf && Get3DEngine()->m_bInLoad) ? FSM_SETMESH_ASYNC : 0;
  358. m_pRenderMesh->SetMesh(*pMesh, 0, nFlags, false);
  359. pMesh->m_pBoneMapping = pBoneMap;
  360. }
  361. //////////////////////////////////////////////////////////////////////////
  362. void CStatObj::SetMaterial(_smart_ptr<IMaterial> pMaterial)
  363. {
  364. m_pMaterial = pMaterial;
  365. }
  366. ///////////////////////////////////////////////////////////////////////////////////////
  367. Vec3 CStatObj::GetHelperPos(const char* szHelperName)
  368. {
  369. SSubObject* pSubObj = FindSubObject(szHelperName);
  370. if (!pSubObj)
  371. {
  372. return Vec3(0, 0, 0);
  373. }
  374. return Vec3(pSubObj->tm.m03, pSubObj->tm.m13, pSubObj->tm.m23);
  375. }
  376. ///////////////////////////////////////////////////////////////////////////////////////
  377. const Matrix34& CStatObj::GetHelperTM(const char* szHelperName)
  378. {
  379. SSubObject* pSubObj = FindSubObject(szHelperName);
  380. if (!pSubObj)
  381. {
  382. static Matrix34 identity(IDENTITY);
  383. return identity;
  384. }
  385. return pSubObj->tm;
  386. }
  387. bool CStatObj::IsSameObject(const char* szFileName, const char* szGeomName)
  388. {
  389. // cmp object names
  390. if (szGeomName)
  391. {
  392. if (azstricmp(szGeomName, m_szGeomName) != 0)
  393. {
  394. return false;
  395. }
  396. }
  397. // Normalize file name
  398. char szFileNameNorm[MAX_PATH_LENGTH] = "";
  399. char* pszDest = szFileNameNorm;
  400. const char* pszSource = szFileName;
  401. while (*pszSource)
  402. {
  403. if (*pszSource == '\\')
  404. {
  405. *pszDest++ = '/';
  406. }
  407. else
  408. {
  409. *pszDest++ = *pszSource;
  410. }
  411. pszSource++;
  412. }
  413. *pszDest = 0;
  414. // cmp file names
  415. if (azstricmp(szFileNameNorm, m_szFileName) != 0)
  416. {
  417. return false;
  418. }
  419. return true;
  420. }
  421. void CStatObj::GetMemoryUsage(ICrySizer* pSizer) const
  422. {
  423. {
  424. SIZER_COMPONENT_NAME(pSizer, "Self");
  425. pSizer->AddObject(this, sizeof(*this));
  426. }
  427. {
  428. SIZER_COMPONENT_NAME(pSizer, "subObjects");
  429. pSizer->AddObject(m_subObjects);
  430. }
  431. {
  432. SIZER_COMPONENT_NAME(pSizer, "Strings");
  433. pSizer->AddObject(m_szFileName);
  434. pSizer->AddObject(m_szGeomName);
  435. pSizer->AddObject(m_szProperties);
  436. }
  437. {
  438. SIZER_COMPONENT_NAME(pSizer, "Material");
  439. pSizer->AddObject(m_pMaterial);
  440. }
  441. {
  442. SIZER_COMPONENT_NAME(pSizer, "PhysGeomInfo");
  443. pSizer->AddObject(m_arrPhysGeomInfo);
  444. }
  445. if (m_pLODs)
  446. {
  447. for (int i = 1; i < MAX_STATOBJ_LODS_NUM; i++)
  448. {
  449. SIZER_COMPONENT_NAME(pSizer, "StatObjLods");
  450. pSizer->AddObject(m_pLODs[i]);
  451. }
  452. }
  453. if (m_pIndexedMesh)
  454. {
  455. SIZER_COMPONENT_NAME(pSizer, "Mesh");
  456. pSizer->AddObject(m_pIndexedMesh);
  457. }
  458. int nVtx = 0;
  459. if (m_pIndexedMesh)
  460. {
  461. nVtx = m_pIndexedMesh->GetVertexCount();
  462. }
  463. else if (m_pRenderMesh)
  464. {
  465. nVtx = m_pRenderMesh->GetVerticesCount();
  466. }
  467. if (m_pSpines)
  468. {
  469. SIZER_COMPONENT_NAME(pSizer, "StatObj Foliage Data");
  470. pSizer->AddObject(m_pSpines, sizeof(m_pSpines[0]), m_nSpines);
  471. if (m_pBoneMapping)
  472. {
  473. pSizer->AddObject(m_pBoneMapping, sizeof(m_pBoneMapping[0]), nVtx);
  474. }
  475. for (int i = 0; i < m_nSpines; i++)
  476. {
  477. pSizer->AddObject(m_pSpines[i].pVtx, sizeof(Vec3) * 2 + sizeof(Vec4), m_pSpines[i].nVtx);
  478. }
  479. }
  480. if (m_hasClothTangentsData && (!m_pClonedSourceObject || m_pClonedSourceObject == this))
  481. {
  482. SIZER_COMPONENT_NAME(pSizer, "Deformable StatObj ClothTangents");
  483. pSizer->AddObject(m_pClothTangentsData, nVtx * sizeof(m_pClothTangentsData[0]));
  484. }
  485. if (m_hasSkinInfo && (!m_pClonedSourceObject || m_pClonedSourceObject == this))
  486. {
  487. SIZER_COMPONENT_NAME(pSizer, "Deformable StatObj SkinData");
  488. pSizer->AddObject(m_pSkinInfo, (nVtx + 1) * sizeof(m_pSkinInfo[0]));
  489. }
  490. if (m_pMapFaceToFace0)
  491. {
  492. SIZER_COMPONENT_NAME(pSizer, "Deformable StatObj Mesh");
  493. pSizer->AddObject(m_pMapFaceToFace0, sizeof(m_pMapFaceToFace0[0]) * max(m_nLoadedTrisCount, m_nRenderTrisCount));
  494. }
  495. }
  496. //////////////////////////////////////////////////////////////////////////
  497. void CStatObj::SetLodObject(int nLod, IStatObj* pLod)
  498. {
  499. assert(nLod > 0 && nLod < MAX_STATOBJ_LODS_NUM);
  500. if (nLod <= 0 || nLod >= MAX_STATOBJ_LODS_NUM)
  501. {
  502. return;
  503. }
  504. if (strstr(m_szProperties, "lowspeclod0"))
  505. {
  506. m_bLowSpecLod0Set = true;
  507. }
  508. bool bLodCompound = pLod && (pLod->GetFlags() & STATIC_OBJECT_COMPOUND) != 0;
  509. if (pLod && !bLodCompound)
  510. {
  511. // Check if low lod decrease amount of used materials.
  512. int nPrevLodMatIds = m_nRenderMatIds;
  513. int nPrevLodTris = m_nLoadedTrisCount;
  514. if (nLod > 1 && m_pLODs && m_pLODs[nLod - 1])
  515. {
  516. nPrevLodMatIds = m_pLODs[nLod - 1]->m_nRenderMatIds;
  517. nPrevLodTris = m_pLODs[nLod - 1]->m_nLoadedTrisCount;
  518. }
  519. if (GetCVars()->e_LodsForceUse)
  520. {
  521. if ((int)m_nMaxUsableLod < nLod)
  522. {
  523. m_nMaxUsableLod = nLod;
  524. }
  525. }
  526. else
  527. {
  528. int min_tris = GetCVars()->e_LodMinTtris;
  529. if (((pLod->GetLoadedTrisCount() >= min_tris || nPrevLodTris >= (3 * min_tris) / 2)
  530. || pLod->GetRenderMatIds() < nPrevLodMatIds) && nLod > (int)m_nMaxUsableLod)
  531. {
  532. m_nMaxUsableLod = nLod;
  533. }
  534. }
  535. if (m_pParentObject && (m_pParentObject->m_nMaxUsableLod < m_nMaxUsableLod))
  536. {
  537. m_pParentObject->m_nMaxUsableLod = m_nMaxUsableLod;
  538. }
  539. pLod->SetLodLevel0(this);
  540. pLod->SetMaterial(m_pMaterial); // Lod must use same material as parent.
  541. if (pLod->GetLoadedTrisCount() > MAX_TRIS_IN_LOD_0)
  542. {
  543. if ((strstr(pLod->GetProperties(), "lowspeclod0") != 0) && !m_bLowSpecLod0Set)
  544. {
  545. m_bLowSpecLod0Set = true;
  546. m_nMaxUsableLod0 = nLod;
  547. }
  548. if (!m_bLowSpecLod0Set)
  549. {
  550. m_nMaxUsableLod0 = nLod;
  551. }
  552. }
  553. if (nLod + 1 > (int)m_nLoadedLodsNum)
  554. {
  555. m_nLoadedLodsNum = nLod + 1;
  556. }
  557. // When assigning lod to child object.
  558. if (m_pParentObject)
  559. {
  560. if (nLod + 1 > (int)m_pParentObject->m_nLoadedLodsNum)
  561. {
  562. m_pParentObject->m_nLoadedLodsNum = nLod + 1;
  563. }
  564. }
  565. }
  566. if (pLod && bLodCompound)
  567. {
  568. m_nMaxUsableLod = nLod;
  569. pLod->SetUnmergable(m_bUnmergable);
  570. }
  571. if (!m_pLODs && pLod)
  572. {
  573. m_pLODs = new _smart_ptr<CStatObj>[MAX_STATOBJ_LODS_NUM];
  574. }
  575. if (m_pLODs)
  576. {
  577. m_pLODs[nLod] = (CStatObj*)pLod;
  578. }
  579. }
  580. //////////////////////////////////////////////////////////////////////////
  581. IStatObj* CStatObj::GetLodObject(int nLodLevel, bool bReturnNearest)
  582. {
  583. if (nLodLevel < 1)
  584. {
  585. return this;
  586. }
  587. if (!m_pLODs)
  588. {
  589. if (bReturnNearest || nLodLevel == 0)
  590. {
  591. return this;
  592. }
  593. else
  594. {
  595. return NULL;
  596. }
  597. }
  598. if (bReturnNearest)
  599. {
  600. nLodLevel = CLAMP(nLodLevel, 0, MAX_STATOBJ_LODS_NUM - 1);
  601. }
  602. CStatObj* pLod = 0;
  603. if (nLodLevel < MAX_STATOBJ_LODS_NUM)
  604. {
  605. pLod = m_pLODs[nLodLevel];
  606. // Look up
  607. if (bReturnNearest && !pLod)
  608. {
  609. // Find highest existing lod looking up.
  610. int lod = nLodLevel;
  611. while (lod > 0 && m_pLODs[lod] == 0)
  612. {
  613. lod--;
  614. }
  615. if (lod > 0)
  616. {
  617. pLod = m_pLODs[lod];
  618. }
  619. else
  620. {
  621. pLod = this;
  622. }
  623. }
  624. // Look down
  625. if (bReturnNearest && !pLod)
  626. {
  627. // Find highest existing lod looking down.
  628. for (int lod = nLodLevel + 1; lod < MAX_STATOBJ_LODS_NUM; lod++)
  629. {
  630. if (m_pLODs[lod])
  631. {
  632. pLod = m_pLODs[lod];
  633. break;
  634. }
  635. }
  636. }
  637. }
  638. return pLod;
  639. }
  640. bool CStatObj::IsPhysicsExist()
  641. {
  642. return m_arrPhysGeomInfo.GetGeomCount() > 0;
  643. }
  644. bool CStatObj::IsSphereOverlap(const Sphere& sSphere)
  645. {
  646. if (m_pRenderMesh && Overlap::Sphere_AABB(sSphere, AABB(m_vBoxMin, m_vBoxMax)))
  647. { // if inside bbox
  648. int nPosStride = 0;
  649. int nInds = m_pRenderMesh->GetIndicesCount();
  650. const byte* pPos = m_pRenderMesh->GetPosPtr(nPosStride, FSL_READ);
  651. vtx_idx* pInds = m_pRenderMesh->GetIndexPtr(FSL_READ);
  652. if (pInds && pPos)
  653. {
  654. for (int i = 0; (i + 2) < nInds; i += 3)
  655. { // test all triangles of water surface strip
  656. Vec3 v0 = (*(Vec3*)&pPos[nPosStride * pInds[i + 0]]);
  657. Vec3 v1 = (*(Vec3*)&pPos[nPosStride * pInds[i + 1]]);
  658. Vec3 v2 = (*(Vec3*)&pPos[nPosStride * pInds[i + 2]]);
  659. Vec3 vBoxMin = v0;
  660. vBoxMin.CheckMin(v1);
  661. vBoxMin.CheckMin(v2);
  662. Vec3 vBoxMax = v0;
  663. vBoxMax.CheckMax(v1);
  664. vBoxMax.CheckMax(v2);
  665. if (Overlap::Sphere_AABB(sSphere, AABB(vBoxMin, vBoxMax)))
  666. {
  667. return true;
  668. }
  669. }
  670. }
  671. }
  672. return false;
  673. }
  674. //////////////////////////////////////////////////////////////////////////
  675. void CStatObj::Invalidate(bool bPhysics, float tolerance)
  676. {
  677. AZ_UNUSED(bPhysics);
  678. AZ_UNUSED(tolerance);
  679. if (m_pIndexedMesh)
  680. {
  681. if (m_pIndexedMesh->GetIndexCount() > 0)
  682. {
  683. m_pIndexedMesh->CalcBBox();
  684. m_vBoxMin = m_pIndexedMesh->m_bbox.min;
  685. m_vBoxMax = m_pIndexedMesh->m_bbox.max;
  686. MakeRenderMesh();
  687. m_nLoadedVertexCount = m_pIndexedMesh->GetVertexCount();
  688. m_nLoadedTrisCount = m_pIndexedMesh->GetFaceCount();
  689. if (!m_nLoadedTrisCount)
  690. {
  691. m_nLoadedTrisCount = m_pIndexedMesh->GetIndexCount() / 3;
  692. }
  693. CalcRadiuses();
  694. }
  695. ReleaseIndexedMesh(true);
  696. }
  697. //////////////////////////////////////////////////////////////////////////
  698. // Iterate through sub objects and update hide mask and sub obj mesh count.
  699. //////////////////////////////////////////////////////////////////////////
  700. m_nSubObjectMeshCount = 0;
  701. for (size_t i = 0, numsub = m_subObjects.size(); i < numsub; i++)
  702. {
  703. SSubObject& subObj = m_subObjects[i];
  704. if (subObj.pStatObj && subObj.nType == STATIC_SUB_OBJECT_MESH)
  705. {
  706. m_nSubObjectMeshCount++;
  707. }
  708. }
  709. UnMergeSubObjectsRenderMeshes();
  710. }
  711. //////////////////////////////////////////////////////////////////////////
  712. IStatObj* CStatObj::Clone(bool bCloneGeometry, bool bCloneChildren, bool bMeshesOnly)
  713. {
  714. if (m_bDefaultObject)
  715. {
  716. return this;
  717. }
  718. CStatObj* pNewObj = new CStatObj;
  719. pNewObj->m_pClonedSourceObject = m_pClonedSourceObject ? m_pClonedSourceObject : this;
  720. pNewObj->m_pClonedSourceObject->AddRef(); // Cloned object will keep a reference to this.
  721. pNewObj->m_nLoadedTrisCount = m_nLoadedTrisCount;
  722. pNewObj->m_nLoadedVertexCount = m_nLoadedVertexCount;
  723. pNewObj->m_nRenderTrisCount = m_nRenderTrisCount;
  724. if (bCloneGeometry)
  725. {
  726. if (m_bMerged)
  727. {
  728. UnMergeSubObjectsRenderMeshes();
  729. }
  730. if (m_pIndexedMesh && !m_bMerged)
  731. {
  732. pNewObj->m_pIndexedMesh = new CIndexedMesh;
  733. pNewObj->m_pIndexedMesh->Copy(*m_pIndexedMesh->GetMesh());
  734. }
  735. if (m_pRenderMesh && !m_bMerged)
  736. {
  737. _smart_ptr<IRenderMesh> pRenderMesh = GetRenderer()->CreateRenderMesh(
  738. "StatObj_Cloned",
  739. pNewObj->GetFilePath(),
  740. NULL,
  741. ((GetFlags() & STATIC_OBJECT_DYNAMIC) ? eRMT_Dynamic : eRMT_Static));
  742. m_pRenderMesh->CopyTo(pRenderMesh);
  743. pNewObj->SetRenderMesh(pRenderMesh);
  744. }
  745. }
  746. else
  747. {
  748. if (m_pRenderMesh)
  749. {
  750. if (m_pMergedRenderMesh != m_pRenderMesh)
  751. {
  752. pNewObj->SetRenderMesh(m_pRenderMesh);
  753. }
  754. else
  755. {
  756. pNewObj->m_pRenderMesh = m_pRenderMesh;
  757. }
  758. }
  759. pNewObj->m_pMergedRenderMesh = m_pMergedRenderMesh;
  760. pNewObj->m_bMerged = m_pMergedRenderMesh != NULL;
  761. }
  762. pNewObj->m_szFileName = m_szFileName;
  763. pNewObj->m_szGeomName = m_szGeomName;
  764. pNewObj->m_cgfNodeName = m_cgfNodeName;
  765. // Default material.
  766. pNewObj->m_pMaterial = m_pMaterial;
  767. //*pNewObj->m_arrSpriteTexID = *m_arrSpriteTexID;
  768. pNewObj->m_fObjectRadius = m_fObjectRadius;
  769. for (int i = 0; i < m_arrPhysGeomInfo.GetGeomCount(); i++)
  770. {
  771. pNewObj->m_arrPhysGeomInfo.SetPhysGeom(m_arrPhysGeomInfo[i], i, m_arrPhysGeomInfo.GetGeomType(i));
  772. if (pNewObj->m_arrPhysGeomInfo[i])
  773. {
  774. // Remove geometry
  775. CRY_PHYSICS_REPLACEMENT_ASSERT();
  776. }
  777. }
  778. pNewObj->m_vBoxMin = m_vBoxMin;
  779. pNewObj->m_vBoxMax = m_vBoxMax;
  780. pNewObj->m_vVegCenter = m_vVegCenter;
  781. pNewObj->m_fGeometricMeanFaceArea = m_fGeometricMeanFaceArea;
  782. pNewObj->m_fRadiusHors = m_fRadiusHors;
  783. pNewObj->m_fRadiusVert = m_fRadiusVert;
  784. pNewObj->m_nFlags = m_nFlags | STATIC_OBJECT_CLONE;
  785. pNewObj->m_fLodDistance = m_fLodDistance;
  786. //////////////////////////////////////////////////////////////////////////
  787. // Internal Flags.
  788. //////////////////////////////////////////////////////////////////////////
  789. pNewObj->m_bCanUnload = false;
  790. pNewObj->m_bDefaultObject = m_bDefaultObject;
  791. pNewObj->m_bOpenEdgesTested = m_bOpenEdgesTested;
  792. pNewObj->m_bSubObject = false; // [anton] since parent is not copied anyway
  793. pNewObj->m_bVehicleOnlyPhysics = m_bVehicleOnlyPhysics;
  794. pNewObj->m_idmatBreakable = m_idmatBreakable;
  795. pNewObj->m_bBreakableByGame = m_bBreakableByGame;
  796. pNewObj->m_bHasDeformationMorphs = m_bHasDeformationMorphs;
  797. pNewObj->m_bTmpIndexedMesh = m_bTmpIndexedMesh;
  798. pNewObj->m_bHaveOcclusionProxy = m_bHaveOcclusionProxy;
  799. pNewObj->m_bHasStreamOnlyCGF = m_bHasStreamOnlyCGF;
  800. pNewObj->m_eStreamingStatus = m_eStreamingStatus;
  801. //////////////////////////////////////////////////////////////////////////
  802. int numSubObj = (int)m_subObjects.size();
  803. if (bMeshesOnly)
  804. {
  805. numSubObj = 0;
  806. for (size_t i = 0; i < m_subObjects.size(); i++)
  807. {
  808. if (m_subObjects[i].nType == STATIC_SUB_OBJECT_MESH)
  809. {
  810. numSubObj++;
  811. }
  812. else
  813. {
  814. break;
  815. }
  816. }
  817. }
  818. pNewObj->m_subObjects.reserve(numSubObj);
  819. for (int i = 0; i < numSubObj; i++)
  820. {
  821. pNewObj->m_subObjects.push_back(m_subObjects[i]);
  822. if (m_subObjects[i].pStatObj)
  823. {
  824. if (bCloneChildren)
  825. {
  826. pNewObj->m_subObjects[i].pStatObj = m_subObjects[i].pStatObj->Clone(bCloneGeometry, bCloneChildren, bMeshesOnly);
  827. pNewObj->m_subObjects[i].pStatObj->AddRef();
  828. ((CStatObj*)(pNewObj->m_subObjects[i].pStatObj))->m_pParentObject = pNewObj;
  829. }
  830. else
  831. {
  832. m_subObjects[i].pStatObj->AddRef();
  833. ((CStatObj*)(m_subObjects[i].pStatObj))->m_nFlags |= STATIC_OBJECT_MULTIPLE_PARENTS;
  834. }
  835. }
  836. }
  837. pNewObj->m_nSubObjectMeshCount = m_nSubObjectMeshCount;
  838. if (!bCloneChildren)
  839. {
  840. pNewObj->m_bSharesChildren = true;
  841. }
  842. if (pNewObj->m_hasClothTangentsData = m_hasClothTangentsData)
  843. {
  844. pNewObj->m_pClothTangentsData = m_pClothTangentsData;
  845. }
  846. if (pNewObj->m_hasSkinInfo = m_hasSkinInfo)
  847. {
  848. pNewObj->m_pSkinInfo = m_pSkinInfo;
  849. }
  850. return pNewObj;
  851. }
  852. //////////////////////////////////////////////////////////////////////////
  853. IIndexedMesh* CStatObj::GetIndexedMesh(bool bCreateIfNone)
  854. {
  855. WriteLock lock(m_lockIdxMesh);
  856. if (m_pIndexedMesh)
  857. {
  858. return m_pIndexedMesh;
  859. }
  860. else if (m_pRenderMesh && bCreateIfNone)
  861. {
  862. if (m_pRenderMesh->GetIndexedMesh(m_pIndexedMesh = new CIndexedMesh) == NULL)
  863. {
  864. // GetIndexMesh will free the IndexedMesh object if an allocation failed
  865. m_pIndexedMesh = NULL;
  866. return NULL;
  867. }
  868. CMesh* pMesh = m_pIndexedMesh->GetMesh();
  869. if (!pMesh || pMesh->m_subsets.size() <= 0)
  870. {
  871. m_pIndexedMesh->Release();
  872. m_pIndexedMesh = 0;
  873. return 0;
  874. }
  875. m_bTmpIndexedMesh = true;
  876. int i, j, i0 = pMesh->m_subsets[0].nFirstVertId + pMesh->m_subsets[0].nNumVerts;
  877. for (i = j = 1; i < pMesh->m_subsets.size(); i++)
  878. {
  879. if (pMesh->m_subsets[i].nFirstVertId - i0 < pMesh->m_subsets[j].nFirstVertId - i0)
  880. {
  881. j = i;
  882. }
  883. }
  884. if (j < pMesh->m_subsets.size() && pMesh->m_subsets[0].nPhysicalizeType == PHYS_GEOM_TYPE_DEFAULT &&
  885. pMesh->m_subsets[j].nPhysicalizeType != PHYS_GEOM_TYPE_DEFAULT && pMesh->m_subsets[j].nFirstVertId > i0)
  886. {
  887. pMesh->m_subsets[j].nNumVerts += pMesh->m_subsets[j].nFirstVertId - i0;
  888. pMesh->m_subsets[j].nFirstVertId = i0;
  889. }
  890. return m_pIndexedMesh;
  891. }
  892. return 0;
  893. }
  894. IIndexedMesh* CStatObj::CreateIndexedMesh()
  895. {
  896. if (!m_pIndexedMesh)
  897. {
  898. m_pIndexedMesh = new CIndexedMesh();
  899. }
  900. return m_pIndexedMesh;
  901. }
  902. void CStatObj::ReleaseIndexedMesh(bool bRenderMeshUpdated)
  903. {
  904. WriteLock lock(m_lockIdxMesh);
  905. if (m_bTmpIndexedMesh && m_pIndexedMesh)
  906. {
  907. int istart, iend;
  908. CMesh* pMesh = m_pIndexedMesh->GetMesh();
  909. if (m_pRenderMesh && !bRenderMeshUpdated)
  910. {
  911. TRenderChunkArray& Chunks = m_pRenderMesh->GetChunks();
  912. for (int i = 0; i < pMesh->m_subsets.size(); i++)
  913. {
  914. Chunks[i].m_nMatFlags |= pMesh->m_subsets[i].nMatFlags & 1 << 30;
  915. }
  916. }
  917. if (bRenderMeshUpdated && m_pBoneMapping)
  918. {
  919. for (int i = iend = 0; i < (int)pMesh->m_subsets.size(); i++)
  920. {
  921. if ((pMesh->m_subsets[i].nMatFlags & (MTL_FLAG_NOPHYSICALIZE | MTL_FLAG_NODRAW)) == MTL_FLAG_NOPHYSICALIZE)
  922. {
  923. for (istart = iend++; iend < (int)m_chunkBoneIds.size() && m_chunkBoneIds[iend]; iend++)
  924. {
  925. ;
  926. }
  927. if (!pMesh->m_subsets[i].nNumIndices)
  928. {
  929. m_chunkBoneIds.erase(m_chunkBoneIds.begin() + istart, m_chunkBoneIds.begin() + iend);
  930. iend = istart;
  931. }
  932. }
  933. }
  934. }
  935. m_pIndexedMesh->Release();
  936. m_pIndexedMesh = 0;
  937. m_bTmpIndexedMesh = false;
  938. }
  939. }
  940. //////////////////////////////////////////////////////////////////////////
  941. static bool SubObjectsOfCompoundHaveLOD(const CStatObj* pStatObj, int nLod)
  942. {
  943. int numSubObjects = pStatObj->GetSubObjectCount();
  944. for (int i = 0; i < numSubObjects; ++i)
  945. {
  946. const IStatObj::SSubObject* pSubObject = const_cast<CStatObj*>(pStatObj)->GetSubObject(i);
  947. if (!pSubObject)
  948. {
  949. continue;
  950. }
  951. const CStatObj* pChildObj = (const CStatObj*)pSubObject->pStatObj;
  952. if (!pChildObj)
  953. {
  954. continue;
  955. }
  956. if (!pChildObj->m_pLODs)
  957. {
  958. continue;
  959. }
  960. const CStatObj* pLod = pChildObj->m_pLODs[nLod];
  961. if (pLod)
  962. {
  963. return true;
  964. }
  965. }
  966. return false;
  967. }
  968. //////////////////////////////////////////////////////////////////////////
  969. void CStatObj::TryMergeSubObjects(bool bFromStreaming)
  970. {
  971. // sub meshes merging
  972. if (GetCVars()->e_StatObjMerge)
  973. {
  974. if (!m_bUnmergable && !IsDeformable())
  975. {
  976. MergeSubObjectsRenderMeshes(bFromStreaming, this, 0);
  977. if (!bFromStreaming && !m_pLODs && m_nFlags & STATIC_OBJECT_COMPOUND)
  978. {
  979. // Check if LODs were not split (production mode)
  980. for (int i = 1; i < MAX_STATOBJ_LODS_NUM; ++i)
  981. {
  982. if (!SubObjectsOfCompoundHaveLOD(this, i))
  983. {
  984. continue;
  985. }
  986. CStatObj* pStatObj = new CStatObj();
  987. pStatObj->m_szFileName = m_szFileName;
  988. char lodName[32];
  989. azstrcpy(lodName, 32, "-mlod");
  990. azltoa(i, lodName + 5, AZ_ARRAY_SIZE(lodName) - 5, 10);
  991. pStatObj->m_szFileName.append(lodName);
  992. pStatObj->m_szGeomName = m_szGeomName;
  993. pStatObj->m_bSubObject = true;
  994. SetLodObject(i, pStatObj);
  995. m_bMergedLODs = true;
  996. }
  997. }
  998. if (m_pLODs)
  999. {
  1000. for (int i = 1; i < MAX_STATOBJ_LODS_NUM; i++)
  1001. {
  1002. if (m_pLODs[i])
  1003. {
  1004. m_pLODs[i]->MergeSubObjectsRenderMeshes(bFromStreaming, this, i);
  1005. }
  1006. }
  1007. }
  1008. }
  1009. }
  1010. }
  1011. //////////////////////////////////////////////////////////////////////////
  1012. void CStatObj::MergeSubObjectsRenderMeshes(bool bFromStreaming, CStatObj* pLod0, int nLod)
  1013. {
  1014. if (m_bUnmergable)
  1015. {
  1016. return;
  1017. }
  1018. FUNCTION_PROFILER_3DENGINE;
  1019. LOADING_TIME_PROFILE_SECTION;
  1020. m_bMerged = false;
  1021. m_pMergedRenderMesh = 0;
  1022. int nSubObjCount = (int)pLod0->m_subObjects.size();
  1023. std::vector<SRenderMeshInfoInput> lstRMI;
  1024. SRenderMeshInfoInput rmi;
  1025. rmi.pMat = m_pMaterial;
  1026. rmi.mat.SetIdentity();
  1027. rmi.pMesh = 0;
  1028. rmi.pSrcRndNode = 0;
  1029. for (int s = 0; s < nSubObjCount; s++)
  1030. {
  1031. CStatObj::SSubObject* pSubObj = &pLod0->m_subObjects[s];
  1032. if (pSubObj->pStatObj && pSubObj->nType == STATIC_SUB_OBJECT_MESH)
  1033. {
  1034. CStatObj* pStatObj = (CStatObj*)pSubObj->pStatObj->GetLodObject(nLod, true); // Get lod, if not exist get lowest existing.
  1035. if (pStatObj)
  1036. {
  1037. CryAutoCriticalSection lock(pStatObj->m_streamingMeshLock);
  1038. if (pStatObj->m_pRenderMesh || pStatObj->m_pStreamedRenderMesh)
  1039. {
  1040. rmi.pMesh = pStatObj->m_pRenderMesh ? pStatObj->m_pRenderMesh : pStatObj->m_pStreamedRenderMesh;
  1041. rmi.mat = pSubObj->tm;
  1042. rmi.bIdentityMatrix = pSubObj->bIdentityMatrix;
  1043. rmi.nSubObjectIndex = s;
  1044. lstRMI.push_back(rmi);
  1045. }
  1046. }
  1047. }
  1048. }
  1049. _smart_ptr<IRenderMesh> pMergedMesh = 0;
  1050. if (lstRMI.size() == 1 && lstRMI[0].bIdentityMatrix)
  1051. {
  1052. // If identity matrix and only mesh-subobject use it as a merged render mesh.
  1053. pMergedMesh = rmi.pMesh;
  1054. }
  1055. else if (!lstRMI.empty())
  1056. {
  1057. SMergeInfo info;
  1058. info.sMeshName = GetFilePath();
  1059. info.sMeshType = "StatObj_Merged";
  1060. info.bMergeToOneRenderMesh = true;
  1061. info.pUseMaterial = m_pMaterial;
  1062. pMergedMesh = GetSharedRenderMeshMerger()->MergeRenderMeshes(&lstRMI[0], lstRMI.size(), info);
  1063. }
  1064. if (pMergedMesh)
  1065. {
  1066. if (bFromStreaming)
  1067. {
  1068. CryAutoCriticalSection lock(m_streamingMeshLock);
  1069. m_pMergedRenderMesh = pMergedMesh;
  1070. m_pStreamedRenderMesh = pMergedMesh;
  1071. }
  1072. else
  1073. {
  1074. m_pMergedRenderMesh = pMergedMesh;
  1075. SetRenderMesh(pMergedMesh);
  1076. }
  1077. m_bMerged = true;
  1078. if (m_pLod0)
  1079. {
  1080. // Make sure upmost lod is also marked to be merged.
  1081. m_pLod0->SetMerged(true);
  1082. }
  1083. }
  1084. }
  1085. bool CStatObj::IsMatIDReferencedByObj(uint16 matID)
  1086. {
  1087. //Check root obj
  1088. if (IRenderMesh* pRenderMesh = GetRenderMesh())
  1089. {
  1090. TRenderChunkArray& Chunks = pRenderMesh->GetChunks();
  1091. for (int nChunkId = 0; nChunkId < Chunks.size(); nChunkId++)
  1092. {
  1093. if (Chunks[nChunkId].m_nMatID == matID)
  1094. {
  1095. return true;
  1096. }
  1097. }
  1098. }
  1099. //check children
  1100. int nSubObjCount = (int)m_subObjects.size();
  1101. for (int s = 0; s < nSubObjCount; s++)
  1102. {
  1103. CStatObj::SSubObject* pSubObj = &m_subObjects[s];
  1104. if (pSubObj->pStatObj)
  1105. {
  1106. CStatObj* pSubStatObj = (CStatObj*)pSubObj->pStatObj;
  1107. if (IRenderMesh* pSubRenderMesh = pSubStatObj->GetRenderMesh())
  1108. {
  1109. TRenderChunkArray& Chunks = pSubRenderMesh->GetChunks();
  1110. for (int nChunkId = 0; nChunkId < Chunks.size(); nChunkId++)
  1111. {
  1112. if (Chunks[nChunkId].m_nMatID == matID)
  1113. {
  1114. return true;
  1115. }
  1116. }
  1117. }
  1118. }
  1119. }
  1120. return false;
  1121. }
  1122. //////////////////////////////////////////////////////////////////////////
  1123. bool CStatObj::CanMergeSubObjects()
  1124. {
  1125. if (gEnv->IsDedicated())
  1126. {
  1127. return false;
  1128. }
  1129. if (!m_clothData.empty())
  1130. {
  1131. return false;
  1132. }
  1133. int nSubMeshes = 0;
  1134. int nTotalVertexCount = 0;
  1135. int nTotalTriCount = 0;
  1136. int nTotalRenderChunksCount = 0;
  1137. int nSubObjCount = (int)m_subObjects.size();
  1138. for (int s = 0; s < nSubObjCount; s++)
  1139. {
  1140. CStatObj::SSubObject* pSubObj = &m_subObjects[s];
  1141. if (pSubObj->pStatObj && pSubObj->nType == STATIC_SUB_OBJECT_MESH && !pSubObj->bHidden)
  1142. {
  1143. CStatObj* pStatObj = (CStatObj*)pSubObj->pStatObj;
  1144. // Conditions to not merge subobjects
  1145. if (pStatObj->m_pMaterial != m_pMaterial || // Different materials
  1146. pStatObj->m_nSpines || // It's bendable foliage
  1147. !pStatObj->m_clothData.empty()) // It's cloth
  1148. {
  1149. return false;
  1150. }
  1151. nSubMeshes++;
  1152. nTotalVertexCount += pStatObj->m_nLoadedVertexCount;
  1153. nTotalTriCount += pStatObj->m_nLoadedTrisCount;
  1154. nTotalRenderChunksCount += pStatObj->m_nRenderMatIds;
  1155. }
  1156. }
  1157. // Check for mat_breakable surface type in material
  1158. if (m_pMaterial)
  1159. {
  1160. int nSubMtls = m_pMaterial->GetSubMtlCount();
  1161. if (nSubMtls > 0)
  1162. {
  1163. for (int i = 0; i < nSubMtls; ++i)
  1164. {
  1165. _smart_ptr<IMaterial> pSubMtl = m_pMaterial->GetSafeSubMtl(i);
  1166. if (pSubMtl)
  1167. {
  1168. ISurfaceType* pSFType = pSubMtl->GetSurfaceType();
  1169. // This is breakable glass.
  1170. // Do not merge meshes that have procedural physics breakability in them.
  1171. if (pSFType && pSFType->GetBreakability() != 0)
  1172. {
  1173. //if mesh is streamed, we must assume the material is referenced
  1174. if (m_bMeshStrippedCGF)
  1175. {
  1176. return false;
  1177. }
  1178. else if (IsMatIDReferencedByObj((uint16)i))
  1179. {
  1180. return false;
  1181. }
  1182. }
  1183. }
  1184. }
  1185. }
  1186. else // nSubMtls==0
  1187. {
  1188. ISurfaceType* pSFType = m_pMaterial->GetSurfaceType();
  1189. // This is breakable glass.
  1190. // Do not merge meshes that have procedural physics breakability in them.
  1191. if (pSFType && pSFType->GetBreakability() != 0)
  1192. {
  1193. return false;
  1194. }
  1195. }
  1196. }
  1197. if (nTotalVertexCount > MAX_VERTICES_MERGABLE || nSubMeshes <= 1 || nTotalRenderChunksCount <= 1)
  1198. {
  1199. return false;
  1200. }
  1201. if ((nTotalTriCount / nTotalRenderChunksCount) > GetCVars()->e_StatObjMergeMaxTrisPerDrawCall)
  1202. {
  1203. return false; // tris to draw calls ratio is already not so bad
  1204. }
  1205. return true;
  1206. }
  1207. //////////////////////////////////////////////////////////////////////////
  1208. void CStatObj::UnMergeSubObjectsRenderMeshes()
  1209. {
  1210. if (m_bMerged)
  1211. {
  1212. m_bMerged = false;
  1213. m_pMergedRenderMesh = 0;
  1214. SetRenderMesh(0);
  1215. }
  1216. if (m_bMergedLODs)
  1217. {
  1218. delete[] m_pLODs;
  1219. m_pLODs = 0;
  1220. }
  1221. }
  1222. //------------------------------------------------------------------------------
  1223. // This function is recovered from previous FindSubObject function which was then
  1224. // changed and creating many CGA model issues (some joints never move).
  1225. CStatObj::SSubObject* CStatObj::FindSubObject_CGA(const char* sNodeName)
  1226. {
  1227. uint32 numSubObjects = m_subObjects.size();
  1228. for (uint32 i = 0; i < numSubObjects; i++)
  1229. {
  1230. if (azstricmp(m_subObjects[i].name.c_str(), sNodeName) == 0)
  1231. {
  1232. return &m_subObjects[i];
  1233. }
  1234. }
  1235. return 0;
  1236. }
  1237. //////////////////////////////////////////////////////////////////////////
  1238. CStatObj::SSubObject* CStatObj::FindSubObject(const char* sNodeName)
  1239. {
  1240. uint32 numSubObjects = m_subObjects.size();
  1241. int len = 1; // some objects has ' ' in the beginning
  1242. for (; sNodeName[len] > ' ' && sNodeName[len] != ',' && sNodeName[len] != ';'; len++)
  1243. {
  1244. ;
  1245. }
  1246. for (uint32 i = 0; i < numSubObjects; i++)
  1247. {
  1248. if (_strnicmp(m_subObjects[i].name.c_str(), sNodeName, len) == 0 && m_subObjects[i].name[len] == 0)
  1249. {
  1250. return &m_subObjects[i];
  1251. }
  1252. }
  1253. return 0;
  1254. }
  1255. //////////////////////////////////////////////////////////////////////////
  1256. CStatObj::SSubObject* CStatObj::FindSubObject_StrStr(const char* sNodeName)
  1257. {
  1258. uint32 numSubObjects = m_subObjects.size();
  1259. for (uint32 i = 0; i < numSubObjects; i++)
  1260. {
  1261. if (stristr(m_subObjects[i].name.c_str(), sNodeName))
  1262. {
  1263. return &m_subObjects[i];
  1264. }
  1265. }
  1266. return 0;
  1267. }
  1268. //////////////////////////////////////////////////////////////////////////
  1269. IStatObj::SSubObject& CStatObj::AddSubObject(IStatObj* pSubObj)
  1270. {
  1271. assert(pSubObj);
  1272. SetSubObjectCount(m_subObjects.size() + 1);
  1273. InitializeSubObject(m_subObjects[m_subObjects.size() - 1]);
  1274. m_subObjects[m_subObjects.size() - 1].pStatObj = pSubObj;
  1275. pSubObj->AddRef();
  1276. return m_subObjects[m_subObjects.size() - 1];
  1277. }
  1278. //////////////////////////////////////////////////////////////////////////
  1279. bool CStatObj::RemoveSubObject(int nIndex)
  1280. {
  1281. if (nIndex >= 0 && nIndex < (int)m_subObjects.size())
  1282. {
  1283. SSubObject* pSubObj = &m_subObjects[nIndex];
  1284. CStatObj* pChildObj = (CStatObj*)pSubObj->pStatObj;
  1285. if (pChildObj)
  1286. {
  1287. if (!m_bSharesChildren)
  1288. {
  1289. pChildObj->m_pParentObject = NULL;
  1290. }
  1291. pChildObj->Release();
  1292. }
  1293. m_subObjects.erase(m_subObjects.begin() + nIndex);
  1294. Invalidate(true);
  1295. return true;
  1296. }
  1297. return false;
  1298. }
  1299. //////////////////////////////////////////////////////////////////////////
  1300. void CStatObj::SetSubObjectCount(int nCount)
  1301. {
  1302. // remove sub objects.
  1303. while ((int)m_subObjects.size() > nCount)
  1304. {
  1305. RemoveSubObject(m_subObjects.size() - 1);
  1306. }
  1307. SSubObject subobj;
  1308. InitializeSubObject(subobj);
  1309. m_subObjects.resize(nCount, subobj);
  1310. if (nCount > 0)
  1311. {
  1312. m_nFlags |= STATIC_OBJECT_COMPOUND;
  1313. }
  1314. else
  1315. {
  1316. m_nFlags &= ~STATIC_OBJECT_COMPOUND;
  1317. }
  1318. Invalidate(true);
  1319. UnMergeSubObjectsRenderMeshes();
  1320. }
  1321. //////////////////////////////////////////////////////////////////////////
  1322. bool CStatObj::CopySubObject(int nToIndex, IStatObj* pFromObj, int nFromIndex)
  1323. {
  1324. SSubObject* pSrcSubObj = pFromObj->GetSubObject(nFromIndex);
  1325. if (!pSrcSubObj)
  1326. {
  1327. return false;
  1328. }
  1329. if (nToIndex >= (int)m_subObjects.size())
  1330. {
  1331. SetSubObjectCount(nToIndex + 1);
  1332. if (pFromObj == this)
  1333. {
  1334. pSrcSubObj = pFromObj->GetSubObject(nFromIndex);
  1335. }
  1336. }
  1337. m_subObjects[nToIndex] = *pSrcSubObj;
  1338. if (pSrcSubObj->pStatObj)
  1339. {
  1340. pSrcSubObj->pStatObj->AddRef();
  1341. }
  1342. Invalidate(true);
  1343. return true;
  1344. }
  1345. //////////////////////////////////////////////////////////////////////////
  1346. bool CStatObj::GetPhysicalProperties(float& mass, float& density)
  1347. {
  1348. mass = m_phys_mass;
  1349. density = m_phys_density;
  1350. if (mass < 0 && density < 0)
  1351. {
  1352. return false;
  1353. }
  1354. return true;
  1355. }
  1356. //////////////////////////////////////////////////////////////////////////
  1357. bool CStatObj::RayIntersection(SRayHitInfo& hitInfo, _smart_ptr<IMaterial> pCustomMtl)
  1358. {
  1359. Vec3 vOut;
  1360. bool bNonDirectionalTest = hitInfo.inRay.direction.IsZero();
  1361. // First check if ray intersect objects bounding box.
  1362. if (!bNonDirectionalTest && !Intersect::Ray_AABB(hitInfo.inRay, AABB(m_vBoxMin, m_vBoxMax), vOut))
  1363. {
  1364. return false;
  1365. }
  1366. if (bNonDirectionalTest && !Overlap::AABB_AABB(
  1367. AABB(hitInfo.inRay.origin - Vec3(hitInfo.fMaxHitDistance), hitInfo.inRay.origin + Vec3(hitInfo.fMaxHitDistance)),
  1368. AABB(m_vBoxMin, m_vBoxMax)))
  1369. {
  1370. return false;
  1371. }
  1372. if ((m_nFlags & STATIC_OBJECT_COMPOUND) && !m_bMerged)
  1373. {
  1374. SRayHitInfo hitOut;
  1375. bool bAnyHit = false;
  1376. float fMinDistance = FLT_MAX;
  1377. for (int i = 0, num = m_subObjects.size(); i < num; i++)
  1378. {
  1379. if (m_subObjects[i].pStatObj && m_subObjects[i].nType == STATIC_SUB_OBJECT_MESH && !m_subObjects[i].bHidden)
  1380. {
  1381. if (((CStatObj*)(m_subObjects[i].pStatObj))->m_nFlags & STATIC_OBJECT_HIDDEN)
  1382. {
  1383. continue;
  1384. }
  1385. Matrix34 invertedTM = m_subObjects[i].tm.GetInverted();
  1386. SRayHitInfo hit = hitInfo;
  1387. // Transform ray into sub-object local space.
  1388. hit.inReferencePoint = invertedTM.TransformPoint(hit.inReferencePoint);
  1389. hit.inRay.origin = invertedTM.TransformPoint(hit.inRay.origin);
  1390. hit.inRay.direction = invertedTM.TransformVector(hit.inRay.direction);
  1391. int nFirstTriangleId = hit.pHitTris ? hit.pHitTris->Count() : 0;
  1392. if (((CStatObj*)m_subObjects[i].pStatObj)->RayIntersection(hit, pCustomMtl))
  1393. {
  1394. if (hit.fDistance < fMinDistance)
  1395. {
  1396. hitInfo.pStatObj = m_subObjects[i].pStatObj;
  1397. bAnyHit = true;
  1398. hitOut = hit;
  1399. }
  1400. }
  1401. // transform collected triangles from sub-object space into object space
  1402. if (hit.pHitTris)
  1403. {
  1404. for (int t = nFirstTriangleId; t < hit.pHitTris->Count(); t++)
  1405. {
  1406. SRayHitTriangle& ht = hit.pHitTris->GetAt(t);
  1407. for (int c = 0; c < 3; c++)
  1408. {
  1409. ht.v[c] = m_subObjects[i].tm.TransformPoint(ht.v[c]);
  1410. }
  1411. }
  1412. }
  1413. }
  1414. }
  1415. if (bAnyHit)
  1416. {
  1417. // Restore input ray/reference point.
  1418. hitOut.inReferencePoint = hitInfo.inReferencePoint;
  1419. hitOut.inRay = hitInfo.inRay;
  1420. hitInfo = hitOut;
  1421. return true;
  1422. }
  1423. }
  1424. else
  1425. {
  1426. bool result = false;
  1427. IRenderMesh* pRenderMesh = m_pRenderMesh;
  1428. // Sometimes, object has no base lod mesh. So need to hit test with low level mesh.
  1429. // If the distance from camera is larger then a base lod distance, then base lod mesh is not loaded yet.
  1430. if (!pRenderMesh && m_nMaxUsableLod > 0 && m_pLODs && m_pLODs[m_nMaxUsableLod])
  1431. {
  1432. pRenderMesh = m_pLODs[m_nMaxUsableLod]->GetRenderMesh();
  1433. }
  1434. AZ_Warning("StatObj Ray Intersection",
  1435. pRenderMesh,
  1436. "No render mesh available for hit testing for statobj %s", m_szFileName.c_str());
  1437. if (pRenderMesh)
  1438. {
  1439. result = CRenderMeshUtils::RayIntersection(pRenderMesh, hitInfo, pCustomMtl);
  1440. if (result)
  1441. {
  1442. hitInfo.pStatObj = this;
  1443. hitInfo.pRenderMesh = pRenderMesh;
  1444. }
  1445. }
  1446. return result;
  1447. }
  1448. return false;
  1449. }
  1450. bool CStatObj::LineSegIntersection(const Lineseg& lineSeg, Vec3& hitPos, int& surfaceTypeId)
  1451. {
  1452. bool intersects = false;
  1453. #ifdef SERVER_CHECKS
  1454. if (m_pMesh)
  1455. {
  1456. int numVertices, numVerticesf16, numIndices;
  1457. Vec3* pPositions = m_pMesh->GetStreamPtrAndElementCount<Vec3>(CMesh::POSITIONS, 0, &numVertices);
  1458. Vec3f16* pPositionsf16 = m_pMesh->GetStreamPtrAndElementCount<Vec3f16>(CMesh::POSITIONSF16, 0, &numVerticesf16);
  1459. uint16* pIndices = m_pMesh->GetStreamPtrAndElementCount<uint16>(CMesh::INDICES, 0, &numIndices);
  1460. if (numIndices && numVerticesf16)
  1461. {
  1462. DynArray<SMeshSubset>::iterator itSubset;
  1463. for (itSubset = m_pMesh->m_subsets.begin(); itSubset != m_pMesh->m_subsets.end(); ++itSubset)
  1464. {
  1465. if (!(itSubset->nMatFlags & MTL_FLAG_NODRAW))
  1466. {
  1467. int lastIndex = itSubset->nFirstIndexId + itSubset->nNumIndices;
  1468. for (int i = itSubset->nFirstIndexId; i < lastIndex; )
  1469. {
  1470. const Vec3 v0 = pPositionsf16[pIndices[i++]].ToVec3();
  1471. const Vec3 v1 = pPositionsf16[pIndices[i++]].ToVec3();
  1472. const Vec3 v2 = pPositionsf16[pIndices[i++]].ToVec3();
  1473. if (Intersect::Lineseg_Triangle(lineSeg, v0, v2, v1, hitPos) || // Front face
  1474. Intersect::Lineseg_Triangle(lineSeg, v0, v1, v2, hitPos)) // Back face
  1475. {
  1476. _smart_ptr<IMaterial> pMtl = m_pMaterial->GetSafeSubMtl(itSubset->nMatID);
  1477. surfaceTypeId = pMtl->GetSurfaceTypeId();
  1478. intersects = true;
  1479. break;
  1480. }
  1481. }
  1482. }
  1483. }
  1484. }
  1485. else if (numIndices && numVertices)
  1486. {
  1487. DynArray<SMeshSubset>::iterator itSubset;
  1488. for (itSubset = m_pMesh->m_subsets.begin(); itSubset != m_pMesh->m_subsets.end(); ++itSubset)
  1489. {
  1490. if (!(itSubset->nMatFlags & MTL_FLAG_NODRAW))
  1491. {
  1492. int lastIndex = itSubset->nFirstIndexId + itSubset->nNumIndices;
  1493. for (int i = itSubset->nFirstIndexId; i < lastIndex; )
  1494. {
  1495. const Vec3& v0 = pPositions[pIndices[i++]];
  1496. const Vec3& v1 = pPositions[pIndices[i++]];
  1497. const Vec3& v2 = pPositions[pIndices[i++]];
  1498. if (Intersect::Lineseg_Triangle(lineSeg, v0, v2, v1, hitPos) || // Front face
  1499. Intersect::Lineseg_Triangle(lineSeg, v0, v1, v2, hitPos)) // Back face
  1500. {
  1501. _smart_ptr<IMaterial> pMtl = m_pMaterial->GetSafeSubMtl(itSubset->nMatID);
  1502. surfaceTypeId = pMtl->GetSurfaceTypeId();
  1503. intersects = true;
  1504. break;
  1505. }
  1506. }
  1507. }
  1508. }
  1509. }
  1510. }
  1511. else
  1512. #endif
  1513. if (m_pRenderMesh)
  1514. {
  1515. m_pRenderMesh->LockForThreadAccess();
  1516. int numIndices = m_pRenderMesh->GetIndicesCount();
  1517. int numVertices = m_pRenderMesh->GetVerticesCount();
  1518. if (numIndices && numVertices)
  1519. {
  1520. int posStride;
  1521. uint8* pPositions = (uint8*)m_pRenderMesh->GetPosPtr(posStride, FSL_READ);
  1522. vtx_idx* pIndices = m_pRenderMesh->GetIndexPtr(FSL_READ);
  1523. TRenderChunkArray& Chunks = m_pRenderMesh->GetChunks();
  1524. int nChunkCount = Chunks.size();
  1525. for (int nChunkId = 0; nChunkId < nChunkCount; nChunkId++)
  1526. {
  1527. CRenderChunk* pChunk = &Chunks[nChunkId];
  1528. if (!(pChunk->m_nMatFlags & MTL_FLAG_NODRAW))
  1529. {
  1530. int lastIndex = pChunk->nFirstIndexId + pChunk->nNumIndices;
  1531. for (int i = pChunk->nFirstIndexId; i < lastIndex; )
  1532. {
  1533. const Vec3& v0 = *(Vec3*)(pPositions + pIndices[i++] * posStride);
  1534. const Vec3& v1 = *(Vec3*)(pPositions + pIndices[i++] * posStride);
  1535. const Vec3& v2 = *(Vec3*)(pPositions + pIndices[i++] * posStride);
  1536. if (Intersect::Lineseg_Triangle(lineSeg, v0, v2, v1, hitPos) || // Front face
  1537. Intersect::Lineseg_Triangle(lineSeg, v0, v1, v2, hitPos)) // Back face
  1538. {
  1539. _smart_ptr<IMaterial> pMtl = m_pMaterial->GetSafeSubMtl(pChunk->m_nMatID);
  1540. surfaceTypeId = pMtl->GetSurfaceTypeId();
  1541. intersects = true;
  1542. break;
  1543. }
  1544. }
  1545. }
  1546. }
  1547. }
  1548. m_pRenderMesh->UnlockStream(VSF_GENERAL);
  1549. m_pRenderMesh->UnlockIndexStream();
  1550. m_pRenderMesh->UnLockForThreadAccess();
  1551. }
  1552. return intersects;
  1553. }
  1554. #ifdef SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
  1555. float CStatObj::GetOcclusionAmount()
  1556. {
  1557. if (m_fOcclusionAmount < 0)
  1558. {
  1559. PrintMessage("Computing occlusion value for: %s ... ", GetFilePath());
  1560. float fHits = 0;
  1561. float fTests = 0;
  1562. Matrix34 objMatrix;
  1563. objMatrix.SetIdentity();
  1564. Vec3 vStep = Vec3(0.5f, 0.5f, 0.5f);
  1565. Vec3 vClosestHitPoint;
  1566. float fClosestHitDistance = 1000;
  1567. // y-rays
  1568. for (float x = m_vBoxMin.x; x <= m_vBoxMax.x; x += vStep.x)
  1569. {
  1570. for (float z = m_vBoxMin.z; z <= m_vBoxMax.z; z += vStep.z)
  1571. {
  1572. Vec3 vStart (x, m_vBoxMin.y, z);
  1573. Vec3 vEnd (x, m_vBoxMax.y, z);
  1574. if (GetObjManager()->RayStatObjIntersection(this, objMatrix, GetMaterial(), vStart, vEnd, vClosestHitPoint, fClosestHitDistance, true))
  1575. {
  1576. fHits++;
  1577. }
  1578. fTests++;
  1579. }
  1580. }
  1581. // x-rays
  1582. for (float y = m_vBoxMin.y; y <= m_vBoxMax.y; y += vStep.y)
  1583. {
  1584. for (float z = m_vBoxMin.z; z <= m_vBoxMax.z; z += vStep.z)
  1585. {
  1586. Vec3 vStart (m_vBoxMin.x, y, z);
  1587. Vec3 vEnd (m_vBoxMax.x, y, z);
  1588. if (GetObjManager()->RayStatObjIntersection(this, objMatrix, GetMaterial(), vStart, vEnd, vClosestHitPoint, fClosestHitDistance, true))
  1589. {
  1590. fHits++;
  1591. }
  1592. fTests++;
  1593. }
  1594. }
  1595. // z-rays
  1596. for (float y = m_vBoxMin.y; y <= m_vBoxMax.y; y += vStep.y)
  1597. {
  1598. for (float x = m_vBoxMin.x; x <= m_vBoxMax.x; x += vStep.x)
  1599. {
  1600. Vec3 vStart (x, y, m_vBoxMax.z);
  1601. Vec3 vEnd (x, y, m_vBoxMin.z);
  1602. if (GetObjManager()->RayStatObjIntersection(this, objMatrix, GetMaterial(), vStart, vEnd, vClosestHitPoint, fClosestHitDistance, true))
  1603. {
  1604. fHits++;
  1605. }
  1606. fTests++;
  1607. }
  1608. }
  1609. m_fOcclusionAmount = fTests ? (fHits / fTests) : 0;
  1610. PrintMessagePlus("[%.2f]", m_fOcclusionAmount);
  1611. }
  1612. return m_fOcclusionAmount;
  1613. }
  1614. #endif
  1615. void CStatObj::SetRenderMesh(IRenderMesh* pRM)
  1616. {
  1617. LOADING_TIME_PROFILE_SECTION;
  1618. if (pRM == m_pRenderMesh)
  1619. {
  1620. return;
  1621. }
  1622. {
  1623. CryAutoCriticalSection lock(m_streamingMeshLock);
  1624. m_pRenderMesh = pRM;
  1625. }
  1626. if (m_pRenderMesh)
  1627. {
  1628. m_nRenderTrisCount = 0;
  1629. m_nRenderMatIds = 0;
  1630. TRenderChunkArray& Chunks = m_pRenderMesh->GetChunks();
  1631. for (int nChunkId = 0; nChunkId < Chunks.size(); nChunkId++)
  1632. {
  1633. CRenderChunk* pChunk = &Chunks[nChunkId];
  1634. if (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE)
  1635. {
  1636. continue;
  1637. }
  1638. if (pChunk->nNumIndices > 0)
  1639. {
  1640. m_nRenderMatIds++;
  1641. m_nRenderTrisCount += pChunk->nNumIndices / 3;
  1642. }
  1643. }
  1644. m_nLoadedTrisCount = pRM->GetIndicesCount() / 3;
  1645. m_nLoadedVertexCount = pRM->GetVerticesCount();
  1646. }
  1647. // this will prepare all deformable object during loading instead when needed.
  1648. // Thus is will prevent runtime stalls (300ms when shooting a taxi with 6000 vertices)
  1649. // but will incrase memory since every deformable information needs to be loaded(500kb for the taxi)
  1650. // So this is more a workaround, the real solution would precompute the data in the RC and load
  1651. // the data only when needed into memory
  1652. if (GetCVars()->e_PrepareDeformableObjectsAtLoadTime && m_pRenderMesh && m_pDelayedSkinParams)
  1653. {
  1654. PrepareSkinData(m_pDelayedSkinParams->mtxSkelToMesh, m_pDelayedSkinParams->pPhysSkel, m_pDelayedSkinParams->r);
  1655. }
  1656. }
  1657. #ifdef SUPPORT_TERRAIN_AO_PRE_COMPUTATIONS
  1658. void CStatObj::CheckUpdateObjectHeightmap()
  1659. {
  1660. if (m_pHeightmap)
  1661. {
  1662. return;
  1663. }
  1664. PrintMessage("Computing object heightmap for: %s ... ", GetFilePath());
  1665. m_nHeightmapSize = (int)(CLAMP(max(m_vBoxMax.x - m_vBoxMin.x, m_vBoxMax.y - m_vBoxMin.y) * 16, 8, 256));
  1666. m_pHeightmap = new float[m_nHeightmapSize * m_nHeightmapSize];
  1667. memset(m_pHeightmap, 0, sizeof(float) * m_nHeightmapSize * m_nHeightmapSize);
  1668. float dx = max(0.001f, (m_vBoxMax.x - m_vBoxMin.x) / m_nHeightmapSize);
  1669. float dy = max(0.001f, (m_vBoxMax.y - m_vBoxMin.y) / m_nHeightmapSize);
  1670. Matrix34 objMatrix;
  1671. objMatrix.SetIdentity();
  1672. for (float x = m_vBoxMin.x + dx; x < m_vBoxMax.x - dx; x += dx)
  1673. {
  1674. for (float y = m_vBoxMin.y + dy; y < m_vBoxMax.y - dy; y += dy)
  1675. {
  1676. Vec3 vStart (x, y, m_vBoxMax.z);
  1677. Vec3 vEnd (x, y, m_vBoxMin.z);
  1678. Vec3 vClosestHitPoint(0, 0, 0);
  1679. float fClosestHitDistance = 1000000;
  1680. if (GetObjManager()->RayStatObjIntersection(this, objMatrix, GetMaterial(),
  1681. vStart, vEnd, vClosestHitPoint, fClosestHitDistance, false))
  1682. {
  1683. int nX = CLAMP(int((x - m_vBoxMin.x) / dx), 0, m_nHeightmapSize - 1);
  1684. int nY = CLAMP(int((y - m_vBoxMin.y) / dy), 0, m_nHeightmapSize - 1);
  1685. m_pHeightmap[nX * m_nHeightmapSize + nY] = vClosestHitPoint.z;
  1686. }
  1687. }
  1688. }
  1689. PrintMessagePlus("[%dx%d] done", m_nHeightmapSize, m_nHeightmapSize);
  1690. }
  1691. float CStatObj::GetObjectHeight(float x, float y)
  1692. {
  1693. CheckUpdateObjectHeightmap();
  1694. float dx = max(0.001f, (m_vBoxMax.x - m_vBoxMin.x) / m_nHeightmapSize);
  1695. float dy = max(0.001f, (m_vBoxMax.y - m_vBoxMin.y) / m_nHeightmapSize);
  1696. int nX = CLAMP(int((x - m_vBoxMin.x) / dx), 0, m_nHeightmapSize - 1);
  1697. int nY = CLAMP(int((y - m_vBoxMin.y) / dy), 0, m_nHeightmapSize - 1);
  1698. return m_pHeightmap[nX * m_nHeightmapSize + nY];
  1699. }
  1700. #endif
  1701. //////////////////////////////////////////////////////////////////////////
  1702. int CStatObj::CountChildReferences() const
  1703. {
  1704. // Check if it must be released.
  1705. int nChildRefs = 0;
  1706. int numChilds = (int)m_subObjects.size();
  1707. for (int i = 0; i < numChilds; i++)
  1708. {
  1709. const IStatObj::SSubObject& so = m_subObjects[i];
  1710. CStatObj* pChildStatObj = (CStatObj*)so.pStatObj;
  1711. if (!pChildStatObj) // All stat objects must be at the begining of the array//
  1712. {
  1713. break;
  1714. }
  1715. // if I'm the real parent of this child, check that no-one else is referencing it, otherwise it doesn't matter if I get deleted
  1716. if (pChildStatObj->m_pParentObject == this)
  1717. {
  1718. bool bIgnoreSharedStatObj = false;
  1719. for (int k = 0; k < i; k++)
  1720. {
  1721. if (pChildStatObj == m_subObjects[k].pStatObj)
  1722. {
  1723. // If we share pointer to this stat obj then do not count it again.
  1724. bIgnoreSharedStatObj = true;
  1725. nChildRefs -= 1; // 1 reference from current object should be ignored.
  1726. break;
  1727. }
  1728. }
  1729. if (!bIgnoreSharedStatObj)
  1730. {
  1731. nChildRefs += pChildStatObj->m_nUsers - 1; // 1 reference from parent should be ignored.
  1732. }
  1733. }
  1734. }
  1735. assert(nChildRefs >= 0);
  1736. return nChildRefs;
  1737. }
  1738. IStatObj* CStatObj::GetLowestLod()
  1739. {
  1740. if (int nLowestLod = CStatObj::GetMinUsableLod())
  1741. {
  1742. return m_pLODs ? (CStatObj*)m_pLODs[CStatObj::GetMinUsableLod()] : (CStatObj*)NULL;
  1743. }
  1744. return this;
  1745. }
  1746. //////////////////////////////////////////////////////////////////////////
  1747. int CStatObj::FindHighestLOD(int nBias)
  1748. {
  1749. int nLowestLod = CStatObj::GetMinUsableLod();
  1750. // if requested lod is not ready - find nearest ready one
  1751. int nLod = CLAMP((int)m_nMaxUsableLod + nBias, nLowestLod, (int)m_nMaxUsableLod);
  1752. while (nLod && nLod >= nLowestLod && (!m_pLODs || !m_pLODs[nLod] || !m_pLODs[nLod]->GetRenderMesh()))
  1753. {
  1754. nLod--;
  1755. }
  1756. if (nLod == 0 && !GetRenderMesh())
  1757. {
  1758. nLod = -1;
  1759. }
  1760. return nLod;
  1761. }
  1762. //////////////////////////////////////////////////////////////////////////
  1763. void CStatObj::GetStatisticsNonRecursive(SStatistics& si)
  1764. {
  1765. CStatObj* pStatObj = this;
  1766. for (int lod = 0; lod < MAX_STATOBJ_LODS_NUM; lod++)
  1767. {
  1768. CStatObj* pLod = (CStatObj*)pStatObj->GetLodObject(lod);
  1769. if (pLod)
  1770. {
  1771. //if (!pLod0 && pLod->GetRenderMesh())
  1772. //pLod0 = pLod;
  1773. if (lod > 0 && lod + 1 > si.nLods) // Assign last existing lod.
  1774. {
  1775. si.nLods = lod + 1;
  1776. }
  1777. si.nVerticesPerLod[lod] += pLod->m_nLoadedVertexCount;
  1778. si.nIndicesPerLod[lod] += pLod->m_nLoadedTrisCount * 3;
  1779. si.nMeshSize += pLod->m_nRenderMeshMemoryUsage;
  1780. IRenderMesh* pRenderMesh = pLod->GetRenderMesh();
  1781. if (pRenderMesh)
  1782. {
  1783. si.nMeshSizeLoaded += pRenderMesh->GetMemoryUsage(0, IRenderMesh::MEM_USAGE_ONLY_STREAMS);
  1784. //if (si.pTextureSizer)
  1785. //pRenderMesh->GetTextureMemoryUsage(0,si.pTextureSizer);
  1786. //if (si.pTextureSizer2)
  1787. //pRenderMesh->GetTextureMemoryUsage(0,si.pTextureSizer2);
  1788. }
  1789. }
  1790. }
  1791. si.nIndices += m_nLoadedTrisCount * 3;
  1792. si.nVertices += m_nLoadedVertexCount;
  1793. for (int j = 0; j < pStatObj->m_arrPhysGeomInfo.GetGeomCount(); j++)
  1794. {
  1795. if (pStatObj->GetPhysGeom(j))
  1796. {
  1797. ICrySizer* pPhysSizer = GetISystem()->CreateSizer();
  1798. pStatObj->GetPhysGeom(j)->pGeom->GetMemoryStatistics(pPhysSizer);
  1799. int sz = pPhysSizer->GetTotalSize();
  1800. si.nPhysProxySize += sz;
  1801. si.nPhysProxySizeMax = max(si.nPhysProxySizeMax, sz);
  1802. si.nPhysPrimitives += pStatObj->GetPhysGeom(j)->pGeom->GetPrimitiveCount();
  1803. pPhysSizer->Release();
  1804. }
  1805. }
  1806. }
  1807. //////////////////////////////////////////////////////////////////////////
  1808. void CStatObj::GetStatistics(SStatistics& si)
  1809. {
  1810. si.bSplitLods = m_bLodsAreLoadedFromSeparateFile;
  1811. bool bMultiSubObj = (GetFlags() & STATIC_OBJECT_COMPOUND) != 0;
  1812. if (!bMultiSubObj)
  1813. {
  1814. GetStatisticsNonRecursive(si);
  1815. si.nSubMeshCount = 0;
  1816. si.nNumRefs = GetNumRefs();
  1817. si.nDrawCalls = m_nRenderMatIds;
  1818. }
  1819. else
  1820. {
  1821. si.nNumRefs = GetNumRefs();
  1822. std::vector<void*> addedObjects;
  1823. for (int k = 0; k < GetSubObjectCount(); k++)
  1824. {
  1825. if (!GetSubObject(k))
  1826. {
  1827. continue;
  1828. }
  1829. CStatObj* pSubObj = (CStatObj*)GetSubObject(k)->pStatObj;
  1830. int nSubObjectType = GetSubObject(k)->nType;
  1831. if (nSubObjectType != STATIC_SUB_OBJECT_MESH && nSubObjectType != STATIC_SUB_OBJECT_HELPER_MESH)
  1832. {
  1833. continue;
  1834. }
  1835. if (stl::find(addedObjects, pSubObj))
  1836. {
  1837. continue;
  1838. }
  1839. addedObjects.push_back(pSubObj);
  1840. if (pSubObj)
  1841. {
  1842. pSubObj->GetStatisticsNonRecursive(si);
  1843. si.nSubMeshCount++;
  1844. if (nSubObjectType == STATIC_SUB_OBJECT_MESH)
  1845. {
  1846. si.nDrawCalls += pSubObj->m_nRenderMatIds;
  1847. }
  1848. if (pSubObj->GetNumRefs() > si.nNumRefs)
  1849. {
  1850. si.nNumRefs = pSubObj->GetNumRefs();
  1851. }
  1852. }
  1853. }
  1854. }
  1855. // Only do rough estimation based on the material
  1856. // This is more consistent when streaming is enabled and render mesh may no exist
  1857. if (m_pMaterial)
  1858. {
  1859. if (si.pTextureSizer)
  1860. {
  1861. m_pMaterial->GetTextureMemoryUsage(si.pTextureSizer);
  1862. }
  1863. if (si.pTextureSizer2)
  1864. {
  1865. m_pMaterial->GetTextureMemoryUsage(si.pTextureSizer2);
  1866. }
  1867. }
  1868. }