BVB Source Codes

CRYENGINE Show AttachmentMerger.cpp Source code

Return Download CRYENGINE: download AttachmentMerger.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. #include "AttachmentMerger.h"
  5.  
  6. #include <CryRenderer/IRenderAuxGeom.h>
  7. #include "ModelMesh.h"
  8. #include "AttachmentMerged.h"
  9. #include "AttachmentManager.h"
  10. #include "CharacterManager.h"
  11. #include "Model.h"
  12. #include "CharacterInstance.h"
  13.  
  14. CAttachmentMerger::ShadowChunkRange::ShadowChunkIterator::ShadowChunkIterator(TRenderChunkArray::const_iterator curPos, TRenderChunkArray::const_iterator rangeEnd, IMaterial* pMtl)
  15.         : itCurPos(curPos)
  16.         , itEnd(rangeEnd)
  17.         , isShadowChunk(pMtl)
  18. {
  19.         while (itCurPos != itEnd && !isShadowChunk(*itCurPos))
  20.                 ++itCurPos;
  21. }
  22.  
  23. CAttachmentMerger::ShadowChunkRange::ShadowChunkIterator& CAttachmentMerger::ShadowChunkRange::ShadowChunkIterator::operator++()
  24. {
  25.         ++itCurPos;
  26.  
  27.         while (itCurPos != itEnd && !isShadowChunk(*itCurPos))
  28.                 ++itCurPos;
  29.  
  30.         return *this;
  31. }
  32.  
  33. CAttachmentMerger::ShadowChunkRange::ShadowChunkIterator CAttachmentMerger::ShadowChunkRange::begin()
  34. {
  35.         return ShadowChunkIterator(pRenderMesh->GetChunks().begin(), pRenderMesh->GetChunks().end(), pMaterial);
  36. }
  37.  
  38. CAttachmentMerger::ShadowChunkRange::ShadowChunkIterator CAttachmentMerger::ShadowChunkRange::end()
  39. {
  40.         return ShadowChunkIterator(pRenderMesh->GetChunks().end(), pRenderMesh->GetChunks().end(), pMaterial);
  41. }
  42.  
  43. CAttachmentMerger::MeshStreams::MeshStreams(IRenderMesh* pRenderMesh, uint32 lockFlags, bool bGetSkinningInfos)
  44.         : pMesh(pRenderMesh)
  45.         , pSkinningInfos(NULL)
  46. {
  47.         pRenderMesh->LockForThreadAccess();
  48.  
  49.         pIndices = pRenderMesh->GetIndexPtr(lockFlags);
  50.         pPositions = pRenderMesh->GetPosPtrNoCache(nPositionStride, lockFlags);
  51.  
  52.         if (bGetSkinningInfos)
  53.                 pSkinningInfos = pRenderMesh->GetHWSkinPtr(nSkinningInfoStride, lockFlags);
  54. }
  55.  
  56. CAttachmentMerger::MeshStreams::~MeshStreams()
  57. {
  58.         pMesh->UnlockIndexStream();
  59.         pMesh->UnlockStream(VSF_GENERAL);
  60.         pMesh->UnlockStream(VSF_HWSKIN_INFO);
  61.         pMesh->UnLockForThreadAccess();
  62. }
  63.  
  64. SVF_W4B_I4S& CAttachmentMerger::MeshStreams::GetSkinningInfo(int nVtxIndex)
  65. {
  66.         CRY_ASSERT(nVtxIndex < pMesh->GetVerticesCount());
  67.         return static_cast<SVF_W4B_I4S*>(pSkinningInfos)[nVtxIndex];
  68. }
  69.  
  70. vtx_idx& CAttachmentMerger::MeshStreams::GetVertexIndex(int i)
  71. {
  72.         CRY_ASSERT(i < pMesh->GetIndicesCount());
  73.         return pIndices[i];
  74. }
  75.  
  76. EVertexFormat CAttachmentMerger::MeshStreams::GetVertexFormat()
  77. {
  78.         return pMesh->GetVertexFormat();
  79. }
  80.  
  81. CAttachmentMerger::MergeContext::MergeContext(IAttachment* pAttachment)
  82. {
  83.         memset(this, 0x0, sizeof(MergeContext));
  84.         Update(AttachmentRenderData(pAttachment));
  85. }
  86.  
  87. CAttachmentMerger::MergeContext::MergeContext(const AttachmentRenderData& renderData)
  88. {
  89.         memset(this, 0x0, sizeof(MergeContext));
  90.         Update(renderData);
  91. }
  92.  
  93. void CAttachmentMerger::MergeContext::Update(const AttachmentRenderData& renderData)
  94. {
  95.         nAccumulatedBoneCount += renderData.nBoneCount;
  96.         nMaxLodCount = max(nMaxLodCount, renderData.nLodCount);
  97.  
  98.         uint twoSidedCount = 0;
  99.         uint chunkCount = 0;
  100.  
  101.         for (int lod = 0; lod < MAX_STATOBJ_LODS_NUM; ++lod)
  102.         {
  103.                 auto const& lodData = renderData.GetLod(lod);
  104.                 if (lodData.pMesh && lodData.pMaterial)
  105.                 {
  106.                         nAccumulatedVertexCount[lod] += lodData.pMesh->GetVerticesCount();
  107.  
  108.                         for (auto const& chunk : lodData.GetShadowChunks())
  109.                         {
  110.                                 IMaterial* pSubMtl = lodData.pMaterial->GetSafeSubMtl(chunk.m_nMatID);
  111.                                 IRenderShaderResources* pShaderResources = pSubMtl->GetShaderItem().m_pShaderResources;
  112.  
  113.                                 nAccumulatedIndexCount[lod] += chunk.nNumIndices;
  114.  
  115.                                 if (pShaderResources && pShaderResources->IsAlphaTested())
  116.                                         bAlphaTested = true;
  117.  
  118.                                 if ((pSubMtl->GetFlags() & MTL_FLAG_2SIDED) != 0)
  119.                                         ++twoSidedCount;
  120.  
  121.                                 ++chunkCount;
  122.                         }
  123.  
  124.                         if (lodData.pMesh->GetSkinningWeightCount() > 4)
  125.                                 bEightWeightSkinning = true;
  126.                 }
  127.         }
  128.  
  129.         if (twoSidedCount == 0)
  130.                 nTwoSided = eStateOff;
  131.         else if (twoSidedCount == chunkCount)
  132.                 nTwoSided = eStateOn;
  133.         else
  134.                 nTwoSided = eStateMixed;
  135. }
  136.  
  137. uint CAttachmentMerger::MergeContext::EstimateRequiredMemory() const
  138. {
  139.         const uint nVertexSize = sizeof(SVF_P3F) + sizeof(SVF_W4B_I4S);
  140.         const uint nIndexSize = sizeof(vtx_idx) * 2;  // index buffer is cached CPU side
  141.  
  142.         uint nResult = 0;
  143.         for (int lod = 0; lod < nMaxLodCount; ++lod)
  144.         {
  145.                 nResult += nAccumulatedVertexCount[lod] * nVertexSize;
  146.                 nResult += nAccumulatedIndexCount[lod] * nIndexSize;
  147.         }
  148.  
  149.         return nResult;
  150. }
  151.  
  152. CAttachmentMerger::AttachmentRenderData::AttachmentRenderData(IAttachment* pAtt)
  153. {
  154.         memset(this, 0x0, sizeof(AttachmentRenderData));
  155.  
  156.         if (const IAttachmentObject* pAttachmentObject = pAtt->GetIAttachmentObject())
  157.         {
  158.                 if (CAttachmentSKIN* pAttachmentSkin = static_cast<CAttachmentSKIN*>(pAttachmentObject->GetIAttachmentSkin()))
  159.                 {
  160.                         for (uint lod = 0; lod < MAX_STATOBJ_LODS_NUM; ++lod)
  161.                         {
  162.                                 if (IRenderMesh* pRenderMesh = pAttachmentSkin->m_pModelSkin->GetIRenderMesh(lod))
  163.                                 {
  164.                                         arrLods[lod].pMesh = pRenderMesh;
  165.                                         arrLods[lod].pMaterial = GetAttachmentMaterial(pAtt, lod);
  166.                                         arrLods[lod].mTransform = Matrix34::CreateTranslationMat(pAttachmentSkin->m_pModelSkin->GetModelMesh(lod)->m_vRenderMeshOffset);
  167.                                         ++nLodCount;
  168.                                 }
  169.                         }
  170.  
  171.                         CSkin* pSkin = static_cast<CSkin*>(pAttachmentSkin->GetISkin());
  172.                         nBoneCount = pSkin->m_arrModelJoints.size();
  173.                 }
  174.                 else if (IStatObj* pStatObj = pAttachmentObject->GetIStatObj())
  175.                 {
  176.                         for (uint lod = 0; lod < MAX_STATOBJ_LODS_NUM; ++lod)
  177.                         {
  178.                                 if (IStatObj* pStatObjLod = pStatObj->GetLodObject(lod))
  179.                                 {
  180.                                         if (IRenderMesh* pRenderMesh = pStatObjLod->GetRenderMesh())
  181.                                         {
  182.                                                 arrLods[lod].pMesh = pRenderMesh;
  183.                                                 arrLods[lod].pMaterial = GetAttachmentMaterial(pAtt, lod);
  184.                                                 arrLods[lod].mTransform = Matrix34(pAtt->GetAttAbsoluteDefault());
  185.                                                 ++nLodCount;
  186.                                         }
  187.                                 }
  188.                         }
  189.  
  190.                         nBoneCount = 1;
  191.                 }
  192.         }
  193.  
  194.         // propagate last lod data to remaining lods
  195.         if (nLodCount > 0)
  196.         {
  197.                 for (int i = nLodCount; i < MAX_STATOBJ_LODS_NUM; ++i)
  198.                         arrLods[i] = arrLods[i - 1];
  199.         }
  200.  
  201.         pAttachment = pAtt;
  202. }
  203.  
  204. bool CAttachmentMerger::CanMerge(const MergeContext& context1, const MergeContext& context2)
  205. {
  206.         if (context1.nMaxLodCount == 0 || context2.nMaxLodCount == 0) // can always merge with empty attachment
  207.                 return true;
  208.  
  209.         uint nMemorySize = 0;
  210.         for (int lod = 0; lod < MAX_STATOBJ_LODS_NUM; ++lod)
  211.         {
  212.                 if (context1.nAccumulatedVertexCount[lod] + context2.nAccumulatedVertexCount[lod] > std::numeric_limits<vtx_idx>::max())
  213.                         return false;
  214.         }
  215.  
  216.         if (context1.nAccumulatedBoneCount + context2.nAccumulatedBoneCount > std::numeric_limits<JointIdType>::max())
  217.                 return false;
  218.  
  219.         if (context1.bAlphaTested || context2.bAlphaTested)
  220.                 return false;
  221.  
  222.         if (context1.nTwoSided == MergeContext::eStateMixed || context2.nTwoSided == MergeContext::eStateMixed)
  223.                 return false;
  224.  
  225.         if (context1.nTwoSided != context2.nTwoSided)
  226.                 return false;
  227.  
  228.         if (context1.bEightWeightSkinning || context2.bEightWeightSkinning)
  229.                 return false;
  230.  
  231.         return true;
  232. }
  233.  
  234. bool CAttachmentMerger::CanMerge(IAttachment* pAttachment1, IAttachment* pAttachment2)
  235. {
  236.         MergeContext context1(pAttachment1);
  237.         MergeContext context2(pAttachment2);
  238.  
  239.         return Instance().CanMerge(context1, context2);
  240. }
  241.  
  242. IMaterial* CAttachmentMerger::GetAttachmentMaterial(const IAttachment* pAttachment, int lod)
  243. {
  244.         const IAttachmentObject* pAttachmentObject = pAttachment->GetIAttachmentObject();
  245.         IMaterial* pMaterial = pAttachmentObject->GetBaseMaterial(lod);
  246.         if (!pMaterial) pMaterial = pAttachmentObject->GetBaseMaterial(0);
  247.  
  248.         return pMaterial;
  249. }
  250.  
  251. void CAttachmentMerger::MergeAttachments(DynArray<_smart_ptr<SAttachmentBase>>& arrAttachments, DynArray<_smart_ptr<CAttachmentMerged>>& arrMergedAttachments, CAttachmentManager* pAttachmentManager)
  252. {
  253.         DEFINE_PROFILER_FUNCTION();
  254.  
  255.         DynArray<AttachmentRenderData> mergeableAttachments;
  256.         mergeableAttachments.reserve(arrAttachments.size());
  257.  
  258.         // get list of mergeable attachments
  259.         for (auto pAttachment : arrAttachments)
  260.         {
  261.                 if (pAttachment->IsMerged() || pAttachment->GetIAttachmentObject() == NULL)
  262.                         continue;
  263.  
  264.                 AttachmentRenderData attachmentData(pAttachment);
  265.  
  266.                 bool bAllValidMaterials = true;
  267.                 for (auto const& lod : attachmentData.arrLods)
  268.                 {
  269.                         if (!lod.pMaterial)
  270.                         {
  271.                                 bAllValidMaterials = false;
  272.                                 break;
  273.                         }
  274.                 }
  275.  
  276.                 if (!bAllValidMaterials || attachmentData.nLodCount == 0)
  277.                         continue;
  278.  
  279.                 mergeableAttachments.push_back(attachmentData);
  280.         }
  281.  
  282.         // now try to merge
  283.         for (uint i = 0; i < mergeableAttachments.size(); ++i)
  284.         {
  285.                 if (mergeableAttachments[i].pAttachment == NULL)
  286.                         continue;
  287.  
  288.                 DynArray<AttachmentRenderData> curAttachmentList;
  289.                 curAttachmentList.reserve(mergeableAttachments.size());
  290.                 curAttachmentList.push_back(mergeableAttachments[i]);
  291.  
  292.                 MergeContext context(mergeableAttachments[i]);
  293.                 mergeableAttachments[i].pAttachment = NULL; // mark as done
  294.  
  295.                 for (uint j = i + 1; j < mergeableAttachments.size(); ++j)
  296.                 {
  297.                         if (mergeableAttachments[j].pAttachment)
  298.                         {
  299.                                 CRY_ASSERT(!mergeableAttachments[j].pAttachment->IsMerged());
  300.  
  301.                                 if (CanMerge(mergeableAttachments[j], context))
  302.                                 {
  303.                                         MergeContext mergedContext = context;
  304.                                         mergedContext.Update(mergeableAttachments[j]);
  305.  
  306.                                         if (m_nBytesAllocated + mergedContext.EstimateRequiredMemory() < Console::GetInst().ca_AttachmentMergingMemoryBudget)
  307.                                         {
  308.                                                 curAttachmentList.push_back(mergeableAttachments[j]);
  309.                                                 context = mergedContext;
  310.  
  311.                                                 mergeableAttachments[j].pAttachment = NULL;
  312.                                         }
  313.                                         else
  314.                                         {
  315.                                                 m_bOutOfMemory = true;
  316.                                         }
  317.                                 }
  318.                         }
  319.                 }
  320.  
  321.                 if (curAttachmentList.size() > 1)
  322.                 {
  323.                         CAttachmentMerged* pMergeTarget = NULL;
  324.  
  325.                         // try to merge into existing merged attachment first
  326.                         for (auto pMergedAttachment : arrMergedAttachments)
  327.                         {
  328.                                 AttachmentRenderData mergedAttachmentData(pMergedAttachment->m_pMergedSkinAttachment);
  329.                                 if (CanMerge(mergedAttachmentData, context))
  330.                                 {
  331.                                         context.nMaxLodCount = max(mergedAttachmentData.nLodCount, context.nMaxLodCount); // adjust lod count
  332.                                         pMergeTarget = pMergedAttachment;
  333.                                         pMergeTarget->m_pMergedSkinAttachment->m_pModelSkin->m_arrModelMeshes.resize(context.nMaxLodCount);
  334.  
  335.                                         break;
  336.                                 }
  337.                         }
  338.  
  339.                         // need to create a new merged attachment
  340.                         if (!pMergeTarget)
  341.                         {
  342.                                 string attachmentName;
  343.                                 attachmentName.Format("MergedAttachment_%d", m_nMergedSkinCount++);
  344.  
  345.                                 pMergeTarget = new CAttachmentMerged(attachmentName, pAttachmentManager);
  346.                                 CSkin* pSkin = new CSkin(attachmentName, 0);
  347.                                 pSkin->m_arrModelMeshes.resize(context.nMaxLodCount);
  348.  
  349.                                 for (auto& mesh : pSkin->m_arrModelMeshes) // mark as resident so it cannot be streamed out
  350.                                         ++mesh.m_stream.nKeepResidentRefs;
  351.  
  352.                                 g_pCharacterManager->RegisterModelSKIN(pSkin, 0);
  353.                                 g_pCharacterManager->RegisterInstanceSkin(pSkin, pMergeTarget->m_pMergedSkinAttachment);
  354.                                 pMergeTarget->m_pMergedSkinAttachment->m_pModelSkin = pSkin;
  355.  
  356.                                 arrMergedAttachments.push_back(pMergeTarget);
  357.                         }
  358.  
  359.                         Merge(pMergeTarget, curAttachmentList, pAttachmentManager);
  360.                         m_nBytesAllocated += context.EstimateRequiredMemory();
  361.                 }
  362.         }
  363. }
  364.  
  365. void CAttachmentMerger::OnDeleteMergedAttachment(CAttachmentMerged* pAttachment)
  366. {
  367.         CRY_ASSERT(pAttachment != NULL);
  368.  
  369.         AttachmentRenderData renderData(pAttachment->m_pMergedSkinAttachment);
  370.         uint nSize = MergeContext(renderData).EstimateRequiredMemory();
  371.         CRY_ASSERT(nSize <= m_nBytesAllocated);
  372.  
  373.         m_nBytesAllocated -= nSize;
  374.         m_bOutOfMemory = false;
  375. }
  376.  
  377. inline Vec3 toVec3(const Vec3& v)    { return v; }
  378. inline Vec3 toVec3(const Vec3f16& v) { return v.ToVec3(); }
  379.  
  380. template<typename VertexFormat, const bool RequiresTransform>
  381. void CopyVertices_tpl(CAttachmentMerger::MeshStreams& dstStreams, uint dstVtxOffset, CAttachmentMerger::MeshStreams& srcStreams, uint numVertices, const Matrix34& transform)
  382. {
  383.         const uint8_t* __restrict pSrc = (uint8_t*) srcStreams.pPositions;
  384.         const uint8_t* pSrcEnd = pSrc + numVertices * srcStreams.nPositionStride;
  385.  
  386.         uint8_t* __restrict pDst = (uint8_t*) dstStreams.pPositions + dstVtxOffset * dstStreams.nPositionStride;
  387.  
  388.         while (pSrc < pSrcEnd)
  389.         {
  390.                 Vec3 v = toVec3(((VertexFormat*) pSrc)->xyz);
  391.  
  392.                 if (RequiresTransform)
  393.                         v = transform * v;
  394.  
  395.                 ((SVF_P3F*) pDst)->xyz = v;
  396.  
  397.                 pDst += dstStreams.nPositionStride;
  398.                 pSrc += srcStreams.nPositionStride;
  399.         }
  400. }
  401.  
  402. template<const bool RequiresTransform>
  403. uint CopyVertices(CAttachmentMerger::MeshStreams& dstStreams, uint dstVtxOffset, CAttachmentMerger::MeshStreams& srcStreams, uint numVertices, const Matrix34& transform)
  404. {
  405.         switch (srcStreams.GetVertexFormat())
  406.         {
  407.         case eVF_P3S_C4B_T2S:
  408.                 CopyVertices_tpl<SVF_P3S_C4B_T2S, RequiresTransform>(dstStreams, dstVtxOffset, srcStreams, numVertices, transform);
  409.                 break;
  410.         case eVF_P3F_C4B_T2F:
  411.                 CopyVertices_tpl<SVF_P3F_C4B_T2F, RequiresTransform>(dstStreams, dstVtxOffset, srcStreams, numVertices, transform);
  412.                 break;
  413.         case eVF_P3F:
  414.                 CopyVertices_tpl<SVF_P3F, RequiresTransform>(dstStreams, dstVtxOffset, srcStreams, numVertices, transform);
  415.                 break;
  416.         default:
  417.                 CRY_ASSERT(false);
  418.         }
  419.  
  420.         return numVertices;
  421. }
  422.  
  423. uint CAttachmentMerger::CopyVertices(MeshStreams& dstStreams, uint dstVtxOffset, MeshStreams& srcStreams, uint numVertices)
  424. {
  425.         return ::CopyVertices<false>(dstStreams, dstVtxOffset, srcStreams, numVertices, Matrix34(IDENTITY));
  426. }
  427. uint CAttachmentMerger::CopyVertices(MeshStreams& dstStreams, uint dstVtxOffset, MeshStreams& srcStreams, uint numVertices, const Matrix34& transform)
  428. {
  429.         return ::CopyVertices<true>(dstStreams, dstVtxOffset, srcStreams, numVertices, transform);
  430. }
  431.  
  432. uint CAttachmentMerger::CopyIndices(MeshStreams& dstStreams, uint dstVtxOffset, uint dstIdxOffset, MeshStreams& srcStreams, const CRenderChunk& chunk)
  433. {
  434. #if defined(CRY_PLATFORM_SSE2)
  435.         memcpy(dstStreams.pIndices + dstIdxOffset, srcStreams.pIndices + chunk.nFirstIndexId, chunk.nNumIndices * sizeof(vtx_idx));
  436.  
  437.         const bool b32BitIndices = sizeof(vtx_idx) == 4;
  438.         const uint NumElementsSSE = b32BitIndices ? 4 : 8;
  439.  
  440.         __m128i dstIdxOffset4 = b32BitIndices ? _mm_set1_epi32(dstVtxOffset) : _mm_set1_epi16(dstVtxOffset);
  441.  
  442.         vtx_idx* pDstStart = dstStreams.pIndices + dstIdxOffset;
  443.         vtx_idx* pDstEnd = dstStreams.pIndices + dstIdxOffset + chunk.nNumIndices;
  444.  
  445.         vtx_idx* pDstStartAligned = Align(pDstStart, 16);
  446.         vtx_idx* pDstEndAligned = pDstStart + (chunk.nNumIndices & ~(NumElementsSSE - 1));
  447.  
  448.         vtx_idx* __restrict pCur = pDstStart;
  449.  
  450.         while (pCur < pDstStartAligned)
  451.                 *pCur++ += dstVtxOffset;
  452.  
  453.         for (; pCur < pDstEndAligned; pCur += NumElementsSSE)
  454.         {
  455.                 __m128i v = _mm_load_si128((__m128i*)pCur);
  456.                 __m128i w = b32BitIndices ? _mm_add_epi32(v, dstIdxOffset4) : _mm_add_epi16(v, dstIdxOffset4);
  457.                 _mm_storeu_si128((__m128i*)pCur, w);
  458.         }
  459.  
  460.         while (pCur < pDstEnd)
  461.                 *pCur++ += dstVtxOffset;
  462.  
  463. #else
  464.         for (uint k = 0; k < chunk.nNumIndices; ++k)
  465.         {
  466.                 vtx_idx idxSrc = srcStreams.GetVertexIndex(chunk.nFirstIndexId + k);
  467.                 vtx_idx& idxDst = dstStreams.GetVertexIndex(dstIdxOffset + k);
  468.                 idxDst = idxSrc + dstVtxOffset;
  469.         }
  470. #endif
  471.         return chunk.nNumIndices;
  472. }
  473.  
  474. uint CAttachmentMerger::CopySkinning(MeshStreams& dstStreams, uint dstVtxOffset, MeshStreams& srcStreams, uint numVertices, const DynArray<JointIdType>& boneIDs)
  475. {
  476.         CRY_ASSERT(srcStreams.pSkinningInfos);
  477.  
  478.         uint maxBoneIndex = 0;
  479.  
  480.         for (uint k = 0; k < numVertices; ++k)
  481.         {
  482.                 const SVF_W4B_I4S& srcSkinningInfo = srcStreams.GetSkinningInfo(k);
  483.  
  484.                 JointIdType id0 = srcSkinningInfo.indices[0];
  485.                 JointIdType id1 = srcSkinningInfo.indices[1];
  486.                 JointIdType id2 = srcSkinningInfo.indices[2];
  487.                 JointIdType id3 = srcSkinningInfo.indices[3];
  488.  
  489.                 id0 = srcSkinningInfo.weights.bcolor[0] ? boneIDs[id0] : 0;
  490.                 id1 = srcSkinningInfo.weights.bcolor[1] ? boneIDs[id1] : 0;
  491.                 id2 = srcSkinningInfo.weights.bcolor[2] ? boneIDs[id2] : 0;
  492.                 id3 = srcSkinningInfo.weights.bcolor[3] ? boneIDs[id3] : 0;
  493.  
  494.                 maxBoneIndex = max(maxBoneIndex, (uint)id0);
  495.                 maxBoneIndex = max(maxBoneIndex, (uint)id1);
  496.                 maxBoneIndex = max(maxBoneIndex, (uint)id2);
  497.                 maxBoneIndex = max(maxBoneIndex, (uint)id3);
  498.  
  499.                 CRY_ASSERT(maxBoneIndex <= std::numeric_limits<JointIdType>::max());
  500.  
  501.                 SVF_W4B_I4S& dstSkinningInfo = dstStreams.GetSkinningInfo(k + dstVtxOffset);
  502.  
  503.                 dstSkinningInfo.weights = srcSkinningInfo.weights;
  504.                 dstSkinningInfo.indices[0] = id0;
  505.                 dstSkinningInfo.indices[1] = id1;
  506.                 dstSkinningInfo.indices[2] = id2;
  507.                 dstSkinningInfo.indices[3] = id3;
  508.         }
  509.  
  510.         return maxBoneIndex;
  511. }
  512.  
  513. void CAttachmentMerger::SkinToBone(MeshStreams& dstStreams, uint dstVtxOffset, MeshStreams& srcStreams, uint numVertices, JointIdType jointID)
  514. {
  515.         CRY_ASSERT(dstStreams.pSkinningInfos);
  516.  
  517.         for (uint k = 0; k < numVertices; ++k)
  518.         {
  519.                 SVF_W4B_I4S& dstSkinningInfo = dstStreams.GetSkinningInfo(k + dstVtxOffset);
  520.  
  521.                 dstSkinningInfo.weights.bcolor[0] = 255;
  522.                 dstSkinningInfo.weights.bcolor[1] = 0;
  523.                 dstSkinningInfo.weights.bcolor[2] = 0;
  524.                 dstSkinningInfo.weights.bcolor[3] = 0;
  525.                 dstSkinningInfo.indices[0] = jointID;
  526.                 dstSkinningInfo.indices[1] = 0;
  527.                 dstSkinningInfo.indices[2] = 0;
  528.                 dstSkinningInfo.indices[3] = 0;
  529.         }
  530. }
  531.  
  532. void CAttachmentMerger::Merge(CAttachmentMerged* pDstAttachment, const DynArray<AttachmentRenderData>& attachmentData, CAttachmentManager* pAttachmentManager)
  533. {
  534.         CSkin* pDstSkin = static_cast<CSkin*>(pDstAttachment->m_pMergedSkinAttachment->m_pModelSkin);
  535.         CRY_ASSERT(pDstSkin->m_arrModelMeshes.size() > 0);
  536.  
  537.         DynArray<CSkin::SJointInfo> arrModelJoints = pDstSkin->m_arrModelJoints;
  538.         const uint maxLODCount = pDstSkin->GetNumLODs();
  539.  
  540.         CCharInstance* pInstanceSkel = pAttachmentManager->m_pSkelInstance;
  541.         CDefaultSkeleton* pDefaultSkeleton = pInstanceSkel->m_pDefaultSkeleton;
  542.  
  543.         DynArray<CAttachmentMerged::MergeInfo> mergeInfo;
  544.         mergeInfo.resize(attachmentData.size());
  545.         for (int i = 0; i < attachmentData.size(); ++i)
  546.         {
  547.                 mergeInfo[i].pAttachment = attachmentData[i].pAttachment;
  548.                 mergeInfo[i].pAttachmentObject = attachmentData[i].pAttachment->GetIAttachmentObject();
  549.                 memset(&mergeInfo[i].IndexInfo, 0x0, sizeof(mergeInfo[i].IndexInfo));
  550.         }
  551.  
  552.         for (uint lod = 0; lod < maxLODCount; ++lod)
  553.         {
  554.                 CModelMesh* pModelMesh = pDstSkin->GetModelMesh(lod);
  555.                 IRenderMesh* pPrevRenderMesh = pDstSkin->GetIRenderMesh(lod);
  556.  
  557.                 // Create rendermesh
  558.                 uint numVertices = pPrevRenderMesh ? pPrevRenderMesh->GetVerticesCount() : 0;
  559.                 uint numIndices = pPrevRenderMesh ? pPrevRenderMesh->GetIndicesCount() : 0;
  560.  
  561.                 for (auto const& attData : attachmentData)
  562.                 {
  563.                         const AttachmentLodData& lodData = attData.GetLod(lod);
  564.  
  565.                         for (auto const& chunk : lodData.GetShadowChunks())
  566.                                 numIndices += chunk.nNumIndices;
  567.  
  568.                         numVertices += lodData.pMesh->GetVerticesCount();
  569.                 }
  570.  
  571.                 IRenderMesh::SInitParamerers params;
  572.                 params.nVertexCount = numVertices;
  573.                 params.nIndexCount = numIndices;
  574.                 params.eVertexFormat = TargetVertexFormat;
  575.  
  576.                 _smart_ptr<IRenderMesh> pRenderMesh = g_pISystem->GetIRenderer()->CreateRenderMesh("MergedCharacter", pDstAttachment->m_pMergedSkinAttachment->GetName(), &params);
  577.  
  578.                 // Copy data from attachments
  579.                 {
  580.                         MeshStreams dstStreams(pRenderMesh, FSL_SYSTEM_CREATE);
  581.                         CRY_ASSERT(dstStreams.pSkinningInfos);
  582.  
  583.                         uint vertexBase = 0;
  584.                         uint indexBase = 0;
  585.                         uint maxBoneIndex = 0;
  586.  
  587.                         // copy previous rendermesh data first
  588.                         if (pPrevRenderMesh)
  589.                         {
  590.                                 MeshStreams srcStreams(pPrevRenderMesh);
  591.                                 memcpy(dstStreams.pPositions, srcStreams.pPositions, pPrevRenderMesh->GetVerticesCount() * srcStreams.nPositionStride);
  592.                                 memcpy(dstStreams.pSkinningInfos, srcStreams.pSkinningInfos, pPrevRenderMesh->GetVerticesCount() * srcStreams.nSkinningInfoStride);
  593.                                 memcpy(dstStreams.pIndices, srcStreams.pIndices, pPrevRenderMesh->GetIndicesCount() * sizeof(srcStreams.pIndices[0]));
  594.  
  595.                                 vertexBase = pPrevRenderMesh->GetVerticesCount();
  596.                                 indexBase = pPrevRenderMesh->GetIndicesCount();
  597.                                 maxBoneIndex = pDstSkin->m_arrModelJoints.size();
  598.                         }
  599.  
  600.                         for (int i = 0; i < attachmentData.size(); ++i)
  601.                         {
  602.                                 const AttachmentRenderData& curAttachmentData = attachmentData[i];
  603.                                 const AttachmentLodData& lodData = curAttachmentData.GetLod(lod);
  604.  
  605.                                 CAttachmentMerged::MergeInfo& curMergeInfo = mergeInfo[i];
  606.                                 curMergeInfo.IndexInfo[lod].nFirstIndex = indexBase;
  607.  
  608.                                 IAttachmentObject* pAttachmentObject = curAttachmentData.pAttachment->GetIAttachmentObject();
  609.  
  610.                                 if (CAttachmentSKIN* pAttachmentSkin = static_cast<CAttachmentSKIN*>(pAttachmentObject->GetIAttachmentSkin())) // SKIN ATTACHMENT
  611.                                 {
  612.                                         CRY_ASSERT(lodData.pMesh != NULL);
  613.  
  614.                                         DynArray<CSkin::SJointInfo>& srcJoints = pAttachmentSkin->m_pModelSkin->m_arrModelJoints;
  615.                                         DynArray<JointIdType> arrChunkBoneIDs;
  616.                                         arrChunkBoneIDs.resize(srcJoints.size());
  617.  
  618.                                         // add bones to merged bones list and build remapping table
  619.                                         for (uint k = 0; k < srcJoints.size(); ++k)
  620.                                         {
  621.                                                 auto compareToCurrentJoint = [&](const CSkin::SJointInfo& j0) { return j0.m_nJointCRC32Lower == srcJoints[k].m_nJointCRC32Lower; };
  622.                                                 DynArray<CSkin::SJointInfo>::const_iterator it = std::find_if(arrModelJoints.begin(), arrModelJoints.end(), compareToCurrentJoint);
  623.  
  624.                                                 if (it == arrModelJoints.end())
  625.                                                         arrModelJoints.push_back(srcJoints[k]);
  626.  
  627.                                                 arrChunkBoneIDs[k] = pDefaultSkeleton->GetJointIDByCRC32(srcJoints[k].m_nJointCRC32Lower);
  628.                                         }
  629.  
  630.                                         MeshStreams srcStreams(lodData.pMesh);
  631.                                         uint vertexCount = CopyVertices(dstStreams, vertexBase, srcStreams, lodData.pMesh->GetVerticesCount(), lodData.mTransform);
  632.                                         uint maxBoneID = CopySkinning(dstStreams, vertexBase, srcStreams, lodData.pMesh->GetVerticesCount(), arrChunkBoneIDs);
  633.  
  634.                                         for (auto const& chunk : lodData.GetShadowChunks())
  635.                                                 indexBase += CopyIndices(dstStreams, vertexBase, indexBase, srcStreams, chunk);
  636.  
  637.                                         vertexBase += lodData.pMesh->GetVerticesCount();
  638.                                         maxBoneIndex = max(maxBoneIndex, maxBoneID);
  639.                                 }
  640.                                 else // BONE/FACE ATTACHMENT
  641.                                 {
  642.                                         CRY_ASSERT(lod != 0 || pAttachmentManager->FindExtraBone(curAttachmentData.pAttachment) == -1);
  643.  
  644.                                         JointIdType jointID = pAttachmentManager->FindExtraBone(curAttachmentData.pAttachment);
  645.                                         if (jointID == (JointIdType) - 1)
  646.                                         {
  647.                                                 jointID = pAttachmentManager->AddExtraBone(curAttachmentData.pAttachment);
  648.  
  649.                                                 QuatT jointDefaultAbsolute(IDENTITY);
  650.                                                 JointIdType idAttachedTo = curAttachmentData.pAttachment->GetJointID();
  651.  
  652.                                                 if (idAttachedTo < pAttachmentManager->GetSkelInstance()->GetIDefaultSkeleton().GetJointCount())
  653.                                                         jointDefaultAbsolute = pAttachmentManager->GetSkelInstance()->GetIDefaultSkeleton().GetDefaultAbsJointByID(idAttachedTo);
  654.  
  655.                                                 CSkin::SJointInfo jointInfo;
  656.                                                 jointInfo.m_DefaultAbsolute = jointDefaultAbsolute;
  657.                                                 jointInfo.m_DefaultAbsolute.q.Normalize();
  658.                                                 jointInfo.m_idxParent = -1;
  659.                                                 jointInfo.m_nJointCRC32Lower = -1;
  660.                                                 jointInfo.m_nExtraJointID = jointID;
  661.                                                 jointInfo.m_NameModelSkin = pDstAttachment->m_pMergedSkinAttachment->GetName();
  662.                                                 arrModelJoints.push_back(jointInfo);
  663.                                         }
  664.  
  665.                                         jointID += pDefaultSkeleton->m_arrModelJoints.size();
  666.  
  667.                                         maxBoneIndex = max(maxBoneIndex, (uint)jointID);
  668.                                         CRY_ASSERT(maxBoneIndex <= std::numeric_limits<JointIdType>::max());
  669.  
  670.                                         MeshStreams srcStreams(lodData.pMesh, FSL_READ, false);
  671.                                         uint vertexCount = CopyVertices(dstStreams, vertexBase, srcStreams, lodData.pMesh->GetVerticesCount());
  672.                                         SkinToBone(dstStreams, vertexBase, srcStreams, lodData.pMesh->GetVerticesCount(), jointID);
  673.  
  674.                                         for (auto const& chunk : lodData.GetShadowChunks())
  675.                                                 indexBase += CopyIndices(dstStreams, vertexBase, indexBase, srcStreams, chunk);
  676.  
  677.                                         vertexBase += lodData.pMesh->GetVerticesCount();
  678.                                 }
  679.  
  680.                                 curMergeInfo.IndexInfo[lod].nIndexCount = indexBase - curMergeInfo.IndexInfo[lod].nFirstIndex;
  681.                         }
  682.  
  683.                         numIndices = indexBase;
  684.                         pDstAttachment->m_MergedAttachmentIndices[lod].assign(dstStreams.pIndices, dstStreams.pIndices + numIndices);
  685.  
  686.                         CRY_ASSERT(vertexBase == numVertices);
  687.                         CRY_ASSERT(indexBase == numIndices);
  688.                         CRY_ASSERT(maxBoneIndex < std::numeric_limits<JointIdType>::max());
  689.                 }
  690.  
  691.                 auto const& firstAttachmentLod = attachmentData[0].GetLod(lod);
  692.                 auto firstAttachmentChunk = firstAttachmentLod.GetShadowChunks().begin();
  693.  
  694.                 pModelMesh->m_pIRenderMesh = pRenderMesh;
  695.                 pModelMesh->m_pIDefaultMaterial = firstAttachmentLod.pMaterial->GetSafeSubMtl(firstAttachmentChunk->m_nMatID);
  696.                 pModelMesh->m_arrRenderChunks.resize(1);
  697.                 pModelMesh->m_arrRenderChunks[0].m_nFirstIndexId = 0;
  698.                 pModelMesh->m_arrRenderChunks[0].m_nNumIndices = numIndices;
  699.  
  700.                 CRenderChunk chunk;
  701.                 chunk.m_nMatID = 0;
  702.                 chunk.nNumVerts = numVertices;
  703.                 chunk.nNumIndices = numIndices;
  704.  
  705.                 if (chunk.nNumVerts > 0 && chunk.nNumIndices > 0)
  706.                 {
  707.                         pRenderMesh->SetChunk(-1, chunk);
  708.                         pRenderMesh->GetChunks()[0].pRE->mfUpdateFlags(FCEF_SKINNED);
  709.                         pRenderMesh->SetSkinned();
  710.                 }
  711.         }
  712.  
  713.         pDstSkin->m_arrModelJoints = arrModelJoints;
  714.  
  715.         CSKINAttachment* pSkinInstance = new CSKINAttachment();
  716.         pSkinInstance->m_pIAttachmentSkin = pDstAttachment->m_pMergedSkinAttachment;
  717.         pDstAttachment->AddAttachments(mergeInfo);
  718.         pDstAttachment->m_pMergedSkinAttachment->Immediate_AddBinding(pSkinInstance, pDstSkin, CA_SkipBoneRemapping);
  719. }
  720.  
  721. void CAttachmentMerger::UpdateIndices(CAttachmentMerged* pAttachment, int lod, const DynArray<std::pair<uint32, uint32>>& srcRanges)
  722. {
  723.         CRY_ASSERT(pAttachment && pAttachment->m_pMergedSkinAttachment->m_pModelSkin);
  724.         CRY_ASSERT(lod >= 0 && lod <= MAX_STATOBJ_LODS_NUM);
  725.  
  726.         DEFINE_PROFILER_FUNCTION();
  727.  
  728.         uint indexCount = 0;
  729.         for (auto& curRange : srcRanges)
  730.                 indexCount += curRange.second;
  731.  
  732.         DynArray<vtx_idx> newIndices;
  733.         newIndices.resize(indexCount);
  734.  
  735.         uint dstOffset = 0;
  736.         for (auto& curRange : srcRanges)
  737.         {
  738.                 if (curRange.second > 0)
  739.                 {
  740.                         memcpy(&newIndices[dstOffset], &pAttachment->m_MergedAttachmentIndices[lod][curRange.first], curRange.second * sizeof(vtx_idx));
  741.                         dstOffset += curRange.second;
  742.                 }
  743.         }
  744.  
  745.         IRenderMesh* pDstMesh = pAttachment->m_pMergedSkinAttachment->m_pModelSkin->GetIRenderMesh(lod);
  746.         if (pDstMesh)
  747.         {
  748.                 pDstMesh->LockForThreadAccess();
  749.                 pDstMesh->UpdateIndices(indexCount > 0 ? &newIndices[0] : NULL, newIndices.size(), 0, 0);
  750.                 pDstMesh->UnLockForThreadAccess();
  751.         }
  752.  
  753. }
  754.  
downloadAttachmentMerger.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