BVB Source Codes

CRYENGINE Show RenderMeshUtils.cpp Source code

Return Download CRYENGINE: download RenderMeshUtils.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   RenderMeshUtils.cpp
  5. //  Created:     14/11/2006 by Timur.
  6. //  Description:
  7. // -------------------------------------------------------------------------
  8. //  History:
  9. //
  10. ////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "StdAfx.h"
  13. #include "RenderMeshUtils.h"
  14.  
  15. namespace
  16. {
  17. enum { MAX_CACHED_HITS = 8 };
  18. struct SCachedHit
  19. {
  20.         IRenderMesh* pRenderMesh;
  21.         SRayHitInfo  hitInfo;
  22.         Vec3         tri[3];
  23. };
  24. static SCachedHit last_hits[MAX_CACHED_HITS];
  25. }
  26.  
  27. bool SIntersectionData::Init(IRenderMesh* param_pRenderMesh, SRayHitInfo* param_pHitInfo, IMaterial* param_pMtl, bool param_bRequestDecalPlacementTest)
  28. {
  29.         pRenderMesh = param_pRenderMesh;
  30.         pHitInfo = param_pHitInfo;
  31.         pMtl = param_pMtl;
  32.         bDecalPlacementTestRequested = param_bRequestDecalPlacementTest;
  33.  
  34.         bool bAllDMeshData = pHitInfo->bGetVertColorAndTC;
  35.  
  36.         nVerts = pRenderMesh->GetVerticesCount();
  37.         nInds = pRenderMesh->GetIndicesCount();
  38.  
  39.         if (nInds == 0 || nVerts == 0)
  40.                 return false;
  41.         pPos = (uint8*)pRenderMesh->GetPosPtr(nPosStride, FSL_READ);
  42.         pInds = pRenderMesh->GetIndexPtr(FSL_READ);
  43.  
  44.         if (!pPos || !pInds)
  45.                 return false;
  46.  
  47.         if (bAllDMeshData)
  48.         {
  49.                 pUV = (uint8*)pRenderMesh->GetUVPtr(nUVStride, FSL_READ);
  50.                 pCol = (uint8*)pRenderMesh->GetColorPtr(nColStride, FSL_READ);
  51.  
  52.                 pTangs = pRenderMesh->GetTangentPtr(nTangsStride, FSL_READ);
  53.         }
  54.  
  55.         return true;
  56. }
  57.  
  58. template<class T> bool GetBarycentricCoordinates(T P_A, T B_A, T C_A, float& u, float& v, float& w, float fBorder)
  59. {
  60.         // Compute vectors
  61.         const T& v0 = C_A;
  62.         const T& v1 = B_A;
  63.         const T& v2 = P_A;
  64.  
  65.         // Compute dot products
  66.         float dot00 = v0.Dot(v0);
  67.         float dot01 = v0.Dot(v1);
  68.         float dot02 = v0.Dot(v2);
  69.         float dot11 = v1.Dot(v1);
  70.         float dot12 = v1.Dot(v2);
  71.  
  72.         // Compute barycentric coordinates
  73.         float invDenom = 1.f / (dot00 * dot11 - dot01 * dot01);
  74.         u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  75.         v = (dot00 * dot12 - dot01 * dot02) * invDenom;
  76.         w = 1.f - u - v;
  77.  
  78.         // Check if point is in triangle
  79.         return (u >= -fBorder) && (v >= -fBorder) && (w >= -fBorder);
  80. }
  81.  
  82. void CRenderMeshUtils::ClearHitCache()
  83. {
  84.         // do not allow items to stay too long in the cache, it allows to minimize wrong hit detections
  85.         memmove(&last_hits[1], &last_hits[0], sizeof(last_hits) - sizeof(last_hits[0])); // Move hits to the end of array, throwing out the last one.
  86.         memset(&last_hits[0], 0, sizeof(last_hits[0]));
  87. }
  88. //////////////////////////////////////////////////////////////////////////
  89. bool CRenderMeshUtils::RayIntersection(IRenderMesh* pRenderMesh, SRayHitInfo& hitInfo, IMaterial* pMtl)
  90. {
  91.         SIntersectionData data;
  92.  
  93.         pRenderMesh->LockForThreadAccess();
  94.         if (!data.Init(pRenderMesh, &hitInfo, pMtl))
  95.         {
  96.                 return false;
  97.         }
  98.  
  99.         // forward call to implementation
  100.         bool result = CRenderMeshUtils::RayIntersectionImpl(&data, &hitInfo, pMtl, false);
  101.  
  102.         pRenderMesh->UnlockStream(VSF_GENERAL);
  103.         pRenderMesh->UnlockIndexStream();
  104.         pRenderMesh->UnLockForThreadAccess();
  105.         return result;
  106. }
  107.  
  108. void CRenderMeshUtils::RayIntersectionAsync(SIntersectionData* pIntersectionRMData)
  109. {
  110.         // forward call to implementation
  111.         SRayHitInfo& rHitInfo = *pIntersectionRMData->pHitInfo;
  112.         SIntersectionData& rIntersectionData = *pIntersectionRMData;
  113.  
  114.         if (CRenderMeshUtils::RayIntersectionImpl(&rIntersectionData, &rHitInfo, rIntersectionData.pMtl, true))
  115.         {
  116.                 const float testAreaSize = GetFloatCVar(e_DecalsPlacementTestAreaSize);
  117.                 const float minTestDepth = GetFloatCVar(e_DecalsPlacementTestMinDepth);
  118.  
  119.                 if (rIntersectionData.bDecalPlacementTestRequested && testAreaSize)
  120.                 {
  121.                         rIntersectionData.fDecalPlacementTestMaxSize = 0.f;
  122.                         float fRange = testAreaSize * 0.5f;
  123.  
  124.                         for (uint32 i = 0; i < 2; ++i, fRange *= 2.f)
  125.                         {
  126.                                 Vec3 vDir = -rHitInfo.vHitNormal;
  127.                                 vDir.Normalize();
  128.  
  129.                                 Vec3 vRight;
  130.                                 Vec3 vUp;
  131.  
  132.                                 if (fabs(vDir.Dot(Vec3(0, 0, 1))) > 0.995f)
  133.                                 {
  134.                                         vRight = Vec3(1, 0, 0);
  135.                                         vUp = Vec3(0, 1, 0);
  136.                                 }
  137.                                 else
  138.                                 {
  139.                                         vRight = vDir.Cross(Vec3(0, 0, 1));
  140.                                         vUp = vRight.Cross(vDir);
  141.                                 }
  142.  
  143.                                 Vec3 arrOffset[4] = { vRight* fRange, -vRight * fRange, vUp * fRange, -vUp * fRange };
  144.  
  145.                                 SRayHitInfo hInfo;
  146.                                 SIntersectionData intersectionData;
  147.  
  148.                                 float fDepth = max(minTestDepth, fRange * 0.2f);
  149.  
  150.                                 int nPoint;
  151.                                 for (nPoint = 0; nPoint < 4; nPoint++)
  152.                                 {
  153.                                         intersectionData = rIntersectionData;
  154.  
  155.                                         hInfo = rHitInfo;
  156.                                         hInfo.inReferencePoint = hInfo.vHitPos + arrOffset[nPoint];//*fRange;
  157.                                         hInfo.inRay.origin = hInfo.inReferencePoint + hInfo.vHitNormal * fDepth;
  158.                                         hInfo.inRay.direction = -hInfo.vHitNormal * fDepth * 2.f;
  159.                                         hInfo.fMaxHitDistance = fDepth;
  160.                                         if (!CRenderMeshUtils::RayIntersectionImpl(&intersectionData, &hInfo, rIntersectionData.pMtl, true))
  161.                                                 break;
  162.                                 }
  163.  
  164.                                 if (nPoint == 4)
  165.                                         rIntersectionData.fDecalPlacementTestMaxSize = fRange;
  166.                                 else
  167.                                         break;
  168.                         }
  169.                 }
  170.         }
  171. }
  172.  
  173. bool CRenderMeshUtils::RayIntersectionImpl(SIntersectionData* pIntersectionRMData, SRayHitInfo* phitInfo, IMaterial* pMtl, bool bAsync)
  174. {
  175.         IF (phitInfo->bGetVertColorAndTC, 0)
  176.                 return RayIntersectionFastImpl(*pIntersectionRMData, *phitInfo, pMtl, bAsync);
  177.  
  178.         SIntersectionData& rIntersectionRMData = *pIntersectionRMData;
  179.         SRayHitInfo& hitInfo = *phitInfo;
  180.  
  181.         FUNCTION_PROFILER_3DENGINE;
  182.  
  183.         //CTimeValue t0 = gEnv->pTimer->GetAsyncTime();
  184.  
  185.         float fMaxDist2 = hitInfo.fMaxHitDistance * hitInfo.fMaxHitDistance;
  186.  
  187.         Vec3 vHitPos(0, 0, 0);
  188.         Vec3 vHitNormal(0, 0, 0);
  189.  
  190.         static bool bClearHitCache = true;
  191.         if (bClearHitCache && !bAsync)
  192.         {
  193.                 memset(last_hits, 0, sizeof(last_hits));
  194.                 bClearHitCache = false;
  195.         }
  196.  
  197.         if (hitInfo.bUseCache && !bAsync)
  198.         {
  199.                 Vec3 vOut;
  200.                 // Check for cached hits.
  201.                 for (int i = 0; i < MAX_CACHED_HITS; i++)
  202.                 {
  203.                         if (last_hits[i].pRenderMesh == rIntersectionRMData.pRenderMesh)
  204.                         {
  205.                                 // If testing same render mesh, check if we hit the same triangle again.
  206.                                 if (Intersect::Ray_Triangle(hitInfo.inRay, last_hits[i].tri[0], last_hits[i].tri[2], last_hits[i].tri[1], vOut))
  207.                                 {
  208.                                         if (fMaxDist2)
  209.                                         {
  210.                                                 float fDistance2 = hitInfo.inReferencePoint.GetSquaredDistance(vOut);
  211.                                                 if (fDistance2 > fMaxDist2)
  212.                                                         continue; // Ignore hits that are too far.
  213.                                         }
  214.  
  215.                                         // Cached hit.
  216.                                         hitInfo.vHitPos = vOut;
  217.                                         hitInfo.vHitNormal = last_hits[i].hitInfo.vHitNormal;
  218.                                         hitInfo.nHitMatID = last_hits[i].hitInfo.nHitMatID;
  219.                                         hitInfo.nHitSurfaceID = last_hits[i].hitInfo.nHitSurfaceID;
  220.  
  221.                                         if (hitInfo.inRetTriangle)
  222.                                         {
  223.                                                 hitInfo.vTri0 = last_hits[i].tri[0];
  224.                                                 hitInfo.vTri1 = last_hits[i].tri[1];
  225.                                                 hitInfo.vTri2 = last_hits[i].tri[2];
  226.                                         }
  227.                                         //CTimeValue t1 = gEnv->pTimer->GetAsyncTime();
  228.                                         //CryLogAlways( "TestTime :%.2f", (t1-t0).GetMilliSeconds() );
  229.                                         //static int nCount = 0; CryLogAlways( "Cached Hit %d",++nCount );
  230.                                         hitInfo.pRenderMesh = rIntersectionRMData.pRenderMesh;
  231.                                         rIntersectionRMData.bResult = true;
  232.                                         return true;
  233.                                 }
  234.                         }
  235.                 }
  236.         }
  237.  
  238.         uint nVerts = rIntersectionRMData.nVerts;
  239.         int nInds = rIntersectionRMData.nInds;
  240.  
  241.         assert(nInds != 0 && nVerts != 0);
  242.  
  243.         // get position offset and stride
  244.         const int nPosStride = rIntersectionRMData.nPosStride;
  245.         uint8* const pPos = rIntersectionRMData.pPos;
  246.  
  247.         // get indices
  248.         vtx_idx* const pInds = rIntersectionRMData.pInds;
  249.  
  250.         assert(pInds != NULL && pPos != NULL);
  251.         assert(nInds % 3 == 0);
  252.  
  253.         float fMinDistance2 = FLT_MAX;
  254.  
  255.         Ray inRay = hitInfo.inRay;
  256.  
  257.         bool bAnyHit = false;
  258.  
  259.         Vec3 vOut;
  260.         Vec3 tri[3];
  261.  
  262.         // test tris
  263.         TRenderChunkArray& RESTRICT_REFERENCE Chunks = rIntersectionRMData.pRenderMesh->GetChunks();
  264.         int nChunkCount = Chunks.size();
  265.  
  266.         for (int nChunkId = 0; nChunkId < nChunkCount; nChunkId++)
  267.         {
  268.                 CRenderChunk* pChunk = &Chunks[nChunkId];
  269.  
  270.                 IF (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE, 0)
  271.                         continue;
  272.                 const int16 nChunkMatID = pChunk->m_nMatID;
  273.  
  274.                 bool b2Sided = false;
  275.  
  276.                 if (pMtl)
  277.                 {
  278.                         const SShaderItem& shaderItem = pMtl->GetShaderItem(nChunkMatID);
  279.                         if (hitInfo.bOnlyZWrite && !shaderItem.IsZWrite())
  280.                                 continue;
  281.                         if (!shaderItem.m_pShader || shaderItem.m_pShader->GetFlags() & EF_NODRAW || shaderItem.m_pShader->GetFlags() & EF_DECAL)
  282.                                 continue;
  283.                         if (shaderItem.m_pShader->GetCull() & eCULL_None)
  284.                                 b2Sided = true;
  285.                         if (shaderItem.m_pShaderResources && shaderItem.m_pShaderResources->GetResFlags() & MTL_FLAG_2SIDED)
  286.                                 b2Sided = true;
  287.                 }
  288.  
  289.                 int nLastIndexId = pChunk->nFirstIndexId + pChunk->nNumIndices;
  290.                 const vtx_idx* __restrict pIndices = rIntersectionRMData.pInds;
  291.  
  292.                 IF (nLastIndexId - 1 >= nInds, 0)
  293.                 {
  294.                         Error("%s (%s): invalid mesh chunk", __FUNCTION__, rIntersectionRMData.pRenderMesh->GetSourceName());
  295.                         rIntersectionRMData.bResult = false;
  296.                         return 0;
  297.                 }
  298.  
  299.                 // make line triangle intersection
  300.                 int i = pChunk->nFirstIndexId;
  301.  
  302.                 while (i < nLastIndexId)
  303.                 {
  304.                         int p = nLastIndexId;
  305.  
  306.                         for (; i < p; i += 3)//process all prefetched vertices
  307.                         {
  308.                                 IF (pInds[i + 2] >= nVerts, 0)
  309.                                 {
  310.                                         Error("%s (%s): invalid mesh indices", __FUNCTION__, rIntersectionRMData.pRenderMesh->GetSourceName());
  311.                                         rIntersectionRMData.bResult = false;
  312.                                         return 0;
  313.                                 }
  314.  
  315.                                 // get tri vertices
  316.                                 const Vec3& tv0 = *(const Vec3*)&pPos[nPosStride * pIndices[i + 0]];
  317.                                 const Vec3& tv1 = *(const Vec3*)&pPos[nPosStride * pIndices[i + 1]];
  318.                                 const Vec3& tv2 = *(const Vec3*)&pPos[nPosStride * pIndices[i + 2]];
  319.  
  320.                                 if (Intersect::Ray_Triangle(inRay, tv0, tv2, tv1, vOut))
  321.                                 {
  322.                                         float fDistance2 = hitInfo.inReferencePoint.GetSquaredDistance(vOut);
  323.                                         if (fMaxDist2)
  324.                                         {
  325.                                                 if (fDistance2 > fMaxDist2)
  326.                                                         continue; // Ignore hits that are too far.
  327.                                         }
  328.                                         bAnyHit = true;
  329.                                         // Test front.
  330.                                         if (hitInfo.bInFirstHit)
  331.                                         {
  332.                                                 vHitPos = vOut;
  333.                                                 hitInfo.nHitMatID = nChunkMatID;
  334.                                                 tri[0] = tv0;
  335.                                                 tri[1] = tv1;
  336.                                                 tri[2] = tv2;
  337.                                                 goto AnyHit;//need to break chunk loops, vertex loop and prefetched loop
  338.                                         }
  339.                                         if (fDistance2 < fMinDistance2)
  340.                                         {
  341.                                                 fMinDistance2 = fDistance2;
  342.                                                 vHitPos = vOut;
  343.                                                 hitInfo.nHitMatID = nChunkMatID;
  344.                                                 tri[0] = tv0;
  345.                                                 tri[1] = tv1;
  346.                                                 tri[2] = tv2;
  347.                                         }
  348.                                 }
  349.                                 else if (b2Sided)
  350.                                 {
  351.                                         if (Intersect::Ray_Triangle(inRay, tv0, tv1, tv2, vOut))
  352.                                         {
  353.                                                 float fDistance2 = hitInfo.inReferencePoint.GetSquaredDistance(vOut);
  354.                                                 if (fMaxDist2)
  355.                                                 {
  356.                                                         if (fDistance2 > fMaxDist2)
  357.                                                                 continue; // Ignore hits that are too far.
  358.                                                 }
  359.  
  360.                                                 bAnyHit = true;
  361.                                                 // Test back.
  362.                                                 if (hitInfo.bInFirstHit)
  363.                                                 {
  364.                                                         vHitPos = vOut;
  365.                                                         hitInfo.nHitMatID = nChunkMatID;
  366.                                                         tri[0] = tv0;
  367.                                                         tri[1] = tv2;
  368.                                                         tri[2] = tv1;
  369.                                                         goto AnyHit;//need to break chunk loops, vertex loop and prefetched loop
  370.                                                 }
  371.                                                 if (fDistance2 < fMinDistance2)
  372.                                                 {
  373.                                                         fMinDistance2 = fDistance2;
  374.                                                         vHitPos = vOut;
  375.                                                         hitInfo.nHitMatID = nChunkMatID;
  376.                                                         tri[0] = tv0;
  377.                                                         tri[1] = tv2;
  378.                                                         tri[2] = tv1;
  379.                                                 }
  380.                                         }
  381.                                 }
  382.                         }
  383.                 }
  384.         }
  385. AnyHit:
  386.         if (bAnyHit)
  387.         {
  388.                 hitInfo.pRenderMesh = rIntersectionRMData.pRenderMesh;
  389.  
  390.                 // return closest to the shooter
  391.                 hitInfo.fDistance = (float)sqrt_tpl(fMinDistance2);
  392.                 hitInfo.vHitNormal = (tri[1] - tri[0]).Cross(tri[2] - tri[0]).GetNormalized();
  393.                 hitInfo.vHitPos = vHitPos;
  394.                 hitInfo.nHitSurfaceID = 0;
  395.  
  396.                 if (hitInfo.inRetTriangle)
  397.                 {
  398.                         hitInfo.vTri0 = tri[0];
  399.                         hitInfo.vTri1 = tri[1];
  400.                         hitInfo.vTri2 = tri[2];
  401.                 }
  402.  
  403.                 if (pMtl)
  404.                 {
  405.                         pMtl = pMtl->GetSafeSubMtl(hitInfo.nHitMatID);
  406.                         if (pMtl)
  407.                                 hitInfo.nHitSurfaceID = pMtl->GetSurfaceTypeId();
  408.                 }
  409.  
  410.                 if (!bAsync)
  411.                 {
  412.                         //////////////////////////////////////////////////////////////////////////
  413.                         // Add to cached results.
  414.                         memmove(&last_hits[1], &last_hits[0], sizeof(last_hits) - sizeof(last_hits[0])); // Move hits to the end of array, throwing out the last one.
  415.                         last_hits[0].pRenderMesh = rIntersectionRMData.pRenderMesh;
  416.                         last_hits[0].hitInfo = hitInfo;
  417.                         memcpy(last_hits[0].tri, tri, sizeof(tri));
  418.                         //////////////////////////////////////////////////////////////////////////
  419.                 }
  420.  
  421.         }
  422.         //CTimeValue t1 = gEnv->pTimer->GetAsyncTime();
  423.         //CryLogAlways( "TestTime :%.2f", (t1-t0).GetMilliSeconds() );
  424.  
  425.         rIntersectionRMData.bResult = bAnyHit;
  426.         return bAnyHit;
  427. }
  428.  
  429. bool CRenderMeshUtils::RayIntersectionFast(IRenderMesh* pRenderMesh, SRayHitInfo& hitInfo, IMaterial* pMtl)
  430. {
  431.         SIntersectionData data;
  432.  
  433.         if (!data.Init(pRenderMesh, &hitInfo, pMtl))
  434.         {
  435.                 return false;
  436.         }
  437.  
  438.         // forward call to implementation
  439.         return CRenderMeshUtils::RayIntersectionFastImpl(data, hitInfo, pMtl, false);
  440. }
  441.  
  442. //////////////////////////////////////////////////////////////////////////
  443. bool CRenderMeshUtils::RayIntersectionFastImpl(SIntersectionData& rIntersectionRMData, SRayHitInfo& hitInfo, IMaterial* pMtl, bool bAsync)
  444. {
  445.         float fBestDist = hitInfo.fMaxHitDistance; // squared distance works different for values less and more than 1.f
  446.  
  447.         Vec3 vHitPos(0, 0, 0);
  448.         Vec3 vHitNormal(0, 0, 0);
  449.  
  450.         int nVerts = rIntersectionRMData.nVerts;
  451.         int nInds = rIntersectionRMData.nInds;
  452.  
  453.         assert(nInds != 0 && nVerts != 0);
  454.  
  455.         // get position offset and stride
  456.         int nPosStride = rIntersectionRMData.nPosStride;
  457.         uint8* pPos = rIntersectionRMData.pPos;
  458.  
  459.         int nUVStride = rIntersectionRMData.nUVStride;
  460.         uint8* pUV = rIntersectionRMData.pUV;
  461.  
  462.         int nColStride = rIntersectionRMData.nColStride;
  463.         uint8* pCol = rIntersectionRMData.pCol;
  464.  
  465.         // get indices
  466.         vtx_idx* pInds = rIntersectionRMData.pInds;
  467.  
  468.         assert(pInds != NULL && pPos != NULL);
  469.  
  470.         assert(nInds % 3 == 0);
  471.  
  472.         Ray inRay = hitInfo.inRay;
  473.  
  474.         bool bAnyHit = false;
  475.  
  476.         Vec3 vOut;
  477.         Vec3 tri[3];
  478.  
  479.         // test tris
  480.  
  481.         Line inLine(inRay.origin, inRay.direction);
  482.  
  483.         if (!inRay.direction.IsZero() && hitInfo.nHitTriID >= 0)
  484.         {
  485.                 if (hitInfo.nHitTriID + 2 >= nInds)
  486.                         return false;
  487.  
  488.                 int I0 = pInds[hitInfo.nHitTriID + 0];
  489.                 int I1 = pInds[hitInfo.nHitTriID + 1];
  490.                 int I2 = pInds[hitInfo.nHitTriID + 2];
  491.  
  492.                 if (I0 < nVerts && I1 < nVerts && I2 < nVerts)
  493.                 {
  494.                         // get tri vertices
  495.                         Vec3& tv0 = *((Vec3*)&pPos[nPosStride * I0]);
  496.                         Vec3& tv1 = *((Vec3*)&pPos[nPosStride * I1]);
  497.                         Vec3& tv2 = *((Vec3*)&pPos[nPosStride * I2]);
  498.  
  499.                         if (Intersect::Line_Triangle(inLine, tv0, tv2, tv1, vOut))  // || Intersect::Line_Triangle( inLine, tv0, tv1, tv2, vOut ))
  500.                         {
  501.                                 float fDistance = (hitInfo.inReferencePoint - vOut).GetLengthFast();
  502.  
  503.                                 if (fDistance < fBestDist)
  504.                                 {
  505.                                         bAnyHit = true;
  506.                                         fBestDist = fDistance;
  507.                                         vHitPos = vOut;
  508.                                         tri[0] = tv0;
  509.                                         tri[1] = tv1;
  510.                                         tri[2] = tv2;
  511.                                 }
  512.                         }
  513.                 }
  514.         }
  515.  
  516.         if (hitInfo.nHitTriID == HIT_UNKNOWN)
  517.         {
  518.                 if (inRay.direction.IsZero())
  519.                 {
  520.                         ProcessBoxIntersection(inRay, hitInfo, rIntersectionRMData, pMtl, pInds, nVerts, pPos, nPosStride, pUV, nUVStride, pCol, nColStride, nInds, bAnyHit, fBestDist, vHitPos, tri);
  521.                 }
  522.                 else
  523.                 {
  524.                         if (const PodArray<std::pair<int, int>>* pTris = rIntersectionRMData.pRenderMesh->GetTrisForPosition(inRay.origin + inRay.direction * 0.5f, pMtl))
  525.                         {
  526.                                 for (int nId = 0; nId < pTris->Count(); ++nId)
  527.                                 {
  528.                                         std::pair<int, int>& t = pTris->GetAt(nId);
  529.  
  530.                                         if (t.first + 2 >= nInds)
  531.                                                 return false;
  532.  
  533.                                         int I0 = pInds[t.first + 0];
  534.                                         int I1 = pInds[t.first + 1];
  535.                                         int I2 = pInds[t.first + 2];
  536.  
  537.                                         if (I0 >= nVerts || I1 >= nVerts || I2 >= nVerts)
  538.                                                 return false;
  539.  
  540.                                         // get tri vertices
  541.                                         Vec3& tv0 = *((Vec3*)&pPos[nPosStride * I0]);
  542.                                         Vec3& tv1 = *((Vec3*)&pPos[nPosStride * I1]);
  543.                                         Vec3& tv2 = *((Vec3*)&pPos[nPosStride * I2]);
  544.  
  545.                                         if (Intersect::Line_Triangle(inLine, tv0, tv2, tv1, vOut))  // || Intersect::Line_Triangle( inLine, tv0, tv1, tv2, vOut ))
  546.                                         {
  547.                                                 float fDistance = (hitInfo.inReferencePoint - vOut).GetLengthFast();
  548.  
  549.                                                 if (fDistance < fBestDist)
  550.                                                 {
  551.                                                         bAnyHit = true;
  552.                                                         fBestDist = fDistance;
  553.                                                         vHitPos = vOut;
  554.                                                         tri[0] = tv0;
  555.                                                         tri[1] = tv1;
  556.                                                         tri[2] = tv2;
  557.                                                         hitInfo.nHitMatID = t.second;
  558.                                                         hitInfo.nHitTriID = t.first;
  559.                                                 }
  560.                                         }
  561.                                 }
  562.                         }
  563.                 }
  564.         }
  565.  
  566.         if (bAnyHit)
  567.         {
  568.                 hitInfo.pRenderMesh = rIntersectionRMData.pRenderMesh;
  569.  
  570.                 // return closest to the shooter
  571.                 hitInfo.fDistance = fBestDist;
  572.                 hitInfo.vHitNormal = (tri[1] - tri[0]).Cross(tri[2] - tri[0]).GetNormalized();
  573.                 hitInfo.vHitPos = vHitPos;
  574.                 hitInfo.nHitSurfaceID = 0;
  575.  
  576.                 if (pMtl)
  577.                 {
  578.                         pMtl = pMtl->GetSafeSubMtl(hitInfo.nHitMatID);
  579.                         if (pMtl)
  580.                                 hitInfo.nHitSurfaceID = pMtl->GetSurfaceTypeId();
  581.                 }
  582.  
  583.                 if (hitInfo.bGetVertColorAndTC && hitInfo.nHitTriID >= 0 && !inRay.direction.IsZero())
  584.                 {
  585.                         int I0 = pInds[hitInfo.nHitTriID + 0];
  586.                         int I1 = pInds[hitInfo.nHitTriID + 1];
  587.                         int I2 = pInds[hitInfo.nHitTriID + 2];
  588.  
  589.                         // get tri vertices
  590.                         Vec3& tv0 = *((Vec3*)&pPos[nPosStride * I0]);
  591.                         Vec3& tv1 = *((Vec3*)&pPos[nPosStride * I1]);
  592.                         Vec3& tv2 = *((Vec3*)&pPos[nPosStride * I2]);
  593.  
  594.                         float u = 0, v = 0, w = 0;
  595.                         if (GetBarycentricCoordinates(vHitPos - tv0, tv1 - tv0, tv2 - tv0, u, v, w, 16.0f))
  596.                         {
  597.                                 float arrVertWeight[3] = { max(0.f, w), max(0.f, v), max(0.f, u) };
  598.                                 float fDiv = 1.f / (arrVertWeight[0] + arrVertWeight[1] + arrVertWeight[2]);
  599.                                 arrVertWeight[0] *= fDiv;
  600.                                 arrVertWeight[1] *= fDiv;
  601.                                 arrVertWeight[2] *= fDiv;
  602.  
  603.                                 Vec2 tc0 = ((Vec2f16*)&pUV[nUVStride * I0])->ToVec2();
  604.                                 Vec2 tc1 = ((Vec2f16*)&pUV[nUVStride * I1])->ToVec2();
  605.                                 Vec2 tc2 = ((Vec2f16*)&pUV[nUVStride * I2])->ToVec2();
  606.  
  607.                                 hitInfo.vHitTC = tc0 * arrVertWeight[0] + tc1 * arrVertWeight[1] + tc2 * arrVertWeight[2];
  608.  
  609.                                 Vec4 c0 = (*(ColorB*)&pCol[nColStride * I0]).toVec4();
  610.                                 Vec4 c1 = (*(ColorB*)&pCol[nColStride * I1]).toVec4();
  611.                                 Vec4 c2 = (*(ColorB*)&pCol[nColStride * I2]).toVec4();
  612.  
  613.                                 // get tangent basis
  614.                                 int nTangsStride = rIntersectionRMData.nTangsStride;
  615.                                 byte* pTangs = rIntersectionRMData.pTangs;
  616.  
  617.                                 Vec4 tangent[3];
  618.                                 Vec4 bitangent[3];
  619.                                 int arrId[3] = { I0, I1, I2 };
  620.                                 for (int ii = 0; ii < 3; ii++)
  621.                                 {
  622.                                         SPipTangents tb = *(SPipTangents*)&pTangs[nTangsStride * arrId[ii]];
  623.  
  624.                                         tb.GetTB(tangent[ii], bitangent[ii]);
  625.                                 }
  626.  
  627.                                 hitInfo.vHitTangent = (tangent[0] * arrVertWeight[0] + tangent[1] * arrVertWeight[1] + tangent[2] * arrVertWeight[2]);
  628.                                 hitInfo.vHitBitangent = (bitangent[0] * arrVertWeight[0] + bitangent[1] * arrVertWeight[1] + bitangent[2] * arrVertWeight[2]);
  629.                                 hitInfo.vHitColor = (c0 * arrVertWeight[0] + c1 * arrVertWeight[1] + c2 * arrVertWeight[2]) / 255.f;
  630.                         }
  631.                 }
  632.         }
  633.  
  634.         //CTimeValue t1 = gEnv->pTimer->GetAsyncTime();
  635.         //CryLogAlways( "TestTime :%.2f", (t1-t0).GetMilliSeconds() );
  636.  
  637.         return bAnyHit;
  638. }
  639.  
  640. // used for CPU voxelization
  641. bool CRenderMeshUtils::ProcessBoxIntersection(Ray& inRay, SRayHitInfo& hitInfo, SIntersectionData& rIntersectionRMData, IMaterial* pMtl, vtx_idx* pInds, int nVerts, uint8* pPos, int nPosStride, uint8* pUV, int nUVStride, uint8* pCol, int nColStride, int nInds, bool& bAnyHit, float& fBestDist, Vec3& vHitPos, Vec3* tri)
  642. {
  643.         AABB voxBox;
  644.         voxBox.min = inRay.origin - Vec3(hitInfo.fMaxHitDistance);
  645.         voxBox.max = inRay.origin + Vec3(hitInfo.fMaxHitDistance);
  646.  
  647.         if (hitInfo.pHitTris)
  648.         {
  649.                 // just collect tris
  650.                 TRenderChunkArray& Chunks = rIntersectionRMData.pRenderMesh->GetChunks();
  651.                 int nChunkCount = Chunks.size();
  652.  
  653.                 for (int nChunkId = 0; nChunkId < nChunkCount; nChunkId++)
  654.                 {
  655.                         CRenderChunk* pChunk(&Chunks[nChunkId]);
  656.  
  657.                         IF (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE, 0)
  658.                                 continue;
  659.  
  660.                         const int16 nChunkMatID = pChunk->m_nMatID;
  661.  
  662.                         bool b2Sided = false;
  663.  
  664.                         const SShaderItem& shaderItem = pMtl->GetShaderItem(nChunkMatID);
  665.                         //                                      if (!shaderItem.IsZWrite())
  666.                         //                                      continue;
  667.                         IShader* pShader = shaderItem.m_pShader;
  668.                         if (!pShader || pShader->GetFlags() & EF_NODRAW || pShader->GetFlags() & EF_DECAL || (pShader->GetShaderType() != eST_General && pShader->GetShaderType() != eST_Vegetation))
  669.                                 continue;
  670.                         if (pShader->GetCull() & eCULL_None)
  671.                                 b2Sided = true;
  672.                         if (shaderItem.m_pShaderResources && shaderItem.m_pShaderResources->GetResFlags() & MTL_FLAG_2SIDED)
  673.                                 b2Sided = true;
  674.  
  675.                         float fOpacity = shaderItem.m_pShaderResources->GetStrengthValue(EFTT_OPACITY) * shaderItem.m_pShaderResources->GetVoxelCoverage();
  676.                         if (fOpacity < hitInfo.fMinHitOpacity)
  677.                                 continue;
  678.  
  679.                         //          ColorB colEm = shaderItem.m_pShaderResources->GetEmissiveColor();
  680.                         //          if(!colEm.r && !colEm.g && !colEm.b)
  681.                         //            colEm = Col_DarkGray;
  682.  
  683.                         // make line triangle intersection
  684.                         for (uint ii = pChunk->nFirstIndexId; ii < pChunk->nFirstIndexId + pChunk->nNumIndices; ii += 3)
  685.                         {
  686.                                 int I0 = pInds[ii + 0];
  687.                                 int I1 = pInds[ii + 1];
  688.                                 int I2 = pInds[ii + 2];
  689.  
  690.                                 if (I0 >= nVerts || I1 >= nVerts || I2 >= nVerts)
  691.                                         return false;
  692.  
  693.                                 // get tri vertices
  694.                                 Vec3& tv0 = *((Vec3*)&pPos[nPosStride * I0]);
  695.                                 Vec3& tv1 = *((Vec3*)&pPos[nPosStride * I1]);
  696.                                 Vec3& tv2 = *((Vec3*)&pPos[nPosStride * I2]);
  697.  
  698.                                 if (Overlap::AABB_Triangle(voxBox, tv0, tv2, tv1))
  699.                                 {
  700.                                         AABB triBox(tv0, tv0);
  701.                                         triBox.Add(tv2);
  702.                                         triBox.Add(tv1);
  703.  
  704.                                         if (triBox.GetRadiusSqr() > 0.00001f)
  705.                                         {
  706.                                                 SRayHitTriangle ht;
  707.                                                 ht.v[0] = tv0;
  708.                                                 ht.v[1] = tv1;
  709.                                                 ht.v[2] = tv2;
  710.  
  711.                                                 ht.t[0] = *((Vec2*)&pUV[nUVStride * I0]);
  712.                                                 ht.t[1] = *((Vec2*)&pUV[nUVStride * I1]);
  713.                                                 ht.t[2] = *((Vec2*)&pUV[nUVStride * I2]);
  714.  
  715.                                                 ht.pMat = pMtl->GetSafeSubMtl(nChunkMatID);
  716.                                                 pMtl->AddRef();
  717.  
  718.                                                 ht.c[0] = (*(ColorB*)&pCol[nColStride * I0]);
  719.                                                 ht.c[1] = (*(ColorB*)&pCol[nColStride * I1]);
  720.                                                 ht.c[2] = (*(ColorB*)&pCol[nColStride * I2]);
  721.  
  722.                                                 ht.nOpacity = SATURATEB(int(fOpacity * 255.f));
  723.                                                 hitInfo.pHitTris->Add(ht);
  724.                                         }
  725.                                 }
  726.                         }
  727.                 }
  728.         }
  729.         else if (const PodArray<std::pair<int, int>>* pTris = rIntersectionRMData.pRenderMesh->GetTrisForPosition(inRay.origin, pMtl))
  730.         {
  731.                 for (int nId = 0; nId < pTris->Count(); ++nId)
  732.                 {
  733.                         std::pair<int, int>& t = pTris->GetAt(nId);
  734.  
  735.                         if (t.first + 2 >= nInds)
  736.                                 return false;
  737.  
  738.                         int I0 = pInds[t.first + 0];
  739.                         int I1 = pInds[t.first + 1];
  740.                         int I2 = pInds[t.first + 2];
  741.  
  742.                         if (I0 >= nVerts || I1 >= nVerts || I2 >= nVerts)
  743.                                 return false;
  744.  
  745.                         // get tri vertices
  746.                         Vec3& tv0 = *((Vec3*)&pPos[nPosStride * I0]);
  747.                         Vec3& tv1 = *((Vec3*)&pPos[nPosStride * I1]);
  748.                         Vec3& tv2 = *((Vec3*)&pPos[nPosStride * I2]);
  749.  
  750.                         if (Overlap::AABB_Triangle(voxBox, tv0, tv2, tv1))
  751.                         {
  752.                                 {
  753.                                         IMaterial* pSubMtl = pMtl->GetSafeSubMtl(t.second);
  754.                                         if (pSubMtl)
  755.                                         {
  756.                                                 if (!pSubMtl->GetShaderItem().IsZWrite())
  757.                                                         continue;
  758.                                                 if (!pSubMtl->GetShaderItem().m_pShader)
  759.                                                         continue;
  760.                                                 if (pSubMtl->GetShaderItem().m_pShader->GetShaderType() != eST_Metal && pSubMtl->GetShaderItem().m_pShader->GetShaderType() != eST_General)
  761.                                                         continue;
  762.                                         }
  763.                                 }
  764.  
  765.                                 bAnyHit = true;
  766.                                 fBestDist = 0;
  767.                                 vHitPos = voxBox.GetCenter();
  768.                                 tri[0] = tv0;
  769.                                 tri[1] = tv1;
  770.                                 tri[2] = tv2;
  771.                                 hitInfo.nHitMatID = t.second;
  772.                                 hitInfo.nHitTriID = t.first;
  773.  
  774.                                 break;
  775.                         }
  776.                 }
  777.         }
  778.  
  779.         return bAnyHit;
  780. }
  781.  
downloadRenderMeshUtils.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