BVB Source Codes

CRYENGINE Show RenderMeshMerger.cpp Source code

Return Download CRYENGINE: download RenderMeshMerger.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include "StatObj.h"
  6. #include "ObjMan.h"
  7. #include "MatMan.h"
  8. #include "VisAreas.h"
  9. #include "terrain_sector.h"
  10. #include "CCullThread.h"
  11. #include "3dEngine.h"
  12. #include "IndexedMesh.h"
  13. #include "Brush.h"
  14. #include "Vegetation.h"
  15. #include "terrain.h"
  16. #include "RenderMeshMerger.h"
  17. #include "MeshCompiler/MeshCompiler.h"
  18. #include <CryThreading/IJobManager_JobDelegator.h>
  19.  
  20. CRenderMeshMerger::CRenderMeshMerger()
  21. {
  22.         m_nTotalVertexCount = 0;
  23.         m_nTotalIndexCount = 0;
  24. }
  25.  
  26. CRenderMeshMerger::~CRenderMeshMerger()
  27. {
  28. }
  29.  
  30. int CRenderMeshMerger::Cmp_Materials(IMaterial* pMat1, IMaterial* pMat2)
  31. {
  32.         if (!pMat1 || !pMat2)
  33.                 return 0;
  34.  
  35.         SShaderItem& shaderItem1 = pMat1->GetShaderItem();
  36.         SShaderItem& shaderItem2 = pMat2->GetShaderItem();
  37.  
  38. #ifdef _DEBUG
  39.         const char* pName1 = shaderItem1.m_pShader->GetName();
  40.         const char* pName2 = shaderItem2.m_pShader->GetName();
  41. #endif
  42.  
  43.         // vert format
  44.         int nVertFormat1 = shaderItem1.m_pShader->GetVertexFormat();
  45.         int nVertFormat2 = shaderItem2.m_pShader->GetVertexFormat();
  46.  
  47.         if (nVertFormat1 > nVertFormat2)
  48.                 return 1;
  49.         if (nVertFormat1 < nVertFormat2)
  50.                 return -1;
  51.  
  52.         bool bDecal1 = (shaderItem1.m_pShader->GetFlags() & EF_DECAL) != 0;
  53.         bool bDecal2 = (shaderItem2.m_pShader->GetFlags() & EF_DECAL) != 0;
  54.  
  55.         // shader
  56.         if (bDecal1 > bDecal2)
  57.                 return 1;
  58.         if (bDecal1 < bDecal2)
  59.                 return -1;
  60.  
  61.         // shader resources
  62.         if (shaderItem1.m_pShaderResources > shaderItem2.m_pShaderResources)
  63.                 return 1;
  64.         if (shaderItem1.m_pShaderResources < shaderItem2.m_pShaderResources)
  65.                 return -1;
  66.  
  67.         // shader
  68.         if (shaderItem1.m_pShader > shaderItem2.m_pShader)
  69.                 return 1;
  70.         if (shaderItem1.m_pShader < shaderItem2.m_pShader)
  71.                 return -1;
  72.  
  73.         // compare mats ptr
  74.         if (pMat1 > pMat2)
  75.                 return 1;
  76.         if (pMat1 < pMat2)
  77.                 return -1;
  78.  
  79.         return 0;
  80. }
  81.  
  82. int CRenderMeshMerger::Cmp_RenderChunksInfo(const void* v1, const void* v2)
  83. {
  84.         SRenderMeshInfoInput* in1 = (SRenderMeshInfoInput*)v1;
  85.         SRenderMeshInfoInput* in2 = (SRenderMeshInfoInput*)v2;
  86.  
  87.         //assert(pChunk1->LMInfo.iRAETex == pChunk2->LMInfo.iRAETex);
  88.  
  89.         IMaterial* pMat1 = in1->pMat;
  90.         IMaterial* pMat2 = in2->pMat;
  91.  
  92.         return Cmp_Materials(pMat1, pMat2);
  93. }
  94.  
  95. int CRenderMeshMerger::Cmp_RenderChunks_(const void* v1, const void* v2)
  96. {
  97.         SMergedChunk* pChunk1 = (SMergedChunk*)v1;
  98.         SMergedChunk* pChunk2 = (SMergedChunk*)v2;
  99.  
  100.         if (pChunk1->rChunk.nSubObjectIndex < pChunk2->rChunk.nSubObjectIndex)
  101.                 return -1;
  102.         if (pChunk1->rChunk.nSubObjectIndex > pChunk2->rChunk.nSubObjectIndex)
  103.                 return 1;
  104.  
  105.         IMaterial* pMat1 = pChunk1->pMaterial;
  106.         IMaterial* pMat2 = pChunk2->pMaterial;
  107.  
  108.         return Cmp_Materials(pMat1, pMat2);
  109. }
  110.  
  111. void CRenderMeshMerger::IsChunkValid(CRenderChunk& Ch, PodArray<SVF_P3S_C4B_T2S>& m_lstVerts, PodArray<uint32>& m_lstIndices)
  112. {
  113. #ifdef _DEBUG
  114.         assert(Ch.nFirstIndexId + Ch.nNumIndices <= (uint32)m_lstIndices.Count());
  115.         assert(Ch.nFirstVertId + Ch.nNumVerts <= (uint16)m_lstVerts.Count());
  116.  
  117.         for (uint32 i = Ch.nFirstIndexId; i < Ch.nFirstIndexId + Ch.nNumIndices; i++)
  118.         {
  119.                 assert(m_lstIndices[i] >= Ch.nFirstVertId && m_lstIndices[i] < (uint32)(Ch.nFirstVertId + Ch.nNumVerts));
  120.                 assert(m_lstIndices[i] >= 0 && m_lstIndices[i] < (uint32)m_lstVerts.Count());
  121.         }
  122. #endif
  123. }
  124.  
  125. void CRenderMeshMerger::MakeRenderMeshInfoListOfAllChunks(SRenderMeshInfoInput* pRMIArray, int nRMICount, SMergeInfo& info)
  126. {
  127.         for (int nRmi = 0; nRmi < nRMICount; nRmi++)
  128.         {
  129.                 SRenderMeshInfoInput* pRMI = &pRMIArray[nRmi];
  130.                 IRenderMesh* pRM = pRMI->pMesh;
  131.  
  132.                 const TRenderChunkArray& chunks = pRM->GetChunks();
  133.                 int nChunkCount = chunks.size();
  134.                 for (int nChunk = 0; nChunk < nChunkCount; nChunk++)
  135.                 {
  136.                         const CRenderChunk& renderChunk = chunks[nChunk];
  137.  
  138.                         if (renderChunk.m_nMatFlags & MTL_FLAG_NODRAW || !renderChunk.pRE)
  139.                                 continue;
  140.  
  141.                         IMaterial* pCustMat;
  142.                         if (pRMI->pMat && renderChunk.m_nMatID < pRMI->pMat->GetSubMtlCount())
  143.                                 pCustMat = pRMI->pMat->GetSubMtl(renderChunk.m_nMatID);
  144.                         else
  145.                                 pCustMat = pRMI->pMat;
  146.  
  147.                         if (!pCustMat)
  148.                                 continue;
  149.                         if (!pCustMat->GetShaderItem().m_pShader)
  150.                                 pCustMat = GetMatMan()->GetDefaultMaterial();
  151.  
  152.                         IShader* pShader = pCustMat->GetShaderItem().m_pShader;
  153.  
  154.                         if (!pShader)
  155.                                 continue;
  156.                         if (pShader->GetFlags() & EF_NODRAW)
  157.                                 continue;
  158.  
  159.                         if (info.pDecalClipInfo)
  160.                                 if (pShader->GetFlags() & EF_DECAL)
  161.                                         continue;
  162.  
  163.                         SRenderMeshInfoInput RMIChunk = *pRMI;
  164.                         RMIChunk.pMat = info.pDecalClipInfo ? NULL : pCustMat;
  165.                         RMIChunk.nChunkId = nChunk;
  166.  
  167.                         m_lstRMIChunks.Add(RMIChunk);
  168.                 }
  169.         }
  170. }
  171.  
  172. void CRenderMeshMerger::MakeListOfAllCRenderChunks(SMergeInfo& info)
  173. {
  174.         FUNCTION_PROFILER_3DENGINE;
  175.  
  176.         m_nTotalVertexCount = 0;
  177.         m_nTotalIndexCount = 0;
  178.  
  179.         for (int nEntityId = 0; nEntityId < m_lstRMIChunks.Count(); nEntityId++)
  180.         {
  181.                 SRenderMeshInfoInput* pRMI = &m_lstRMIChunks[nEntityId];
  182.  
  183.                 bool bMatrixHasRotation;
  184.                 if (!pRMI->mat.m01 && !pRMI->mat.m02 && !pRMI->mat.m10 && !pRMI->mat.m12 && !pRMI->mat.m20 && !pRMI->mat.m21)
  185.                         bMatrixHasRotation = false;
  186.                 else
  187.                         bMatrixHasRotation = true;
  188.  
  189.                 Matrix34 matInv = pRMI->mat.GetInverted();
  190.  
  191.                 IRenderMesh* pRM = pRMI->pMesh;
  192.                 if (!pRM->GetVerticesCount())
  193.                         continue;
  194.  
  195.                 int nInitVertCout = m_lstVerts.Count();
  196.  
  197.                 int nPosStride = 0;
  198.                 int nTexStride = 0;
  199.                 int nColorStride = 0;
  200.                 Vec3* pPos = 0;
  201.                 Vec2* pTex = 0;
  202.                 UCol* pColor = 0;
  203.  
  204.                 // get vertices's
  205.                 {
  206.                         FRAME_PROFILER("CRenderMeshMerger::MakeListOfAllCRenderChunks_GetPosPtr", GetSystem(), PROFILE_3DENGINE);
  207.  
  208.                         pPos = reinterpret_cast<Vec3*>(pRM->GetPosPtr(nPosStride, FSL_READ));
  209.                         pTex = reinterpret_cast<Vec2*>(pRM->GetUVPtr(nTexStride, FSL_READ));
  210.                         pColor = reinterpret_cast<UCol*>(pRM->GetColorPtr(nColorStride, FSL_READ));
  211.                 }
  212.  
  213.                 if (!pPos || !pTex || !pColor)
  214.                         continue;
  215.  
  216.                 // get tangent basis
  217.                 int nNormStride = 0;
  218.                 int nTangsStride = 0;
  219.                 byte* pNorm = 0;
  220.                 byte* pTangs = 0;
  221.  
  222.                 if (pRM->GetVertexFormat() != eVF_P3S_N4B_C4B_T2S)
  223.                 {
  224.                         pTangs = pRM->GetTangentPtr(nTangsStride, FSL_READ);
  225.                 }
  226.  
  227. #if ENABLE_NORMALSTREAM_SUPPORT
  228.                 // get normal stream
  229.                 {
  230.                         pNorm = pRM->GetNormPtr(nNormStride, FSL_READ);
  231.                 }
  232. #endif
  233.  
  234.                 Vec3 vMin, vMax;
  235.                 pRM->GetBBox(vMin, vMax);
  236.  
  237.                 // get indices
  238.                 uint32 nIndCount = pRM->GetIndicesCount();
  239.                 vtx_idx* pSrcInds = pRM->GetIndexPtr(FSL_READ);
  240.  
  241.                 Vec3 vOSPos(0, 0, 0);
  242.                 Vec3 vOSProjDir(0, 0, 0);
  243.                 float fMatrixScale = 1.f;
  244.                 float fOSRadius = 0.f;
  245.  
  246.                 if (info.pDecalClipInfo && info.pDecalClipInfo->fRadius)
  247.                 {
  248.                         vOSPos = matInv.TransformPoint(info.pDecalClipInfo->vPos);
  249.                         vOSProjDir = matInv.TransformVector(info.pDecalClipInfo->vProjDir);
  250.                         fMatrixScale = vOSProjDir.GetLength();
  251.                         fOSRadius = info.pDecalClipInfo->fRadius * fMatrixScale;
  252.                         if (vOSProjDir.GetLength() > 0.01f)
  253.                                 vOSProjDir.Normalize();
  254.                 }
  255.  
  256.                 CRenderChunk newMatInfo = pRM->GetChunks()[pRMI->nChunkId];
  257.  
  258. #ifdef _DEBUG
  259.                 CRenderChunk Ch = newMatInfo;
  260.                 for (uint32 i = Ch.nFirstIndexId; i < Ch.nFirstIndexId + Ch.nNumIndices; i++)
  261.                 {
  262.                         assert(i >= 0 && i < nIndCount);
  263.                         assert(pSrcInds[i] >= Ch.nFirstVertId && pSrcInds[i] < Ch.nFirstVertId + Ch.nNumVerts);
  264.                         assert((int)pSrcInds[i] < pRM->GetVerticesCount());
  265.                 }
  266. #endif
  267.  
  268.                 int nFirstIndexId = m_lstIndices.Count();
  269.  
  270.                 // add indices
  271.                 for (uint32 i = newMatInfo.nFirstIndexId; i < newMatInfo.nFirstIndexId + newMatInfo.nNumIndices; i += 3)
  272.                 {
  273.                         assert((int)pSrcInds[i + 0] < pRM->GetVerticesCount());
  274.                         assert((int)pSrcInds[i + 1] < pRM->GetVerticesCount());
  275.                         assert((int)pSrcInds[i + 2] < pRM->GetVerticesCount());
  276.  
  277.                         assert((int)pSrcInds[i + 0] >= newMatInfo.nFirstVertId && pSrcInds[i + 0] < newMatInfo.nFirstVertId + newMatInfo.nNumVerts);
  278.                         assert((int)pSrcInds[i + 1] >= newMatInfo.nFirstVertId && pSrcInds[i + 1] < newMatInfo.nFirstVertId + newMatInfo.nNumVerts);
  279.                         assert((int)pSrcInds[i + 2] >= newMatInfo.nFirstVertId && pSrcInds[i + 2] < newMatInfo.nFirstVertId + newMatInfo.nNumVerts);
  280.  
  281.                         // skip not needed triangles for decals
  282.                         if (fOSRadius)
  283.                         {
  284.                                 // get verts
  285.                                 Vec3 v0 = pPos[nPosStride * pSrcInds[i + 0]];
  286.                                 Vec3 v1 = pPos[nPosStride * pSrcInds[i + 1]];
  287.                                 Vec3 v2 = pPos[nPosStride * pSrcInds[i + 2]];
  288.  
  289.                                 if (vOSProjDir.IsZero())
  290.                                 {
  291.                                         // explosion mode
  292.                                         // test the face
  293.                                         float fDot0 = (vOSPos - v0).Dot((v1 - v0).Cross(v2 - v0));
  294.                                         float fTest = -0.15f;
  295.                                         if (fDot0 < fTest)
  296.                                                 continue;
  297.                                 }
  298.                                 else
  299.                                 {
  300.                                         // get triangle normal
  301.                                         Vec3 vNormal = (v1 - v0).Cross(v2 - v0);
  302.  
  303.                                         // test the face
  304.                                         if (vNormal.Dot(vOSProjDir) <= 0)
  305.                                                 continue;
  306.                                 }
  307.  
  308.                                 // get bbox
  309.                                 AABB triBox;
  310.                                 triBox.min = v0;
  311.                                 triBox.min.CheckMin(v1);
  312.                                 triBox.min.CheckMin(v2);
  313.                                 triBox.max = v0;
  314.                                 triBox.max.CheckMax(v1);
  315.                                 triBox.max.CheckMax(v2);
  316.  
  317.                                 if (!Overlap::Sphere_AABB(Sphere(vOSPos, fOSRadius), triBox))
  318.                                         continue;
  319.                         }
  320.                         else if (info.pClipCellBox)
  321.                         {
  322.                                 // get verts
  323.                                 Vec3 v0 = pRMI->mat.TransformPoint(pPos[nPosStride * pSrcInds[i + 0]]);
  324.                                 Vec3 v1 = pRMI->mat.TransformPoint(pPos[nPosStride * pSrcInds[i + 1]]);
  325.                                 Vec3 v2 = pRMI->mat.TransformPoint(pPos[nPosStride * pSrcInds[i + 2]]);
  326.  
  327.                                 if (!Overlap::AABB_Triangle(*info.pClipCellBox, v0, v1, v2))
  328.                                         continue;
  329.                         }
  330.  
  331.                         m_lstIndices.Add((int)(pSrcInds[i + 0]) - newMatInfo.nFirstVertId + nInitVertCout);
  332.                         m_lstIndices.Add((int)(pSrcInds[i + 1]) - newMatInfo.nFirstVertId + nInitVertCout);
  333.                         m_lstIndices.Add((int)(pSrcInds[i + 2]) - newMatInfo.nFirstVertId + nInitVertCout);
  334.                 }
  335.  
  336.                 newMatInfo.nFirstIndexId = nFirstIndexId;
  337.                 newMatInfo.nNumIndices = m_lstIndices.Count() - nFirstIndexId;
  338.  
  339.                 if (!newMatInfo.nNumIndices)
  340.                         continue;
  341.  
  342.                 // add vertices
  343.                 for (int v = newMatInfo.nFirstVertId; v < (int)newMatInfo.nFirstVertId + (int)newMatInfo.nNumVerts; v++)
  344.                 {
  345.                         assert(v >= 0 && v < pRM->GetVerticesCount());
  346.  
  347.                         SVF_P3S_C4B_T2S vert;
  348.  
  349.                         // set pos
  350.                         Vec3 vPos = pPos[nPosStride * v];
  351.                         vPos = pRMI->mat.TransformPoint(vPos);
  352.                         vert.xyz = vPos - info.vResultOffset;
  353.  
  354.                         // set uv
  355.                         if (pTex)
  356.                         {
  357.                                 vert.st = pTex[nTexStride * v];
  358.                         }
  359.                         else
  360.                         {
  361.                                 vert.st = Vec2f16(0, 0);
  362.                         }
  363.  
  364.                         vert.color = pColor[nColorStride * v + 0];
  365.  
  366.                         m_lstVerts.Add(vert);
  367.  
  368.                         // get tangent basis + normal
  369.                         SPipTangents basis = SPipTangents(Vec4sf(0, 0, 0, 0), Vec4sf(0, 0, 0, 0));
  370.                         SPipNormal normal = SPipNormal(Vec3(0, 0, 0));
  371.  
  372.                         assert((pTangs) || (!pNorm));
  373.                         if (pTangs)
  374.                         {
  375.                                 basis = *(SPipTangents*)&pTangs[nTangsStride * v];
  376. #if ENABLE_NORMALSTREAM_SUPPORT
  377.                                 if (pNorm)
  378.                                 {
  379.                                         normal = *(SPipNormal*)&pNorm[nNormStride * v];
  380.                                 }
  381. #endif
  382.  
  383.                                 if (bMatrixHasRotation)
  384.                                 {
  385.                                         basis.TransformSafelyBy(pRMI->mat);
  386. #if ENABLE_NORMALSTREAM_SUPPORT
  387.                                         if (pNorm)
  388.                                                 normal.TransformSafelyBy(pRMI->mat);
  389. #endif
  390.                                 }
  391.                         }
  392.  
  393.                         m_lstTangBasises.Add(basis);
  394. #if ENABLE_NORMALSTREAM_SUPPORT
  395.                         m_lstNormals.Add(normal);
  396. #endif
  397.                 }
  398.  
  399.                 // set vert range
  400.                 newMatInfo.nFirstVertId = m_lstVerts.Count() - newMatInfo.nNumVerts;
  401.                 newMatInfo.pRE = NULL;
  402.  
  403.                 //              assert(IsHeapValid());
  404.                 //              IsChunkValid(newMatInfo, m_lstVerts, m_lstIndices);
  405.  
  406.                 if (m_lstChunks.Count())
  407.                         assert(m_lstChunks.Last().rChunk.nFirstVertId + m_lstChunks.Last().rChunk.nNumVerts == newMatInfo.nFirstVertId);
  408.  
  409.                 if (newMatInfo.nNumIndices)
  410.                 {
  411.                         SMergedChunk mrgChunk;
  412.                         mrgChunk.rChunk = newMatInfo;
  413.                         mrgChunk.rChunk.nSubObjectIndex = pRMI->nSubObjectIndex;
  414.                         mrgChunk.pMaterial = info.pDecalClipInfo ? NULL : pRMI->pMat.get();
  415.                         if (pRMI->pMat)
  416.                                 mrgChunk.rChunk.m_nMatFlags = pRMI->pMat->GetFlags();
  417.                         m_lstChunks.Add(mrgChunk);
  418.                 }
  419.  
  420.                 m_nTotalVertexCount += newMatInfo.nNumVerts;
  421.                 m_nTotalIndexCount += newMatInfo.nNumIndices;
  422.         }
  423. }
  424.  
  425. //////////////////////////////////////////////////////////////////////////
  426. void CRenderMeshMerger::CompactVertices(SMergeInfo& info)
  427. {
  428.         if (info.bPrintDebugMessages)
  429.                 PrintMessage("Removing unused vertices");
  430.  
  431.         PodArray<uint32> lstVertUsage;
  432.         lstVertUsage.PreAllocate(m_lstVerts.Count(), m_lstVerts.Count());
  433.         for (int i = 0; i < m_lstIndices.Count(); i++)
  434.                 lstVertUsage[m_lstIndices[i]] = 1;
  435.  
  436.         PodArray<SVF_P3S_C4B_T2S> lstVertsOptimized;
  437.         lstVertsOptimized.PreAllocate(m_lstVerts.Count());
  438.         PodArray<SPipTangents> lstTangBasisesOptimized;
  439.         lstTangBasisesOptimized.PreAllocate(m_lstVerts.Count());
  440. #if ENABLE_NORMALSTREAM_SUPPORT
  441.         PodArray<SPipNormal> lstNormalsOptimized;
  442.         lstNormalsOptimized.PreAllocate(m_lstVerts.Count());
  443. #endif
  444.  
  445.         int nCurChunkId = 0;
  446.         CRenderChunk* pChBack = &m_lstChunks[0].rChunk;
  447.         int nVertsRemoved = 0;
  448.         PodArray<SMergedChunk> lstChunksBk;
  449.         lstChunksBk.AddList(m_lstChunks);
  450.         for (int i = 0; i < m_lstVerts.Count(); )
  451.         {
  452.                 if (lstVertUsage[i])
  453.                 {
  454.                         lstVertsOptimized.Add(m_lstVerts[i]);
  455.                         lstTangBasisesOptimized.Add(m_lstTangBasises[i]);
  456. #if ENABLE_NORMALSTREAM_SUPPORT
  457.                         lstNormalsOptimized.Add(m_lstNormals[i]);
  458. #endif
  459.                 }
  460.                 else
  461.                         nVertsRemoved++;
  462.  
  463.                 lstVertUsage[i] = lstVertsOptimized.Count() - 1;
  464.  
  465.                 i++;
  466.  
  467.                 if (i >= (int)lstChunksBk[nCurChunkId].rChunk.nFirstVertId + (int)lstChunksBk[nCurChunkId].rChunk.nNumVerts)
  468.                 {
  469.                         if (nVertsRemoved)
  470.                         {
  471.                                 pChBack->nNumVerts -= nVertsRemoved;
  472.  
  473.                                 for (int nId = nCurChunkId + 1; nId < m_lstChunks.Count(); nId++)
  474.                                 {
  475.                                         CRenderChunk& ChBack = m_lstChunks[nId].rChunk;
  476.                                         ChBack.nFirstVertId -= nVertsRemoved;
  477.                                 }
  478.  
  479.                                 nVertsRemoved = 0;
  480.                         }
  481.  
  482.                         nCurChunkId++;
  483.                         if (nCurChunkId < m_lstChunks.Count())
  484.                                 pChBack = &m_lstChunks[nCurChunkId].rChunk;
  485.                         else
  486.                                 break;
  487.                 }
  488.         }
  489.  
  490.         for (int i = 0; i < m_lstIndices.Count(); i++)
  491.                 m_lstIndices[i] = lstVertUsage[m_lstIndices[i]];
  492.  
  493.         int nOldVertsNum = m_lstVerts.Count();
  494.  
  495.         m_lstVerts = lstVertsOptimized;
  496.         m_lstTangBasises = lstTangBasisesOptimized;
  497. #if ENABLE_NORMALSTREAM_SUPPORT
  498.         m_lstNormals = lstNormalsOptimized;
  499. #endif
  500.  
  501.         if (info.bPrintDebugMessages)
  502.                 PrintMessage("old->new = %d->%d vertices", nOldVertsNum, m_lstVerts.Count());
  503.  
  504.         int nBadTrisCount = 0;
  505.         for (int i = 0; i < m_lstIndices.Count(); i += 3)
  506.         {
  507.                 if (m_lstIndices[i + 0] == m_lstIndices[i + 1] ||
  508.                     m_lstIndices[i + 1] == m_lstIndices[i + 2] ||
  509.                     m_lstIndices[i + 2] == m_lstIndices[i + 0])
  510.                 {
  511.                         nBadTrisCount++;
  512.                 }
  513.         }
  514.  
  515.         if (nBadTrisCount)
  516.                 PrintMessage("CRenderMeshMerger::CompactVertices: Warning: %d bad tris found", nBadTrisCount);
  517. }
  518.  
  519. //////////////////////////////////////////////////////////////////////////
  520. void CRenderMeshMerger::ClipByAABB(SMergeInfo& info)
  521. {
  522.         if (info.bPrintDebugMessages)
  523.                 PrintMessage("  Do clipping . . ." /*, m_lstChunks.Count()*/);
  524.  
  525.         {
  526.                 // minimize range
  527.                 uint32 nMin = ~0;
  528.                 uint32 nMax = 0;
  529.  
  530.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  531.                 {
  532.                         if (nMin > m_lstIndices[i]) nMin = m_lstIndices[i];
  533.                         if (nMax < m_lstIndices[i]) nMax = m_lstIndices[i];
  534.                 }
  535.  
  536.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  537.                         m_lstIndices[i] -= nMin;
  538.  
  539.                 if (m_lstVerts.Count() - nMax - 1 > 0)
  540.                 {
  541.                         m_lstVerts.Delete(nMax + 1, m_lstVerts.Count() - (nMax + 1));
  542.                         m_lstTangBasises.Delete(nMax + 1, m_lstTangBasises.Count() - (nMax + 1));
  543. #if ENABLE_NORMALSTREAM_SUPPORT
  544.                         m_lstNormals.Delete(nMax + 1, m_lstNormals.Count() - (nMax + 1));
  545. #endif
  546.                 }
  547.  
  548.                 m_lstVerts.Delete(0, nMin);
  549.                 m_lstTangBasises.Delete(0, nMin);
  550. #if ENABLE_NORMALSTREAM_SUPPORT
  551.                 m_lstNormals.Delete(0, nMin);
  552. #endif
  553.         }
  554.  
  555.         // define clip planes
  556.         Plane planes[6];
  557.         float fClipRadius = info.pDecalClipInfo->fRadius * 1.3f;
  558.         planes[0].SetPlane(Vec3(0, 0, 1), info.pDecalClipInfo->vPos + Vec3(0, 0, fClipRadius));
  559.         planes[1].SetPlane(Vec3(0, 0, -1), info.pDecalClipInfo->vPos + Vec3(0, 0, -fClipRadius));
  560.         planes[2].SetPlane(Vec3(0, 1, 0), info.pDecalClipInfo->vPos + Vec3(0, fClipRadius, 0));
  561.         planes[3].SetPlane(Vec3(0, -1, 0), info.pDecalClipInfo->vPos + Vec3(0, -fClipRadius, 0));
  562.         planes[4].SetPlane(Vec3(1, 0, 0), info.pDecalClipInfo->vPos + Vec3(fClipRadius, 0, 0));
  563.         planes[5].SetPlane(Vec3(-1, 0, 0), info.pDecalClipInfo->vPos + Vec3(-fClipRadius, 0, 0));
  564.  
  565.         // clip triangles
  566.         int nOrigCount = m_lstIndices.Count();
  567.         for (int i = 0; i < nOrigCount; i += 3)
  568.         {
  569.                 if (ClipTriangle(i, planes, 6))
  570.                 {
  571.                         i -= 3;
  572.                         nOrigCount -= 3;
  573.                 }
  574.         }
  575.  
  576.         if (m_lstIndices.Count() < 3 || m_lstVerts.Count() < 3)
  577.                 return;
  578.  
  579.         assert(m_lstTangBasises.Count() == m_lstVerts.Count());
  580. #if ENABLE_NORMALSTREAM_SUPPORT
  581.         assert(m_lstNormals.Count() == m_lstVerts.Count());
  582. #endif
  583.  
  584.         {
  585.                 // minimize range
  586.                 uint32 nMin = ~0;
  587.                 uint32 nMax = 0;
  588.  
  589.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  590.                 {
  591.                         if (nMin > m_lstIndices[i]) nMin = m_lstIndices[i];
  592.                         if (nMax < m_lstIndices[i]) nMax = m_lstIndices[i];
  593.                 }
  594.  
  595.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  596.                         m_lstIndices[i] -= nMin;
  597.  
  598.                 if (m_lstVerts.Count() - nMax - 1 > 0)
  599.                 {
  600.                         m_lstVerts.Delete(nMax + 1, m_lstVerts.Count() - (nMax + 1));
  601.                         m_lstTangBasises.Delete(nMax + 1, m_lstTangBasises.Count() - (nMax + 1));
  602. #if ENABLE_NORMALSTREAM_SUPPORT
  603.                         m_lstNormals.Delete(nMax + 1, m_lstNormals.Count() - (nMax + 1));
  604. #endif
  605.                 }
  606.  
  607.                 m_lstVerts.Delete(0, nMin);
  608.                 m_lstTangBasises.Delete(0, nMin);
  609. #if ENABLE_NORMALSTREAM_SUPPORT
  610.                 m_lstNormals.Delete(0, nMin);
  611. #endif
  612.         }
  613.  
  614. #ifdef _DEBUG
  615.         assert(m_lstTangBasises.Count() == m_lstVerts.Count());
  616.         #if ENABLE_NORMALSTREAM_SUPPORT
  617.         assert(m_lstNormals.Count() == m_lstVerts.Count());
  618.         #endif
  619.         for (int i = 0; i < m_lstIndices.Count(); i++)
  620.                 assert(m_lstIndices[i] >= 0 && m_lstIndices[i] < (uint32)m_lstVerts.Count());
  621. #endif
  622.  
  623.         if (m_lstIndices.Count() < 3 || m_lstVerts.Count() < 3)
  624.                 return;
  625.  
  626.         m_lstChunks[0].rChunk.nNumIndices = m_lstIndices.Count();
  627.         m_lstChunks[0].rChunk.nNumVerts = m_lstVerts.Count();
  628. }
  629.  
  630. //////////////////////////////////////////////////////////////////////////
  631. bool CRenderMeshMerger::ClipTriangle(int nStartIdxId, Plane* pPlanes, int nPlanesNum)
  632. {
  633.         const PodArray<Vec3>& clipped = m_tmpClipContext.Clip(
  634.           m_lstVerts[m_lstIndices[nStartIdxId + 0]].xyz.ToVec3(),
  635.           m_lstVerts[m_lstIndices[nStartIdxId + 1]].xyz.ToVec3(),
  636.           m_lstVerts[m_lstIndices[nStartIdxId + 2]].xyz.ToVec3(),
  637.           pPlanes, nPlanesNum);
  638.  
  639.         if (clipped.Count() < 3)
  640.         {
  641.                 m_lstIndices.Delete(nStartIdxId, 3);
  642.                 return true; // entire triangle is clipped away
  643.         }
  644.  
  645.         if (clipped.Count() == 3)
  646.                 if (clipped[0].IsEquivalent(m_lstVerts[m_lstIndices[nStartIdxId + 0]].xyz.ToVec3()))
  647.                         if (clipped[1].IsEquivalent(m_lstVerts[m_lstIndices[nStartIdxId + 1]].xyz.ToVec3()))
  648.                                 if (clipped[2].IsEquivalent(m_lstVerts[m_lstIndices[nStartIdxId + 2]].xyz.ToVec3()))
  649.                                         return false;
  650.         // entire triangle is in
  651.  
  652.         // replace old triangle with several new triangles
  653.         int nStartId = m_lstVerts.Count();
  654.         int nStartIndex = m_lstIndices[nStartIdxId + 0];
  655.         SVF_P3S_C4B_T2S fullVert = m_lstVerts[nStartIndex];
  656.         SPipTangents fullTang = m_lstTangBasises[nStartIndex];
  657. #if ENABLE_NORMALSTREAM_SUPPORT
  658.         SPipNormal fullNorm = m_lstNormals[nStartIndex];
  659. #endif
  660.  
  661.         for (int i = 0; i < clipped.Count(); i++)
  662.         {
  663.                 fullVert.xyz = clipped[i];
  664.                 m_lstVerts.Add(fullVert);
  665.                 m_lstTangBasises.Add(fullTang);
  666. #if ENABLE_NORMALSTREAM_SUPPORT
  667.                 m_lstNormals.Add(fullNorm);
  668. #endif
  669.         }
  670.  
  671.         // put first new triangle into position of original one
  672.         m_lstIndices[nStartIdxId + 0] = nStartId + 0;
  673.         m_lstIndices[nStartIdxId + 1] = nStartId + 1;
  674.         m_lstIndices[nStartIdxId + 2] = nStartId + 2;
  675.  
  676.         // put others in the end
  677.         for (int i = 1; i < clipped.Count() - 2; i++)
  678.         {
  679.                 m_lstIndices.Add(nStartId + 0);
  680.                 m_lstIndices.Add(nStartId + i + 1);
  681.                 m_lstIndices.Add(nStartId + i + 2);
  682.         }
  683.  
  684.         return false;
  685. }
  686.  
  687. //////////////////////////////////////////////////////////////////////////
  688. void CRenderMeshMerger::ClipDecals(SMergeInfo& info)
  689. {
  690.         if (info.bPrintDebugMessages)
  691.                 PrintMessage("  Do clipping . . ." /*, m_lstChunks.Count()*/);
  692.  
  693.         {
  694.                 // minimize range
  695.                 uint32 nMin = ~0;
  696.                 uint32 nMax = 0;
  697.  
  698.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  699.                 {
  700.                         if (nMin > m_lstIndices[i]) nMin = m_lstIndices[i];
  701.                         if (nMax < m_lstIndices[i]) nMax = m_lstIndices[i];
  702.                 }
  703.  
  704.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  705.                         m_lstIndices[i] -= nMin;
  706.  
  707.                 if (m_lstVerts.Count() - nMax - 1 > 0)
  708.                 {
  709.                         m_lstVerts.Delete(nMax + 1, m_lstVerts.Count() - (nMax + 1));
  710.                         m_lstTangBasises.Delete(nMax + 1, m_lstTangBasises.Count() - (nMax + 1));
  711. #if ENABLE_NORMALSTREAM_SUPPORT
  712.                         m_lstNormals.Delete(nMax + 1, m_lstNormals.Count() - (nMax + 1));
  713. #endif
  714.                 }
  715.  
  716.                 m_lstVerts.Delete(0, nMin);
  717.                 m_lstTangBasises.Delete(0, nMin);
  718. #if ENABLE_NORMALSTREAM_SUPPORT
  719.                 m_lstNormals.Delete(0, nMin);
  720. #endif
  721.         }
  722.  
  723.         // define clip planes
  724.         Plane planes[6];
  725.         float fClipRadius = info.pDecalClipInfo->fRadius * 1.3f;
  726.         planes[0].SetPlane(Vec3(0, 0, 1), info.pDecalClipInfo->vPos - info.vResultOffset + Vec3(0, 0, fClipRadius));
  727.         planes[1].SetPlane(Vec3(0, 0, -1), info.pDecalClipInfo->vPos - info.vResultOffset + Vec3(0, 0, -fClipRadius));
  728.         planes[2].SetPlane(Vec3(0, 1, 0), info.pDecalClipInfo->vPos - info.vResultOffset + Vec3(0, fClipRadius, 0));
  729.         planes[3].SetPlane(Vec3(0, -1, 0), info.pDecalClipInfo->vPos - info.vResultOffset + Vec3(0, -fClipRadius, 0));
  730.         planes[4].SetPlane(Vec3(1, 0, 0), info.pDecalClipInfo->vPos - info.vResultOffset + Vec3(fClipRadius, 0, 0));
  731.         planes[5].SetPlane(Vec3(-1, 0, 0), info.pDecalClipInfo->vPos - info.vResultOffset + Vec3(-fClipRadius, 0, 0));
  732.  
  733.         // clip triangles
  734.         int nOrigCount = m_lstIndices.Count();
  735.         for (int i = 0; i < nOrigCount; i += 3)
  736.         {
  737.                 if (ClipTriangle(i, planes, 6))
  738.                 {
  739.                         i -= 3;
  740.                         nOrigCount -= 3;
  741.                 }
  742.         }
  743.  
  744.         if (m_lstIndices.Count() < 3 || m_lstVerts.Count() < 3)
  745.                 return;
  746.  
  747.         assert(m_lstTangBasises.Count() == m_lstVerts.Count());
  748. #if ENABLE_NORMALSTREAM_SUPPORT
  749.         assert(m_lstNormals.Count() == m_lstVerts.Count());
  750. #endif
  751.  
  752.         {
  753.                 // minimize range
  754.                 uint32 nMin = ~0;
  755.                 uint32 nMax = 0;
  756.  
  757.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  758.                 {
  759.                         if (nMin > m_lstIndices[i]) nMin = m_lstIndices[i];
  760.                         if (nMax < m_lstIndices[i]) nMax = m_lstIndices[i];
  761.                 }
  762.  
  763.                 for (int i = 0; i < m_lstIndices.Count(); i++)
  764.                         m_lstIndices[i] -= nMin;
  765.  
  766.                 if (m_lstVerts.Count() - nMax - 1 > 0)
  767.                 {
  768.                         m_lstVerts.Delete(nMax + 1, m_lstVerts.Count() - (nMax + 1));
  769.                         m_lstTangBasises.Delete(nMax + 1, m_lstTangBasises.Count() - (nMax + 1));
  770. #if ENABLE_NORMALSTREAM_SUPPORT
  771.                         m_lstNormals.Delete(nMax + 1, m_lstNormals.Count() - (nMax + 1));
  772. #endif
  773.                 }
  774.  
  775.                 m_lstVerts.Delete(0, nMin);
  776.                 m_lstTangBasises.Delete(0, nMin);
  777. #if ENABLE_NORMALSTREAM_SUPPORT
  778.                 m_lstNormals.Delete(0, nMin);
  779. #endif
  780.         }
  781.  
  782. #ifdef _DEBUG
  783.         assert(m_lstTangBasises.Count() == m_lstVerts.Count());
  784.         #if ENABLE_NORMALSTREAM_SUPPORT
  785.         assert(m_lstNormals.Count() == m_lstVerts.Count());
  786.         #endif
  787.         for (int i = 0; i < m_lstIndices.Count(); i++)
  788.                 assert(m_lstIndices[i] >= 0 && m_lstIndices[i] < (uint32)m_lstVerts.Count());
  789. #endif
  790.  
  791.         if (m_lstIndices.Count() < 3 || m_lstVerts.Count() < 3)
  792.                 return;
  793.  
  794.         m_lstChunks[0].rChunk.nNumIndices = m_lstIndices.Count();
  795.         m_lstChunks[0].rChunk.nNumVerts = m_lstVerts.Count();
  796. }
  797.  
  798. //////////////////////////////////////////////////////////////////////////
  799. void CRenderMeshMerger::TryMergingChunks(SMergeInfo& info)
  800. {
  801.         PodArray<SMergedChunk>& lstChunksMerged = m_lstChunksMergedTemp;
  802.         lstChunksMerged.clear();
  803.         lstChunksMerged.reserve(m_lstChunks.size());
  804.  
  805.         int nCurrVertFormat = -1;
  806.         for (int nChunkId = 0; nChunkId < m_lstChunks.Count(); nChunkId++)
  807.         {
  808.                 SMergedChunk& mergChunk = m_lstChunks[nChunkId];
  809.  
  810.                 //              IsChunkValid(mergChunk, m_lstVerts, m_lstIndices);
  811.  
  812.                 int nChunkVertFormat;
  813.                 if (info.pDecalClipInfo || info.bMergeToOneRenderMesh)
  814.                         nChunkVertFormat = -1;
  815.                 else
  816.                 {
  817.                         IMaterial* pMat = mergChunk.pMaterial;
  818.                         SShaderItem& shaderItem = pMat->GetShaderItem();
  819.                         nChunkVertFormat = shaderItem.m_pShader->GetVertexFormat();
  820.                 }
  821.  
  822.                 if (info.bMergeToOneRenderMesh)
  823.                 {
  824.                         nChunkVertFormat = nCurrVertFormat;
  825.                 }
  826.  
  827.                 if (!nChunkId ||
  828.                     (nChunkVertFormat != nCurrVertFormat || Cmp_RenderChunks_(&mergChunk, &m_lstChunks[nChunkId - 1]) ||
  829.                      (lstChunksMerged.Last().rChunk.nNumVerts + mergChunk.rChunk.nNumVerts) > 0xFFFF))
  830.                 {
  831.                         // not equal materials - add new chunk
  832.                         lstChunksMerged.Add(mergChunk);
  833.                 }
  834.                 else
  835.                 {
  836.                         float texelAreaDensity = 0.0f;
  837.                         int totalIndices = 0;
  838.  
  839.                         if (lstChunksMerged.Last().rChunk.m_texelAreaDensity != (float)UINT_MAX)
  840.                         {
  841.                                 texelAreaDensity += lstChunksMerged.Last().rChunk.nNumIndices * lstChunksMerged.Last().rChunk.m_texelAreaDensity;
  842.                                 totalIndices += lstChunksMerged.Last().rChunk.nNumIndices;
  843.                         }
  844.  
  845.                         if (mergChunk.rChunk.m_texelAreaDensity != (float)UINT_MAX)
  846.                         {
  847.                                 texelAreaDensity += mergChunk.rChunk.nNumIndices * mergChunk.rChunk.m_texelAreaDensity;
  848.                                 totalIndices += mergChunk.rChunk.nNumIndices;
  849.                         }
  850.  
  851.                         if (totalIndices != 0)
  852.                         {
  853.                                 lstChunksMerged.Last().rChunk.m_texelAreaDensity = texelAreaDensity / totalIndices;
  854.                         }
  855.  
  856.                         lstChunksMerged.Last().rChunk.nNumIndices += mergChunk.rChunk.nNumIndices;
  857.                         lstChunksMerged.Last().rChunk.nNumVerts += mergChunk.rChunk.nNumVerts;
  858.                 }
  859.  
  860.                 IsChunkValid(lstChunksMerged.Last().rChunk, m_lstVerts, m_lstIndices);
  861.  
  862.                 nCurrVertFormat = nChunkVertFormat;
  863.         }
  864.  
  865.         m_lstChunks = lstChunksMerged;
  866. }
  867.  
  868. //////////////////////////////////////////////////////////////////////////
  869. _smart_ptr<IRenderMesh> CRenderMeshMerger::MergeRenderMeshes(SRenderMeshInfoInput* pRMIArray, int nRMICount,
  870.                                                              PodArray<SRenderMeshInfoOutput>& outRenderMeshes,
  871.                                                              SMergeInfo& info) PREFAST_SUPPRESS_WARNING(6262) //function uses > 32k stack space
  872. {
  873.         FUNCTION_PROFILER_3DENGINE;
  874.  
  875.         if (info.bPrintDebugMessages)
  876.                 PrintMessage("MergeRenderMeshs: name: %s, input brushes num: %d", info.sMeshName, nRMICount);
  877.  
  878.         m_nTotalVertexCount = 0;
  879.         m_nTotalIndexCount = 0;
  880.  
  881.         m_lstRMIChunks.clear();
  882.         m_lstVerts.clear();
  883.         m_lstTangBasises.clear();
  884. #if ENABLE_NORMALSTREAM_SUPPORT
  885.         m_lstNormals.clear();
  886. #endif
  887.         m_lstIndices.clear();
  888.         m_lstChunks.clear();
  889.  
  890.         // make list of all chunks
  891.         MakeRenderMeshInfoListOfAllChunks(pRMIArray, nRMICount, info);
  892.  
  893.         if (info.bPrintDebugMessages)
  894.                 PrintMessage("%d render chunks found", m_lstRMIChunks.Count());
  895.  
  896.         if (!m_lstRMIChunks.Count())
  897.                 return NULL;
  898.  
  899.         // sort by materials
  900.         if (!info.pDecalClipInfo)
  901.                 qsort(m_lstRMIChunks.GetElements(), m_lstRMIChunks.Count(), sizeof(m_lstRMIChunks[0]), Cmp_RenderChunksInfo);
  902.  
  903.         // make list of all CRenderChunks
  904.         MakeListOfAllCRenderChunks(info);
  905.  
  906.         //      assert(IsHeapValid());
  907.  
  908.         if (!m_lstVerts.Count() || !m_lstChunks.Count() || !m_lstIndices.Count())
  909.                 return NULL;
  910.  
  911.         if (info.bPrintDebugMessages)
  912.                 PrintMessage("%d chunks left after culling (%d verts, %d indices)", m_lstChunks.Count(), m_lstVerts.Count(), m_lstIndices.Count());
  913.  
  914.         // Split chunks that does not fit together.
  915.         TryMergingChunks(info);
  916.  
  917.         if (info.bPrintDebugMessages)
  918.                 PrintMessage("%d chunks left after merging", m_lstChunks.Count());
  919.  
  920.         if (!m_lstChunks.Count())
  921.                 return NULL;
  922.  
  923.         // now we have list of merged/sorted chunks, indices and vertices's
  924.         // overall amount of vertices's may be more than 0xFFFF
  925.         if (m_lstChunks.Count() == 1 && info.pDecalClipInfo && GetCVars()->e_DecalsClip)
  926.         {
  927.                 // clip decals if needed
  928.                 ClipDecals(info);
  929.                 if (m_lstIndices.Count() < 3 || m_lstVerts.Count() < 3)
  930.                         return NULL;
  931.  
  932.                 // find AABB
  933.                 AABB aabb = AABB(m_lstVerts[0].xyz.ToVec3(), m_lstVerts[0].xyz.ToVec3());
  934.                 for (int i = 0; i < m_lstVerts.Count(); i++)
  935.                         aabb.Add(m_lstVerts[i].xyz.ToVec3());
  936.  
  937.                 // weld positions
  938.                 mesh_compiler::CMeshCompiler meshCompiler;
  939. #if ENABLE_NORMALSTREAM_SUPPORT
  940.                 PREFAST_SUPPRESS_WARNING(6385);
  941.                 meshCompiler.WeldPos_VF_P3X(m_lstVerts, m_lstTangBasises, m_lstNormals, m_lstIndices, VEC_EPSILON, aabb);
  942. #else
  943.                 PodArray<Vec3> lstNormalsDummy;
  944.                 meshCompiler.WeldPos_VF_P3X(m_lstVerts, m_lstTangBasises, lstNormalsDummy, m_lstIndices, VEC_EPSILON, aabb);
  945. #endif
  946.  
  947.                 // update chunk
  948.                 CRenderChunk& Ch0 = m_lstChunks[0].rChunk;
  949.                 Ch0.nFirstIndexId = 0;
  950.                 Ch0.nNumIndices = m_lstIndices.Count();
  951.                 Ch0.nFirstVertId = 0;
  952.                 Ch0.nNumVerts = m_lstVerts.Count();
  953.         }
  954.  
  955.         if (/*GetCVars()->e_scene_merging_compact_vertices && */ info.bCompactVertBuffer)
  956.         {
  957.                 // remove gaps in vertex buffers
  958.                 CompactVertices(info);
  959.         }
  960.  
  961. #ifdef _DEBUG
  962.         for (int nChunkId = 0; nChunkId < m_lstChunks.Count(); nChunkId++)
  963.         {
  964.                 CRenderChunk& Ch0 = m_lstChunks[nChunkId].rChunk;
  965.                 IsChunkValid(Ch0, m_lstVerts, m_lstIndices);
  966.         }
  967. #endif // _DEBUG
  968.  
  969.         if (info.bPrintDebugMessages)
  970.                 PrintMessage("Making new RenderMeshes");
  971.  
  972.         outRenderMeshes.clear();
  973.  
  974.         m_lstNewChunks.reserve(m_lstChunks.Count());
  975.         m_lstNewVerts.reserve(m_nTotalVertexCount);
  976.         m_lstNewTangBasises.reserve(m_nTotalVertexCount);
  977. #if ENABLE_NORMALSTREAM_SUPPORT
  978.         m_lstNormals.reserve(m_nTotalVertexCount);
  979. #endif
  980.         m_lstNewIndices.reserve(m_nTotalIndexCount);
  981.  
  982.         for (int nChunkId = 0; nChunkId < m_lstChunks.Count(); )
  983.         {
  984.                 AABB finalBox;
  985.                 finalBox.Reset();
  986.  
  987.                 m_lstNewVerts.clear();
  988.                 m_lstNewTangBasises.clear();
  989. #if ENABLE_NORMALSTREAM_SUPPORT
  990.                 m_lstNormals.clear();
  991. #endif
  992.                 m_lstNewIndices.clear();
  993.                 m_lstNewChunks.clear();
  994.  
  995.                 int nVertsNum = 0;
  996.                 for (; nChunkId < m_lstChunks.Count(); )
  997.                 {
  998.                         CRenderChunk Ch = m_lstChunks[nChunkId].rChunk;
  999.                         SMergedChunk& mrgChunk = m_lstChunks[nChunkId];
  1000.  
  1001.                         assert(m_lstNewVerts.Count() + Ch.nNumVerts <= 0xFFFF);
  1002.  
  1003.                         IsChunkValid(Ch, m_lstVerts, m_lstIndices);
  1004.  
  1005.                         int nCurrIdxPos = m_lstNewIndices.Count();
  1006.                         int nCurrVertPos = m_lstNewVerts.Count();
  1007.  
  1008.                         m_lstNewVerts.AddList(&m_lstVerts[Ch.nFirstVertId], Ch.nNumVerts);
  1009.                         m_lstNewTangBasises.AddList(&m_lstTangBasises[Ch.nFirstVertId], Ch.nNumVerts);
  1010. #if ENABLE_NORMALSTREAM_SUPPORT
  1011.                         m_lstNormals.AddList(&m_lstNormals[Ch.nFirstVertId], Ch.nNumVerts);
  1012. #endif
  1013.  
  1014.                         for (uint32 i = Ch.nFirstIndexId; i < Ch.nFirstIndexId + Ch.nNumIndices; i++)
  1015.                         {
  1016.                                 uint32 nIndex = m_lstIndices[i] - Ch.nFirstVertId + nCurrVertPos;
  1017.                                 assert(nIndex >= 0 && nIndex <= 0xFFFF && nIndex < (uint32)m_lstNewVerts.Count());
  1018.                                 nIndex = nIndex & 0xFFFF;
  1019.                                 m_lstNewIndices.Add(nIndex);
  1020.                                 finalBox.Add(m_lstNewVerts[nIndex].xyz.ToVec3());
  1021.                         }
  1022.  
  1023.                         Ch.nFirstIndexId = nCurrIdxPos;
  1024.                         Ch.nFirstVertId = nCurrVertPos;
  1025.  
  1026.                         nVertsNum += Ch.nNumVerts;
  1027.  
  1028.                         {
  1029.                                 assert(Ch.nFirstIndexId + Ch.nNumIndices <= (uint32)m_lstNewIndices.Count());
  1030.                                 assert(Ch.nFirstVertId + Ch.nNumVerts <= (uint16)m_lstNewVerts.Count());
  1031.  
  1032. #ifdef _DEBUG
  1033.                                 for (uint32 i = Ch.nFirstIndexId; i < Ch.nFirstIndexId + Ch.nNumIndices; i++)
  1034.                                 {
  1035.                                         assert(m_lstNewIndices[i] >= Ch.nFirstVertId && m_lstNewIndices[i] < Ch.nFirstVertId + Ch.nNumVerts);
  1036.                                         assert((int)m_lstNewIndices[i] < m_lstNewVerts.Count());
  1037.                                 }
  1038. #endif
  1039.                         }
  1040.  
  1041.                         SMergedChunk newMergedChunk;
  1042.                         newMergedChunk.rChunk = Ch;
  1043.                         newMergedChunk.pMaterial = mrgChunk.pMaterial;
  1044.                         m_lstNewChunks.Add(newMergedChunk);
  1045.  
  1046.                         nChunkId++;
  1047.  
  1048.                         if (nChunkId < m_lstChunks.Count())
  1049.                         {
  1050.                                 if (nVertsNum + m_lstChunks[nChunkId].rChunk.nNumVerts > 0xFFFF)
  1051.                                         break;
  1052.  
  1053.                                 if (info.bMergeToOneRenderMesh)
  1054.                                         continue;
  1055.  
  1056.                                 // detect vert format change
  1057.                                 SShaderItem& shaderItemCur = mrgChunk.pMaterial->GetShaderItem();
  1058.                                 EVertexFormat nNextChunkVertFormatCur = shaderItemCur.m_pShader->GetVertexFormat();
  1059.  
  1060.                                 SShaderItem& shaderItemNext = m_lstChunks[nChunkId].pMaterial->GetShaderItem();
  1061.                                 EVertexFormat nNextChunkVertFormatNext = shaderItemNext.m_pShader->GetVertexFormat();
  1062.  
  1063.                                 if (nNextChunkVertFormatNext != nNextChunkVertFormatCur)
  1064.                                         break;
  1065.                         }
  1066.                 }
  1067.  
  1068.                 IRenderMesh::SInitParamerers params;
  1069.                 params.pVertBuffer = m_lstNewVerts.GetElements();
  1070.                 params.nVertexCount = m_lstNewVerts.Count();
  1071.                 params.eVertexFormat = eVF_P3S_C4B_T2S;
  1072.                 params.pIndices = m_lstNewIndices.GetElements();
  1073.                 params.nIndexCount = m_lstNewIndices.Count();
  1074.                 params.pTangents = m_lstNewTangBasises.GetElements();
  1075. #if ENABLE_NORMALSTREAM_SUPPORT
  1076.                 params.pNormals = m_lstNewNormals.GetElements();
  1077. #endif
  1078.                 params.nPrimetiveType = prtTriangleList;
  1079.                 params.eType = eRMT_Static;
  1080.                 params.nRenderChunkCount = 0;
  1081.                 params.bOnlyVideoBuffer = false;
  1082.                 params.bPrecache = false;
  1083.  
  1084.                 // make new RenderMesh
  1085.                 _smart_ptr<IRenderMesh> pNewLB = GetRenderer()->CreateRenderMesh(info.sMeshName, info.sMeshType, &params);
  1086.  
  1087.                 IMaterial* pParentMaterial = NULL;
  1088.  
  1089.                 pNewLB->SetBBox(finalBox.min, finalBox.max);
  1090.  
  1091.                 if (!info.pUseMaterial)
  1092.                 {
  1093.                         // make new parent material
  1094.                         if (!info.pDecalClipInfo)
  1095.                         {
  1096.                                 char szMatName[256];
  1097.                                 cry_sprintf(szMatName, "%s_Material", info.sMeshName);
  1098.                                 pParentMaterial = GetMatMan()->CreateMaterial(szMatName, MTL_FLAG_MULTI_SUBMTL);
  1099.                                 pParentMaterial->AddRef();
  1100.                                 pParentMaterial->SetSubMtlCount(m_lstChunks.Count());
  1101.                         }
  1102.  
  1103.                         // define chunks
  1104.                         for (int i = 0; i < m_lstNewChunks.Count(); i++)
  1105.                         {
  1106.                                 CRenderChunk* pChunk = &m_lstNewChunks[i].rChunk;
  1107.  
  1108.                                 IMaterial* pMat = m_lstNewChunks[i].pMaterial;
  1109.  
  1110.                                 if (pParentMaterial)
  1111.                                 {
  1112.                                         assert(pMat);
  1113.                                         pParentMaterial->SetSubMtl(i, pMat);
  1114.                                 }
  1115.  
  1116.                                 assert(pChunk->nFirstIndexId + pChunk->nNumIndices <= (uint32)m_lstNewIndices.Count());
  1117.  
  1118.                                 pChunk->m_nMatID = i;
  1119.                                 if (pMat)
  1120.                                         pChunk->m_nMatFlags = pMat->GetFlags();
  1121.                                 pNewLB->SetChunk(i, *pChunk);
  1122.                         }
  1123.                 }
  1124.                 else
  1125.                 {
  1126.                         pParentMaterial = info.pUseMaterial;
  1127.  
  1128.                         // define chunks
  1129.                         for (int i = 0; i < m_lstNewChunks.Count(); i++)
  1130.                         {
  1131.                                 CRenderChunk* pChunk = &m_lstNewChunks[i].rChunk;
  1132.                                 assert(pChunk->nFirstIndexId + pChunk->nNumIndices <= (uint32)m_lstNewIndices.Count());
  1133.  
  1134.                                 IMaterial* pSubMtl = info.pUseMaterial->GetSafeSubMtl(pChunk->m_nMatID);
  1135.                                 pChunk->m_nMatFlags = pSubMtl->GetFlags();
  1136.  
  1137.                                 pNewLB->SetChunk(i, *pChunk);
  1138.                         }
  1139.                 }
  1140.  
  1141.                 SRenderMeshInfoOutput rmi;
  1142.                 rmi.pMesh = pNewLB;
  1143.                 rmi.pMat = pParentMaterial;
  1144.                 if (pParentMaterial)
  1145.                         pParentMaterial->AddRef();
  1146.  
  1147.                 outRenderMeshes.push_back(rmi);
  1148.         }
  1149.  
  1150.         if (info.bPrintDebugMessages)
  1151.                 PrintMessage("%" PRISIZE_T " RenderMeshes created", outRenderMeshes.size());
  1152.  
  1153.         return outRenderMeshes.Count() ? outRenderMeshes[0].pMesh : _smart_ptr<IRenderMesh>(NULL);
  1154. }
  1155.  
  1156. struct sort_render_chunks_by_material
  1157. {
  1158.         bool operator()(const SMergedChunk& c1, const SMergedChunk& c2) const
  1159.         {
  1160.                 return c1.pMaterial < c2.pMaterial;
  1161.         }
  1162. };
  1163.  
  1164. //////////////////////////////////////////////////////////////////////////
  1165. bool CRenderMeshMerger::GenerateRenderChunks(SRenderMeshInfoInput* pRMIArray, int nRMICount)
  1166. {
  1167.         bool bCanMerge = true;
  1168.         PodArray<SMergedChunk>& allChunks = m_lstChunksAll;
  1169.  
  1170.         allChunks.clear();
  1171.         allChunks.reserve(nRMICount);
  1172.  
  1173.         for (int nRmi = 0; nRmi < nRMICount; nRmi++)
  1174.         {
  1175.                 SRenderMeshInfoInput* pRMI = &pRMIArray[nRmi];
  1176.                 IRenderMesh* pRM = pRMI->pMesh;
  1177.  
  1178.                 // Ignore bad meshes.
  1179.                 if (pRM->GetVerticesCount() == 0 || pRM->GetIndicesCount() == 0)
  1180.                         continue;
  1181.  
  1182.                 const TRenderChunkArray& chunks = pRM->GetChunks();
  1183.                 int nChunkCount = chunks.size();
  1184.                 for (int nChunk = 0; nChunk < nChunkCount; nChunk++)
  1185.                 {
  1186.                         const CRenderChunk& renderChunk = chunks[nChunk];
  1187.  
  1188.                         if (renderChunk.m_nMatFlags & MTL_FLAG_NODRAW || !renderChunk.pRE)
  1189.                                 continue;
  1190.  
  1191.                         if (renderChunk.nNumVerts == 0 || renderChunk.nNumIndices == 0)
  1192.                                 continue;
  1193.  
  1194.                         if (!pRMI->pMat)
  1195.                                 continue;
  1196.  
  1197.                         IMaterial* pCustMat = (pRMI->pMat) ? pRMI->pMat->GetSafeSubMtl(renderChunk.m_nMatID) : 0;
  1198.                         if (!pCustMat)
  1199.                                 continue;
  1200.  
  1201.                         if (!pCustMat->GetShaderItem().m_pShader)
  1202.                                 pCustMat = GetMatMan()->GetDefaultMaterial();
  1203.  
  1204.                         IShader* pShader = pCustMat->GetShaderItem().m_pShader;
  1205.  
  1206.                         if (!pShader)
  1207.                                 continue;
  1208.  
  1209.                         if (pShader->GetFlags() & EF_NODRAW)
  1210.                                 continue;
  1211.  
  1212.                         SMergedChunk newChunk;
  1213.                         newChunk.pFromMesh = pRMI;
  1214.                         newChunk.pMaterial = pCustMat;
  1215.                         newChunk.rChunk = renderChunk;
  1216.                         newChunk.rChunk.nSubObjectIndex = pRMI->nSubObjectIndex;
  1217.                         newChunk.rChunk.pRE = 0;
  1218.  
  1219.                         allChunks.push_back(newChunk);
  1220.                 }
  1221.         }
  1222.  
  1223.         // sort by materials
  1224.         std::sort(allChunks.begin(), allChunks.end(), sort_render_chunks_by_material());
  1225.  
  1226.         return bCanMerge;
  1227. }
  1228.  
  1229. //////////////////////////////////////////////////////////////////////////
  1230. void CRenderMeshMerger::MergeRenderChunks()
  1231. {
  1232.         PodArray<SMergedChunk>& allChunks = m_lstChunksAll;
  1233.  
  1234.         //////////////////////////////////////////////////////////////////////////
  1235.         // Create array of merged chunks.
  1236.         //////////////////////////////////////////////////////////////////////////
  1237.         PodArray<SMergedChunk>& mergedChunks = m_lstChunks;
  1238.         mergedChunks.clear();
  1239.         mergedChunks.reserve(allChunks.size());
  1240.  
  1241.         if (allChunks.size() > 0)
  1242.         {
  1243.                 // Add first chunk.
  1244.                 mergedChunks.push_back(allChunks[0]);
  1245.         }
  1246.  
  1247.         for (size_t nChunkId = 1; nChunkId < allChunks.size(); nChunkId++)
  1248.         {
  1249.                 SMergedChunk& currChunk = allChunks[nChunkId];
  1250.  
  1251.                 SMergedChunk& prevChunk = mergedChunks.back();
  1252.  
  1253.                 if ((currChunk.pMaterial != prevChunk.pMaterial) ||
  1254.                     ((prevChunk.rChunk.nNumVerts + currChunk.rChunk.nNumVerts) > 0xFFFF) ||
  1255.                     ((prevChunk.rChunk.nNumIndices + currChunk.rChunk.nNumIndices) > 0xFFFF))
  1256.                 {
  1257.                         // not equal materials - add new chunk
  1258.                         mergedChunks.Add(currChunk);
  1259.                 }
  1260.                 else
  1261.                 {
  1262.                         float texelAreaDensity = 0.0f;
  1263.                         int totalIndices = 0;
  1264.  
  1265.                         if (prevChunk.rChunk.m_texelAreaDensity != (float)UINT_MAX)
  1266.                         {
  1267.                                 texelAreaDensity += prevChunk.rChunk.nNumIndices * prevChunk.rChunk.m_texelAreaDensity;
  1268.                                 totalIndices += prevChunk.rChunk.nNumIndices;
  1269.                         }
  1270.  
  1271.                         if (currChunk.rChunk.m_texelAreaDensity != (float)UINT_MAX)
  1272.                         {
  1273.                                 texelAreaDensity += currChunk.rChunk.nNumIndices * currChunk.rChunk.m_texelAreaDensity;
  1274.                                 totalIndices += currChunk.rChunk.nNumIndices;
  1275.                         }
  1276.  
  1277.                         if (totalIndices != 0)
  1278.                         {
  1279.                                 prevChunk.rChunk.m_texelAreaDensity = texelAreaDensity / totalIndices;
  1280.                         }
  1281.                         else
  1282.                         {
  1283.                                 prevChunk.rChunk.m_texelAreaDensity = 1.f;
  1284.                         }
  1285.  
  1286.                         prevChunk.rChunk.nNumIndices += currChunk.rChunk.nNumIndices;
  1287.                         prevChunk.rChunk.nNumVerts += currChunk.rChunk.nNumVerts;
  1288.                 }
  1289.         }
  1290. }
  1291.  
  1292. //////////////////////////////////////////////////////////////////////////
  1293. void CRenderMeshMerger::MergeBuffers(AABB& bounds)
  1294. {
  1295.         FUNCTION_PROFILER_3DENGINE;
  1296.  
  1297.         m_nTotalVertexCount = 0;
  1298.         m_nTotalIndexCount = 0;
  1299.  
  1300.         int nNeedVertices = 0;
  1301.         int nNeedIndices = 0;
  1302.  
  1303.         PodArray<SMergedChunk>& allChunks = m_lstChunksAll;
  1304.  
  1305.         // Calculate total required sizes.
  1306.         for (size_t nChunk = 0; nChunk < allChunks.size(); nChunk++)
  1307.         {
  1308.                 SMergedChunk& renderChunk = allChunks[nChunk];
  1309.                 nNeedIndices += renderChunk.rChunk.nNumIndices;
  1310.                 nNeedVertices += renderChunk.rChunk.nNumVerts;
  1311.         }
  1312.  
  1313.         PodArray<vtx_idx>& arrIndices = m_lstNewIndices;
  1314.         arrIndices.clear();
  1315.         arrIndices.reserve(nNeedIndices);
  1316.  
  1317.         PodArray<SVF_P3S_C4B_T2S>& arrVertices = m_lstVerts;
  1318.         arrVertices.clear();
  1319.         arrVertices.reserve(nNeedVertices);
  1320.  
  1321.         PodArray<SPipTangents>& arrTangents = m_lstTangBasises;
  1322.         arrTangents.clear();
  1323.         arrTangents.reserve(nNeedVertices);
  1324.  
  1325. #if ENABLE_NORMALSTREAM_SUPPORT
  1326.         PodArray<SPipNormal>& arrNormals = m_lstNormals;
  1327.         arrNormals.clear();
  1328.         arrNormals.reserve(nNeedVertices);
  1329. #endif
  1330.  
  1331.         m_lstMergeBuffersData.clear();
  1332.         m_lstMergeBuffersData.resize(allChunks.size());
  1333.  
  1334.         m_tmpAABB = bounds;
  1335.  
  1336.         // do all GetPos etc calls before in the t thread
  1337.         for (size_t nChunk = 0; nChunk < allChunks.size(); nChunk++)
  1338.         {
  1339.                 SMergeBuffersData& rMergeBufferData = m_lstMergeBuffersData[nChunk];
  1340.                 IRenderMesh* pRM = allChunks[nChunk].pFromMesh->pMesh;
  1341.                 pRM->LockForThreadAccess();
  1342.                 rMergeBufferData.pPos = pRM->GetPosPtr(rMergeBufferData.nPosStride, FSL_READ);
  1343.                 rMergeBufferData.pTex = pRM->GetUVPtr(rMergeBufferData.nTexStride, FSL_READ);
  1344.                 rMergeBufferData.pColor = pRM->GetColorPtr(rMergeBufferData.nColorStride, FSL_READ);
  1345.                 rMergeBufferData.pTangs = pRM->GetTangentPtr(rMergeBufferData.nTangsStride, FSL_READ);
  1346.                 rMergeBufferData.nIndCount = pRM->GetIndicesCount();
  1347.                 rMergeBufferData.pSrcInds = pRM->GetIndexPtr(FSL_READ);
  1348.  
  1349. #if ENABLE_NORMALSTREAM_SUPPORT
  1350.                 rMergeBufferData.pNorm = pRM->GetNormPtr(rMergeBufferData.nNormStride, FSL_READ);
  1351. #endif
  1352.         }
  1353.  
  1354.         MergeBuffersImpl(&m_tmpAABB, m_lstMergeBuffersData.GetElements());
  1355.  
  1356.         // operation on buffers has finished, unlock them again for rendermesh garbage collection
  1357.         for (size_t nChunk = 0; nChunk < allChunks.size(); nChunk++)
  1358.         {
  1359.                 IRenderMesh* pRM = allChunks[nChunk].pFromMesh->pMesh;
  1360.                 pRM->UnLockForThreadAccess();
  1361.         }
  1362.  
  1363.         bounds = m_tmpAABB;
  1364. }
  1365.  
  1366. void CRenderMeshMerger::MergeBuffersImpl(AABB* pBounds, SMergeBuffersData* _arrMergeBuffersData)
  1367. {
  1368.         // size for SPU buffers, currently we have 16 buffers, means we need 128 kb
  1369.         uint32 nNumMergeChunks = m_lstChunksAll.size();
  1370.  
  1371.         PodArray<SMergedChunk>& allChunks = m_lstChunksAll;
  1372.         SMergeBuffersData* arrMergeBuffersData = _arrMergeBuffersData;
  1373.  
  1374.         PodArray<vtx_idx>& arrIndices = m_lstNewIndices;
  1375.         PodArray<SVF_P3S_C4B_T2S>& arrVertices = m_lstVerts;
  1376.         PodArray<SPipTangents>& arrTangents = m_lstTangBasises;
  1377.  
  1378. #if ENABLE_NORMALSTREAM_SUPPORT
  1379.         PodArray<SPipNormal>& arrNormals = m_lstNormals;
  1380. #endif
  1381.  
  1382.         for (size_t nChunk = 0; nChunk < nNumMergeChunks; nChunk++)
  1383.         {
  1384.  
  1385.                 SMergedChunk& renderChunk = allChunks[nChunk];
  1386.                 SMergeBuffersData& rMergeBufferData = arrMergeBuffersData[nChunk];
  1387.                 SRenderMeshInfoInput* pRMI = renderChunk.pFromMesh;
  1388.                 Matrix34& rMatrix = pRMI->mat;
  1389.  
  1390.                 bool bMatrixHasRotation;
  1391.                 if (!rMatrix.m01 && !rMatrix.m02 && !rMatrix.m10 && !rMatrix.m12 && !rMatrix.m20 && !rMatrix.m21)
  1392.                         bMatrixHasRotation = false;
  1393.                 else
  1394.                         bMatrixHasRotation = true;
  1395.  
  1396.                 Vec3 vOffset = rMatrix.GetTranslation();
  1397.  
  1398.                 IRenderMesh* pRM = pRMI->pMesh;
  1399.  
  1400.                 // get streams.
  1401.                 int nPosStride = rMergeBufferData.nPosStride;
  1402.                 int nTexStride = rMergeBufferData.nTexStride;
  1403.                 int nColorStride = rMergeBufferData.nColorStride;
  1404.                 int nTangsStride = rMergeBufferData.nTangsStride;
  1405.  
  1406.                 uint8* pPos = rMergeBufferData.pPos;
  1407.                 uint8* pTex = rMergeBufferData.pTex;
  1408.                 uint8* pColor = rMergeBufferData.pColor;
  1409.                 uint8* pTangs = rMergeBufferData.pTangs;
  1410.  
  1411. #if ENABLE_NORMALSTREAM_SUPPORT
  1412.                 int nNormStride = rMergeBufferData.nNormStride;
  1413.                 uint8* pNorm = rMergeBufferData.pNorm;
  1414. #endif
  1415.  
  1416.                 if (!pPos || !pTex || !pColor || !pTangs)
  1417.                 {
  1418.                         assert(0); // Should not happen.
  1419.                         continue;
  1420.                 }
  1421.  
  1422.                 Vec3 vMin, vMax;
  1423.                 pRM->GetBBox(vMin, vMax);
  1424.                 pBounds->Add(vMin);
  1425.                 pBounds->Add(vMax);
  1426.  
  1427.                 // get indices
  1428.                 vtx_idx* pInds = rMergeBufferData.pSrcInds;
  1429.  
  1430.                 Vec3 vOSPos(0, 0, 0);
  1431.                 Vec3 vOSProjDir(0, 0, 0);
  1432.  
  1433.                 int nLastVertex = arrVertices.size();
  1434.                 int nLastIndex = arrIndices.size();
  1435.  
  1436.                 //////////////////////////////////////////////////////////////////////////
  1437.                 // add indices
  1438.                 //////////////////////////////////////////////////////////////////////////
  1439.                 int nCurrIndex = nLastIndex;
  1440.                 arrIndices.resize(nLastIndex + renderChunk.rChunk.nNumIndices);
  1441.                 int nAdjustedVertexOffset = nLastVertex - renderChunk.rChunk.nFirstVertId;
  1442.                 int i = renderChunk.rChunk.nFirstIndexId;
  1443.                 int numInd = renderChunk.rChunk.nFirstIndexId + renderChunk.rChunk.nNumIndices;
  1444.  
  1445.                 vtx_idx* __restrict pSrcInds = pInds;
  1446.                 vtx_idx* __restrict pDstInds = &arrIndices[0];
  1447.  
  1448.                 for (; i < numInd; i += 3, nCurrIndex += 3)
  1449.                 {
  1450.                         pDstInds[nCurrIndex + 0] = pSrcInds[i + 0] + nAdjustedVertexOffset;
  1451.                         pDstInds[nCurrIndex + 1] = pSrcInds[i + 1] + nAdjustedVertexOffset;
  1452.                         pDstInds[nCurrIndex + 2] = pSrcInds[i + 2] + nAdjustedVertexOffset;
  1453.                 }
  1454.  
  1455.                 //////////////////////////////////////////////////////////////////////////
  1456.                 renderChunk.rChunk.nFirstIndexId = nLastIndex;
  1457.  
  1458.                 //////////////////////////////////////////////////////////////////////////
  1459.                 // add vertices
  1460.                 //////////////////////////////////////////////////////////////////////////
  1461.                 int nCurrVertex = nLastVertex;
  1462.                 arrVertices.resize(nLastVertex + renderChunk.rChunk.nNumVerts);
  1463.                 arrTangents.resize(nLastVertex + renderChunk.rChunk.nNumVerts);
  1464.  
  1465. #if ENABLE_NORMALSTREAM_SUPPORT
  1466.                 arrNormals.resize(nLastVertex + renderChunk.rChunk.nNumVerts);
  1467. #endif
  1468.  
  1469.                 int v = renderChunk.rChunk.nFirstVertId;
  1470.                 int numVert = renderChunk.rChunk.nFirstVertId + renderChunk.rChunk.nNumVerts;
  1471.                 if (bMatrixHasRotation)
  1472.                 {
  1473.                         SVF_P3S_C4B_T2S* __restrict pDstVerts = &arrVertices[0];
  1474.                         SPipTangents* __restrict pDstTangs = &arrTangents[0];
  1475. #if ENABLE_NORMALSTREAM_SUPPORT
  1476.                         SPipNormal* __restrict pDstNorms = &arrNormals[0];
  1477. #endif
  1478.  
  1479.                         uint8* pSrcPos = pPos;
  1480.                         uint8* pSrcTex = pTex;
  1481.                         uint8* pSrcColor = pColor;
  1482.                         uint8* pSrcTangs = pTangs;
  1483. #if ENABLE_NORMALSTREAM_SUPPORT
  1484.                         uint8* pSrcNorm = pNorm;
  1485. #endif
  1486.                         for (; v < numVert; v++, nCurrVertex++)
  1487.                         {
  1488.                                 SVF_P3S_C4B_T2S& vert = pDstVerts[nCurrVertex];
  1489.                                 SPipTangents& basis = pDstTangs[nCurrVertex];
  1490. #if ENABLE_NORMALSTREAM_SUPPORT
  1491.                                 SPipNormal& normal = pDstNorms[nCurrVertex];
  1492. #endif
  1493.                                 // set pos/uv
  1494.                                 Vec3& vPos = (*(Vec3*)&pSrcPos[nPosStride * v]);
  1495.                                 Vec2* pUV = (Vec2*)&pSrcTex[nTexStride * v];
  1496.  
  1497.                                 vert.xyz = rMatrix.TransformPoint(vPos);
  1498.                                 vert.st = *pUV;
  1499.                                 vert.color.dcolor = *(uint32*)&pSrcColor[nColorStride * v + 0];
  1500.  
  1501.                                 // get tangent basis
  1502.                                 basis = *(SPipTangents*)&pSrcTangs[nTangsStride * v];
  1503.  
  1504. #if ENABLE_NORMALSTREAM_SUPPORT
  1505.                                 normal = SPipNormal(Vec3(0, 0, 0));
  1506.                                 if (pSrcNorm)
  1507.                                         normal = *(SPipNormal*)&pSrcNorm[nNormStride * v];
  1508. #endif
  1509.  
  1510.                                 if (bMatrixHasRotation)
  1511.                                 {
  1512.                                         basis.TransformSafelyBy(rMatrix);
  1513. #if ENABLE_NORMALSTREAM_SUPPORT
  1514.                                         if (pSrcNorm)
  1515.                                         {
  1516.                                                 normal.TransformSafelyBy(rMatrix);
  1517.                                         }
  1518. #endif
  1519.                                 }
  1520.                         }
  1521.                 }
  1522.                 else
  1523.                 {
  1524.                         SVF_P3S_C4B_T2S* __restrict pDstVerts = &arrVertices[0];
  1525.                         SPipTangents* __restrict pDstTangs = &arrTangents[0];
  1526. #if ENABLE_NORMALSTREAM_SUPPORT
  1527.                         SPipNormal* __restrict pDstNorms = &arrNormals[0];
  1528. #endif
  1529.  
  1530.                         uint8* pSrcPos = pPos;
  1531.                         uint8* pSrcTex = pTex;
  1532.                         uint8* pSrcColor = pColor;
  1533.                         uint8* pSrcTangs = pTangs;
  1534. #if ENABLE_NORMALSTREAM_SUPPORT
  1535.                         uint8* pSrcNorm = pNorm;
  1536. #endif
  1537.                         for (; v < numVert; v++, nCurrVertex++)
  1538.                         {
  1539.                                 SVF_P3S_C4B_T2S& vert = pDstVerts[nCurrVertex];
  1540.                                 SPipTangents& basis = pDstTangs[nCurrVertex];
  1541.  
  1542. #if ENABLE_NORMALSTREAM_SUPPORT
  1543.                                 SPipNormal& normal = pDstNorms[nCurrVertex];
  1544. #endif
  1545.  
  1546.                                 // set pos/uv
  1547.                                 Vec3& vPos = (*(Vec3*)&pSrcPos[nPosStride * v]);
  1548.                                 Vec2* pUV = (Vec2*)&pSrcTex[nTexStride * v];
  1549.  
  1550.                                 vert.xyz = rMatrix.TransformPoint(vPos);
  1551.                                 vert.st = *pUV;
  1552.                                 vert.color.dcolor = *(uint32*)&pSrcColor[nColorStride * v];
  1553.  
  1554.                                 // get tangent basis
  1555.                                 basis = *(SPipTangents*)&pSrcTangs[nTangsStride * v];
  1556.  
  1557. #if ENABLE_NORMALSTREAM_SUPPORT
  1558.                                 normal = SPipNormal(Vec3(0, 0, 0));
  1559.                                 if (pSrcNorm)
  1560.                                 {
  1561.                                         normal = *(SPipNormal*)(&pSrcNorm[nNormStride * v]);
  1562.                                 }
  1563. #endif
  1564.                         }
  1565.                 }
  1566.  
  1567.                 // set vert range
  1568.                 renderChunk.rChunk.nFirstVertId = nLastVertex;
  1569.  
  1570.                 m_nTotalVertexCount += renderChunk.rChunk.nNumVerts;
  1571.                 m_nTotalIndexCount += renderChunk.rChunk.nNumIndices;
  1572.         }
  1573. }
  1574.  
  1575. void CRenderMeshMerger::Reset()
  1576. {
  1577.         stl::free_container(m_lstRMIChunks);
  1578.         stl::free_container(m_lstVerts);
  1579.         stl::free_container(m_lstTangBasises);
  1580.         stl::free_container(m_lstIndices);
  1581.         stl::free_container(m_lstChunks);
  1582.         stl::free_container(m_lstChunksAll);
  1583.         stl::free_container(m_lstNewVerts);
  1584.         stl::free_container(m_lstNewTangBasises);
  1585.         stl::free_container(m_lstNewIndices);
  1586.         stl::free_container(m_lstNewChunks);
  1587.         stl::free_container(m_lstChunksMergedTemp);
  1588.         stl::free_container(m_tmpRenderChunkArray);
  1589.         stl::free_container(m_lstMergeBuffersData);
  1590.  
  1591. #if ENABLE_NORMALSTREAM_SUPPORT
  1592.         stl::free_container(m_lstNormals);
  1593.         stl::free_container(m_lstNewNormals);
  1594. #endif
  1595.  
  1596.         m_tmpClipContext.Reset();
  1597. }
  1598.  
  1599. //////////////////////////////////////////////////////////////////////////
  1600. _smart_ptr<IRenderMesh> CRenderMeshMerger::MergeRenderMeshes(SRenderMeshInfoInput* pRMIArray, int nRMICount, SMergeInfo& info)
  1601. {
  1602.         m_nTotalVertexCount = 0;
  1603.         m_nTotalIndexCount = 0;
  1604.  
  1605.         m_lstRMIChunks.clear();
  1606.         m_lstVerts.clear();
  1607.         m_lstTangBasises.clear();
  1608. #if ENABLE_NORMALSTREAM_SUPPORT
  1609.         m_lstNormals.clear();
  1610. #endif
  1611.         m_lstIndices.clear();
  1612.         m_lstNewIndices.clear();
  1613.         m_lstChunks.clear();
  1614.  
  1615.         // make list of all chunks
  1616.         if (!GenerateRenderChunks(pRMIArray, nRMICount))
  1617.         {
  1618.                 return 0;
  1619.         }
  1620.  
  1621.         MergeRenderChunks();
  1622.  
  1623.         if (m_lstChunksAll.empty())
  1624.                 return NULL;
  1625.  
  1626.         // Often even single mesh must be merged, when non identity matrix is provided
  1627.         /*
  1628.            if (m_lstChunks.size() == m_lstChunksAll.size())
  1629.            {
  1630.            // No reduction of render chunks.
  1631.            return 0;
  1632.            }
  1633.          */
  1634.  
  1635.         AABB finalBounds;
  1636.         finalBounds.Reset();
  1637.         MergeBuffers(finalBounds);
  1638.  
  1639.         if (m_lstNewIndices.empty() || m_lstVerts.empty() || m_lstTangBasises.empty())
  1640.         {
  1641.                 return 0;
  1642.         }
  1643.  
  1644.         // Repeat merging to properly update vertex ranges.
  1645.         MergeRenderChunks();
  1646.  
  1647.         IRenderMesh::SInitParamerers params;
  1648.         params.pVertBuffer = &m_lstVerts.front();
  1649.         params.nVertexCount = m_lstVerts.size();
  1650.         params.eVertexFormat = eVF_P3S_C4B_T2S;
  1651.         params.pIndices = &m_lstNewIndices.front();
  1652.         params.nIndexCount = m_lstNewIndices.size();
  1653.         params.pTangents = &m_lstTangBasises.front();
  1654. #if ENABLE_NORMALSTREAM_SUPPORT
  1655.         params.pNormals = &m_lstNormals.front();
  1656. #endif
  1657.         params.nPrimetiveType = prtTriangleList;
  1658.         params.eType = eRMT_Static;
  1659.         params.nRenderChunkCount = 0;
  1660.         params.bOnlyVideoBuffer = false;
  1661.         params.bPrecache = false;
  1662.         params.bLockForThreadAccess = true;//calls LockForThreadAccess in the Rendermesh ctor
  1663.  
  1664.         _smart_ptr<IRenderMesh> pRenderMesh = GetRenderer()->CreateRenderMesh(info.sMeshType, info.sMeshName, &params);
  1665.         pRenderMesh->SetBBox(finalBounds.min, finalBounds.max);
  1666.  
  1667.         //////////////////////////////////////////////////////////////////////////
  1668.         // Setup merged chunks
  1669.         //////////////////////////////////////////////////////////////////////////
  1670.         m_tmpRenderChunkArray.resize(m_lstChunks.size());
  1671.         for (size_t i = 0, num = m_lstChunks.size(); i < num; i++)
  1672.         {
  1673.                 m_tmpRenderChunkArray[i] = m_lstChunks[i].rChunk;
  1674.         }
  1675.         pRenderMesh->SetRenderChunks(&m_tmpRenderChunkArray.front(), m_tmpRenderChunkArray.size(), false);
  1676.         //////////////////////////////////////////////////////////////////////////
  1677.  
  1678.         //////////////////////////////////////////////////////////////////////////
  1679.         // Setup un-merged chunks
  1680.         //////////////////////////////////////////////////////////////////////////
  1681.         m_tmpRenderChunkArray.resize(m_lstChunksAll.size());
  1682.         for (size_t i = 0, num = m_lstChunksAll.size(); i < num; i++)
  1683.         {
  1684.                 m_tmpRenderChunkArray[i] = m_lstChunksAll[i].rChunk;
  1685.         }
  1686.         pRenderMesh->SetRenderChunks(&m_tmpRenderChunkArray.front(), m_tmpRenderChunkArray.size(), true);
  1687.         //////////////////////////////////////////////////////////////////////////
  1688.  
  1689.         pRenderMesh->UnLockForThreadAccess();
  1690.  
  1691.         return pRenderMesh;
  1692. }
  1693.  
downloadRenderMeshMerger.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top