BVB Source Codes

CRYENGINE Show DecalManager.cpp Source code

Return Download CRYENGINE: download DecalManager.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:   decals.cpp
  5. //  Version:     v1.00
  6. //  Created:     28/5/2001 by Vladimir Kajalin
  7. //  Compilers:   Visual Studio.NET
  8. //  Description: draw, create decals on the world
  9. // -------------------------------------------------------------------------
  10. //  History:
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #include "StdAfx.h"
  15. #include <CryAnimation/ICryAnimation.h>
  16. #include <Cry3DEngine/IStatObj.h>
  17.  
  18. #include "DecalManager.h"
  19. #include "3dEngine.h"
  20. #include "ObjMan.h"
  21. #include "MatMan.h"
  22. #include "terrain.h"
  23. #include "PolygonClipContext.h"
  24. #include "RenderMeshMerger.h"
  25. #include "RenderMeshUtils.h"
  26. #include "VisAreas.h"
  27. #include "DecalRenderNode.h"
  28.  
  29. #ifndef RENDER_MESH_TEST_DISTANCE
  30.         #define RENDER_MESH_TEST_DISTANCE (0.2f)
  31. #endif
  32.  
  33. static const int MAX_ASSEMBLE_SIZE = 5;
  34.  
  35. CDecalManager::CDecalManager()
  36. {
  37.         m_nCurDecal = 0;
  38.         memset(m_arrbActiveDecals, 0, sizeof(m_arrbActiveDecals));
  39. }
  40.  
  41. CDecalManager::~CDecalManager()
  42. {
  43.         CDecal::ResetStaticData();
  44. }
  45.  
  46. bool CDecalManager::AdjustDecalPosition(CryEngineDecalInfo& DecalInfo, bool bMakeFatTest)
  47. {
  48.         Matrix34A objMat, objMatInv;
  49.         Matrix33 objRot, objRotInv;
  50.  
  51.         CStatObj* pEntObject = (CStatObj*)DecalInfo.ownerInfo.GetOwner(objMat);
  52.         if (!pEntObject || !pEntObject->GetRenderMesh() || !pEntObject->GetRenderTrisCount())
  53.                 return false;
  54.  
  55.         objRot = Matrix33(objMat);
  56.         objRot.NoScale(); // No scale.
  57.         objRotInv = objRot;
  58.         objRotInv.Invert();
  59.  
  60.         float fWorldScale = objMat.GetColumn(0).GetLength(); // GetScale
  61.         float fWorldScaleInv = 1.0f / fWorldScale;
  62.  
  63.         // transform decal into object space
  64.         objMatInv = objMat;
  65.         objMatInv.Invert();
  66.  
  67.         // put into normal object space hit direction of projection
  68.         Vec3 vOS_HitDir = objRotInv.TransformVector(DecalInfo.vHitDirection).GetNormalized();
  69.  
  70.         // put into position object space hit position
  71.         Vec3 vOS_HitPos = objMatInv.TransformPoint(DecalInfo.vPos);
  72.         vOS_HitPos -= vOS_HitDir * RENDER_MESH_TEST_DISTANCE * fWorldScaleInv;
  73.  
  74.         IMaterial* pMat = DecalInfo.ownerInfo.pRenderNode ? DecalInfo.ownerInfo.pRenderNode->GetMaterial() : NULL;
  75.  
  76.         Vec3 vOS_OutPos(0, 0, 0), vOS_OutNormal(0, 0, 0), vTmp;
  77.         IRenderMesh* pRM = pEntObject->GetRenderMesh();
  78.  
  79.         AABB aabbRNode;
  80.         pRM->GetBBox(aabbRNode.min, aabbRNode.max);
  81.         Vec3 vOut(0, 0, 0);
  82.         if (!Intersect::Ray_AABB(Ray(vOS_HitPos, vOS_HitDir), aabbRNode, vOut))
  83.                 return false;
  84.  
  85.         if (!pRM || !pRM->GetVerticesCount())
  86.                 return false;
  87.  
  88.         if (RayRenderMeshIntersection(pRM, vOS_HitPos, vOS_HitDir, vOS_OutPos, vOS_OutNormal, false, 0, pMat))
  89.         {
  90.                 // now check that none of decal sides run across edges
  91.                 Vec3 srcp = vOS_OutPos + 0.01f * fWorldScaleInv * vOS_OutNormal; /// Rise hit point a little bit above hit plane.
  92.                 Vec3 vDecalNormal = vOS_OutNormal;
  93.                 float fMaxHitDistance = 0.02f * fWorldScaleInv;
  94.  
  95.                 // get decal directions
  96.                 Vec3 vRi(0, 0, 0), vUp(0, 0, 0);
  97.                 if (fabs(vOS_OutNormal.Dot(Vec3(0, 0, 1))) > 0.999f)
  98.                 {
  99.                         // horiz surface
  100.                         vRi = Vec3(0, 1, 0);
  101.                         vUp = Vec3(1, 0, 0);
  102.                 }
  103.                 else
  104.                 {
  105.                         vRi = vOS_OutNormal.Cross(Vec3(0, 0, 1));
  106.                         vRi.Normalize();
  107.                         vUp = vOS_OutNormal.Cross(vRi);
  108.                         vUp.Normalize();
  109.                 }
  110.  
  111.                 vRi *= DecalInfo.fSize * 0.65f;
  112.                 vUp *= DecalInfo.fSize * 0.65f;
  113.  
  114.                 if (!bMakeFatTest || (
  115.                       RayRenderMeshIntersection(pRM, srcp + vUp, -vDecalNormal, vTmp, vTmp, true, fMaxHitDistance, pMat) &&
  116.                       RayRenderMeshIntersection(pRM, srcp - vUp, -vDecalNormal, vTmp, vTmp, true, fMaxHitDistance, pMat) &&
  117.                       RayRenderMeshIntersection(pRM, srcp + vRi, -vDecalNormal, vTmp, vTmp, true, fMaxHitDistance, pMat) &&
  118.                       RayRenderMeshIntersection(pRM, srcp - vRi, -vDecalNormal, vTmp, vTmp, true, fMaxHitDistance, pMat)))
  119.                 {
  120.                         DecalInfo.vPos = objMat.TransformPoint(vOS_OutPos + vOS_OutNormal * 0.001f * fWorldScaleInv);
  121.                         DecalInfo.vNormal = objRot.TransformVector(vOS_OutNormal);
  122.                         return true;
  123.                 }
  124.         }
  125.         return false;
  126. }
  127.  
  128. struct HitPosInfo
  129. {
  130.         HitPosInfo() { memset(this, 0, sizeof(HitPosInfo)); }
  131.         Vec3  vPos, vNormal;
  132.         float fDistance;
  133. };
  134.  
  135. int __cdecl CDecalManager__CmpHitPos(const void* v1, const void* v2)
  136. {
  137.         HitPosInfo* p1 = (HitPosInfo*)v1;
  138.         HitPosInfo* p2 = (HitPosInfo*)v2;
  139.  
  140.         if (p1->fDistance > p2->fDistance)
  141.                 return 1;
  142.         else if (p1->fDistance < p2->fDistance)
  143.                 return -1;
  144.  
  145.         return 0;
  146. }
  147.  
  148. bool CDecalManager::RayRenderMeshIntersection(IRenderMesh* pRenderMesh, const Vec3& vInPos, const Vec3& vInDir,
  149.                                               Vec3& vOutPos, Vec3& vOutNormal, bool bFastTest, float fMaxHitDistance, IMaterial* pMat)
  150. {
  151.         SRayHitInfo hitInfo;
  152.         hitInfo.bUseCache = GetCVars()->e_DecalsHitCache != 0;
  153.         hitInfo.bInFirstHit = bFastTest;
  154.         hitInfo.inRay.origin = vInPos;
  155.         hitInfo.inRay.direction = vInDir.GetNormalized();
  156.         hitInfo.inReferencePoint = vInPos;
  157.         hitInfo.fMaxHitDistance = fMaxHitDistance;
  158.         bool bRes = CRenderMeshUtils::RayIntersection(pRenderMesh, hitInfo, pMat);
  159.         vOutPos = hitInfo.vHitPos;
  160.         vOutNormal = hitInfo.vHitNormal;
  161.         return bRes;
  162. }
  163.  
  164. bool CDecalManager::SpawnHierarchical(const CryEngineDecalInfo& rootDecalInfo, CDecal* pCallerManagedDecal)
  165. {
  166.         // decal on terrain or simple decal on always static object
  167.         if (!rootDecalInfo.ownerInfo.pRenderNode)
  168.                 return Spawn(rootDecalInfo, pCallerManagedDecal);
  169.  
  170.         bool bSuccess = false;
  171.  
  172.         AABB decalBoxWS;
  173.         float fSize = rootDecalInfo.fSize;
  174.         decalBoxWS.max = rootDecalInfo.vPos + Vec3(fSize, fSize, fSize);
  175.         decalBoxWS.min = rootDecalInfo.vPos - Vec3(fSize, fSize, fSize);
  176.  
  177.         for (int nEntitySlotId = 0; nEntitySlotId < 16; nEntitySlotId++)
  178.         {
  179.                 CStatObj* _pStatObj = NULL;
  180.                 Matrix34A entSlotMatrix;
  181.                 entSlotMatrix.SetIdentity();
  182.                 if (_pStatObj = (CStatObj*)rootDecalInfo.ownerInfo.pRenderNode->GetEntityStatObj(nEntitySlotId, ~0, &entSlotMatrix, true))
  183.                 {
  184.                         if (_pStatObj->m_nFlags & STATIC_OBJECT_COMPOUND)
  185.                         {
  186.                                 if (int nSubCount = _pStatObj->GetSubObjectCount())
  187.                                 {
  188.                                         // spawn decals on stat obj sub objects
  189.                                         CryEngineDecalInfo decalInfo = rootDecalInfo;
  190.                                         decalInfo.ownerInfo.nRenderNodeSlotId = nEntitySlotId;
  191.                                         if (rootDecalInfo.ownerInfo.nRenderNodeSlotSubObjectId >= 0)
  192.                                         {
  193.                                                 decalInfo.ownerInfo.nRenderNodeSlotSubObjectId = rootDecalInfo.ownerInfo.nRenderNodeSlotSubObjectId;
  194.                                                 bSuccess |= Spawn(decalInfo, pCallerManagedDecal);
  195.                                         }
  196.                                         else
  197.                                                 for (int nSubId = 0; nSubId < nSubCount; nSubId++)
  198.                                                 {
  199.                                                         IStatObj::SSubObject& subObj = _pStatObj->SubObject(nSubId);
  200.                                                         if (subObj.pStatObj && !subObj.bHidden && subObj.nType == STATIC_SUB_OBJECT_MESH)
  201.                                                         {
  202.                                                                 Matrix34 subObjMatrix = entSlotMatrix * subObj.tm;
  203.                                                                 AABB subObjAABB = AABB::CreateTransformedAABB(subObjMatrix, subObj.pStatObj->GetAABB());
  204.                                                                 if (Overlap::AABB_AABB(subObjAABB, decalBoxWS))
  205.                                                                 {
  206.                                                                         decalInfo.ownerInfo.nRenderNodeSlotSubObjectId = nSubId;
  207.                                                                         bSuccess |= Spawn(decalInfo, pCallerManagedDecal);
  208.                                                                 }
  209.                                                         }
  210.                                                 }
  211.                                 }
  212.                         }
  213.                         else
  214.                         {
  215.                                 AABB subObjAABB = AABB::CreateTransformedAABB(entSlotMatrix, _pStatObj->GetAABB());
  216.                                 if (Overlap::AABB_AABB(subObjAABB, decalBoxWS))
  217.                                 {
  218.                                         CryEngineDecalInfo decalInfo = rootDecalInfo;
  219.                                         decalInfo.ownerInfo.nRenderNodeSlotId = nEntitySlotId;
  220.                                         decalInfo.ownerInfo.nRenderNodeSlotSubObjectId = -1; // no childs
  221.                                         bSuccess |= Spawn(decalInfo, pCallerManagedDecal);
  222.                                 }
  223.                         }
  224.                 }
  225.                 else if (ICharacterInstance* pChar = rootDecalInfo.ownerInfo.pRenderNode->GetEntityCharacter(nEntitySlotId, &entSlotMatrix))
  226.                 {
  227.                         // spawn decals on CGA components
  228.                         ISkeletonPose* pSkeletonPose = pChar->GetISkeletonPose();
  229.                         uint32 numJoints = pChar->GetIDefaultSkeleton().GetJointCount();
  230.                         CryEngineDecalInfo decalInfo = rootDecalInfo;
  231.                         decalInfo.ownerInfo.nRenderNodeSlotId = nEntitySlotId;
  232.  
  233.                         if (rootDecalInfo.ownerInfo.nRenderNodeSlotSubObjectId >= 0)
  234.                         {
  235.                                 decalInfo.ownerInfo.nRenderNodeSlotSubObjectId = rootDecalInfo.ownerInfo.nRenderNodeSlotSubObjectId;
  236.                                 bSuccess |= Spawn(decalInfo, pCallerManagedDecal);
  237.                         }
  238.                         else
  239.                                 // spawn decal on every sub-object intersecting decal bbox
  240.                                 for (uint32 nJointId = 0; nJointId < numJoints; nJointId++)
  241.                                 {
  242.                                         IStatObj* pStatObj = pSkeletonPose->GetStatObjOnJoint(nJointId);
  243.  
  244.                                         if (pStatObj && !(pStatObj->GetFlags() & STATIC_OBJECT_HIDDEN) && pStatObj->GetRenderMesh())
  245.                                         {
  246.                                                 assert(!pStatObj->GetSubObjectCount());
  247.  
  248.                                                 Matrix34 tm34 = entSlotMatrix * Matrix34(pSkeletonPose->GetAbsJointByID(nJointId));
  249.                                                 AABB objBoxWS = AABB::CreateTransformedAABB(tm34, pStatObj->GetAABB());
  250.                                                 //                              DrawBBox(objBoxWS);
  251.                                                 //                      DrawBBox(decalBoxWS);
  252.                                                 if (Overlap::AABB_AABB(objBoxWS, decalBoxWS))
  253.                                                 {
  254.                                                         decalInfo.ownerInfo.nRenderNodeSlotSubObjectId = nJointId;
  255.                                                         bSuccess |= Spawn(decalInfo, pCallerManagedDecal);
  256.                                                 }
  257.                                         }
  258.                                 }
  259.                 }
  260.         }
  261.  
  262.         return bSuccess;
  263. }
  264.  
  265. bool CDecalManager::Spawn(CryEngineDecalInfo DecalInfo, CDecal* pCallerManagedDecal)
  266. {
  267.         FUNCTION_PROFILER_3DENGINE;
  268.  
  269.         Vec3 vCamPos = GetSystem()->GetViewCamera().GetPosition();
  270.  
  271.         // do not spawn if too far
  272.         float fZoom = GetObjManager() ? Get3DEngine()->GetZoomFactor() : 1.f;
  273.         float fDecalDistance = DecalInfo.vPos.GetDistance(vCamPos);
  274.         if (!pCallerManagedDecal && (fDecalDistance > Get3DEngine()->GetMaxViewDistance() || fDecalDistance * fZoom > DecalInfo.fSize * ENTITY_DECAL_DIST_FACTOR * 3.f))
  275.                 return false;
  276.  
  277.         int overlapCount(0);
  278.         int targetSize(0);
  279.         int overlapIds[MAX_ASSEMBLE_SIZE];
  280.  
  281.         // do not spawn new decals if they could overlap the existing and similar ones
  282.         if (!pCallerManagedDecal && !GetCVars()->e_DecalsOverlapping && DecalInfo.fSize && !DecalInfo.bSkipOverlappingTest)
  283.         {
  284.                 for (int i = 0; i < DECAL_COUNT; i++)
  285.                 {
  286.                         if (m_arrbActiveDecals[i])
  287.                         {
  288.                                 // skip overlapping check if decals are very different in size
  289.                                 if ((m_arrDecals[i].m_iAssembleSize > 0) == DecalInfo.bAssemble)
  290.                                 {
  291.                                         float fSizeRatio = m_arrDecals[i].m_fWSSize / DecalInfo.fSize;
  292.                                         if (((m_arrDecals[i].m_iAssembleSize > 0) || (fSizeRatio > 0.5f && fSizeRatio < 2.f)) && m_arrDecals[i].m_nGroupId != DecalInfo.nGroupId)
  293.                                         {
  294.                                                 float fDist = m_arrDecals[i].m_vWSPos.GetSquaredDistance(DecalInfo.vPos);
  295.                                                 if (fDist < sqr(m_arrDecals[i].m_fWSSize * 0.5f + DecalInfo.fSize * 0.5f) && (DecalInfo.vNormal.Dot(m_arrDecals[i].m_vFront) > 0.f))
  296.                                                 {
  297.                                                         if (DecalInfo.bAssemble && m_arrDecals[i].m_iAssembleSize < MAX_ASSEMBLE_SIZE)
  298.                                                         {
  299.                                                                 if (overlapCount < MAX_ASSEMBLE_SIZE)
  300.                                                                 {
  301.                                                                         overlapIds[overlapCount] = i;
  302.                                                                         overlapCount++;
  303.                                                                 }
  304.                                                                 else
  305.                                                                 {
  306.                                                                         m_arrbActiveDecals[i] = false;
  307.                                                                 }
  308.                                                         }
  309.                                                         else
  310.                                                                 return true;
  311.                                                 }
  312.                                         }
  313.                                 }
  314.                         }
  315.                 }
  316.         }
  317.  
  318.         float fAssembleSizeModifier(1.0f);
  319.         if (DecalInfo.bAssemble)
  320.         {
  321.                 Vec3 avgPos(0.0f, 0.0f, 0.0f);
  322.                 int validAssembles(0);
  323.                 for (int i = 0; i < overlapCount; i++)
  324.                 {
  325.                         int id = overlapIds[i];
  326.  
  327.                         float fDist = m_arrDecals[id].m_vWSPos.GetSquaredDistance(DecalInfo.vPos);
  328.                         float minDist = sqr(m_arrDecals[id].m_fWSSize * 0.4f);
  329.                         if (fDist > minDist)
  330.                         {
  331.                                 avgPos += m_arrDecals[id].m_vWSPos;
  332.                                 targetSize += m_arrDecals[id].m_iAssembleSize;
  333.                                 validAssembles++;
  334.                         }
  335.                 }
  336.  
  337.                 if (overlapCount && !validAssembles)
  338.                         return true;
  339.  
  340.                 for (int i = 0; i < overlapCount; i++)
  341.                 {
  342.                         int id = overlapIds[i];
  343.                         m_arrbActiveDecals[id] = false;
  344.                 }
  345.  
  346.                 ++validAssembles;
  347.                 ++targetSize;
  348.                 avgPos += DecalInfo.vPos;
  349.  
  350.                 if (targetSize > 1)
  351.                 {
  352.                         avgPos /= float(validAssembles);
  353.                         DecalInfo.vPos = avgPos;
  354.                         targetSize = min(targetSize, MAX_ASSEMBLE_SIZE);
  355.  
  356.                         const float sizetable[MAX_ASSEMBLE_SIZE] = { 1.0f, 1.5f, 2.3f, 3.5f, 3.5f };
  357.                         const char sValue[2] = { char('0' + targetSize), 0 };
  358.                         cry_strcat(DecalInfo.szMaterialName, sValue);
  359.                         fAssembleSizeModifier = sizetable[targetSize - 1];
  360.                 }
  361.         }
  362.  
  363.         if (GetCVars()->e_Decals > 1)
  364.                 DrawSphere(DecalInfo.vPos, DecalInfo.fSize);
  365.  
  366.         // update lifetime for near decals under control by the decal manager
  367.         if (!pCallerManagedDecal)
  368.         {
  369.                 if (DecalInfo.fSize > 1 && GetCVars()->e_DecalsNeighborMaxLifeTime)
  370.                 {
  371.                         // force near decals to fade faster
  372.                         float fCurrTime = GetTimer()->GetCurrTime();
  373.                         for (int i = 0; i < DECAL_COUNT; i++)
  374.                                 if (m_arrbActiveDecals[i] && m_arrDecals[i].m_nGroupId != DecalInfo.nGroupId)
  375.                                 {
  376.                                         if (m_arrDecals[i].m_vWSPos.GetSquaredDistance(DecalInfo.vPos) < sqr(m_arrDecals[i].m_fWSSize / 1.5f + DecalInfo.fSize / 2.0f))
  377.                                                 if ((m_arrDecals[i]).m_fLifeBeginTime < fCurrTime - 0.1f)
  378.                                                         if (m_arrDecals[i].m_fLifeTime > GetCVars()->e_DecalsNeighborMaxLifeTime)
  379.                                                                 if (m_arrDecals[i].m_fLifeTime < 10000) // decals spawn by cut scenes need to stay
  380.                                                                         m_arrDecals[i].m_fLifeTime = GetCVars()->e_DecalsNeighborMaxLifeTime;
  381.                                 }
  382.                 }
  383.  
  384.                 // loop position in array
  385.                 m_nCurDecal = (m_nCurDecal + 1) & (DECAL_COUNT - 1);
  386.                 //if(m_nCurDecal>=DECAL_COUNT)
  387.                 //      m_nCurDecal=0;
  388.         }
  389.  
  390.         // create reference to decal which is to be filled
  391.         CDecal& newDecal(pCallerManagedDecal ? *pCallerManagedDecal : m_arrDecals[m_nCurDecal]);
  392.  
  393.         newDecal.m_bDeferred = DecalInfo.bDeferred;
  394.  
  395.         newDecal.m_iAssembleSize = targetSize;
  396.         // free old pRM
  397.         newDecal.FreeRenderData();
  398.  
  399.         newDecal.m_nGroupId = DecalInfo.nGroupId;
  400.  
  401.         // get material if specified
  402.         newDecal.m_pMaterial = 0;
  403.  
  404.         if (DecalInfo.szMaterialName[0] != '0')
  405.         {
  406.                 newDecal.m_pMaterial = GetMatMan()->LoadMaterial(DecalInfo.szMaterialName, false, true);
  407.                 if (!newDecal.m_pMaterial)
  408.                 {
  409.                         newDecal.m_pMaterial = GetMatMan()->LoadMaterial("Materials/Decals/Default", true, true);
  410.                         newDecal.m_pMaterial->AddRef();
  411.                         Warning("CDecalManager::Spawn: Specified decal material \"%s\" not found!\n", DecalInfo.szMaterialName);
  412.                 }
  413.         }
  414.         else
  415.                 Warning("CDecalManager::Spawn: Decal material name is not specified");
  416.  
  417.         newDecal.m_sortPrio = DecalInfo.sortPrio;
  418.  
  419.         // set up user defined decal basis if provided
  420.         bool useDefinedUpRight(false);
  421.         Vec3 userDefinedUp;
  422.         Vec3 userDefinedRight;
  423.         if (DecalInfo.pExplicitRightUpFront)
  424.         {
  425.                 userDefinedRight = DecalInfo.pExplicitRightUpFront->GetColumn(0);
  426.                 userDefinedUp = DecalInfo.pExplicitRightUpFront->GetColumn(1);
  427.                 DecalInfo.vNormal = DecalInfo.pExplicitRightUpFront->GetColumn(2);
  428.                 useDefinedUpRight = true;
  429.         }
  430.  
  431.         // just in case
  432.         DecalInfo.vNormal.NormalizeSafe();
  433.  
  434.         // remember object we need to follow
  435.         newDecal.m_ownerInfo.nRenderNodeSlotId = DecalInfo.ownerInfo.nRenderNodeSlotId;
  436.         newDecal.m_ownerInfo.nRenderNodeSlotSubObjectId = DecalInfo.ownerInfo.nRenderNodeSlotSubObjectId;
  437.  
  438.         newDecal.m_vWSPos = DecalInfo.vPos;
  439.         newDecal.m_fWSSize = DecalInfo.fSize * fAssembleSizeModifier;
  440.  
  441.         // If owner entity and object is specified - make decal use entity geometry
  442.         float _fObjScale = 1.f;
  443.  
  444.         Matrix34A _objMat;
  445.         Matrix33 worldRot;
  446.         IStatObj* pStatObj = DecalInfo.ownerInfo.GetOwner(_objMat);
  447.         if (pStatObj)
  448.         {
  449.                 worldRot = Matrix33(_objMat);
  450.                 _objMat.Invert();
  451.         }
  452.  
  453.         float fWrapMinSize = GetFloatCVar(e_DecalsDeferredDynamicMinSize);
  454.  
  455.         EERType ownerRenderNodeType = (DecalInfo.ownerInfo.pRenderNode) ? DecalInfo.ownerInfo.pRenderNode->GetRenderNodeType() : eERType_NotRenderNode;
  456.  
  457.         bool bSpawnOnVegetationWithBending = false;
  458.         if (ownerRenderNodeType == eERType_Vegetation && DecalInfo.fSize > fWrapMinSize && !DecalInfo.bDeferred)
  459.         {
  460.                 //    CVegetation * pVeg = (CVegetation*)DecalInfo.ownerInfo.pRenderNode;
  461.                 //    StatInstGroup & rGroup = GetObjManager()->m_lstStaticTypes[pVeg->m_nObjectTypeID];
  462.                 //  if(rGroup.fBending>0)
  463.                 bSpawnOnVegetationWithBending = true;
  464.  
  465.                 // Check owner material ID (need for decals vertex modifications)
  466.                 SRayHitInfo hitInfo;
  467.                 memset(&hitInfo, 0, sizeof(hitInfo));
  468.                 Vec3 vHitPos = _objMat.TransformPoint(DecalInfo.vPos);
  469.                 // put hit normal into the object space
  470.                 Vec3 vRayDir = DecalInfo.vHitDirection.GetNormalized() * worldRot;
  471.                 hitInfo.inReferencePoint = vHitPos;
  472.                 hitInfo.inRay.origin = vHitPos - vRayDir * 4.0f;
  473.                 hitInfo.inRay.direction = vRayDir;
  474.                 hitInfo.bInFirstHit = false;
  475.                 hitInfo.bUseCache = true;
  476.                 if (pStatObj->RayIntersection(hitInfo, 0))
  477.                         newDecal.m_ownerInfo.nMatID = hitInfo.nHitMatID;
  478.         }
  479.  
  480.         if (DecalInfo.ownerInfo.pRenderNode && DecalInfo.ownerInfo.nRenderNodeSlotId >= 0 && (DecalInfo.fSize > fWrapMinSize || pCallerManagedDecal || bSpawnOnVegetationWithBending) && !DecalInfo.bDeferred)
  481.         {
  482.                 newDecal.m_eDecalType = eDecalType_OS_OwnersVerticesUsed;
  483.  
  484.                 IRenderMesh* pSourceRenderMesh = NULL;
  485.  
  486.                 if (pStatObj)
  487.                         pSourceRenderMesh = pStatObj->GetRenderMesh();
  488.  
  489.                 if (!pSourceRenderMesh)
  490.                         return false;
  491.  
  492.                 // transform decal into object space
  493.                 Matrix33 objRotInv = Matrix33(_objMat);
  494.                 objRotInv.NoScale();
  495.  
  496.                 if (useDefinedUpRight)
  497.                 {
  498.                         userDefinedRight = objRotInv.TransformVector(userDefinedRight).GetNormalized();
  499.                         userDefinedUp = objRotInv.TransformVector(userDefinedUp).GetNormalized();
  500.                         assert(fabsf(DecalInfo.vNormal.Dot(-DecalInfo.vHitDirection.GetNormalized()) - 1.0f) < 1e-4f);
  501.                 }
  502.  
  503.                 // make decals smaller but longer if hit direction is near perpendicular to surface normal
  504.                 float fSizeModificator = 0.25f + 0.75f * fabs(DecalInfo.vHitDirection.GetNormalized().Dot(DecalInfo.vNormal));
  505.  
  506.                 // put into normal object space hit direction of projection
  507.                 DecalInfo.vNormal = -objRotInv.TransformVector((DecalInfo.vHitDirection - DecalInfo.vNormal * 0.25f).GetNormalized());
  508.  
  509.                 if (!DecalInfo.vNormal.IsZero())
  510.                         DecalInfo.vNormal.Normalize();
  511.  
  512.                 // put into position object space hit position
  513.                 DecalInfo.vPos = _objMat.TransformPoint(DecalInfo.vPos);
  514.  
  515.                 // find object scale
  516.                 Vec3 vTest(0, 0, 1.f);
  517.                 vTest = _objMat.TransformVector(vTest);
  518.                 float fObjScale = 1.0f / vTest.len();
  519.  
  520.                 if (fObjScale < 0.01f)
  521.                         return false;
  522.  
  523.                 // transform size into object space
  524.                 DecalInfo.fSize /= fObjScale;
  525.  
  526.                 DecalInfo.fSize *= (DecalInfo.bAssemble ? fAssembleSizeModifier : fSizeModificator);
  527.  
  528.                 if (DecalInfo.bForceEdge)
  529.                 {
  530.                         SRayHitInfo hitInfo;
  531.                         hitInfo.bUseCache = GetCVars()->e_DecalsHitCache != 0;
  532.                         hitInfo.bInFirstHit = false;
  533.                         hitInfo.inRay.origin = DecalInfo.vPos + DecalInfo.vNormal;
  534.                         hitInfo.inRay.direction = -DecalInfo.vNormal;
  535.                         hitInfo.inReferencePoint = DecalInfo.vPos + DecalInfo.vNormal;
  536.                         hitInfo.inRetTriangle = true;
  537.                         CRenderMeshUtils::RayIntersection(pSourceRenderMesh, hitInfo, pStatObj ? pStatObj->GetMaterial() : NULL);
  538.  
  539.                         MoveToEdge(pSourceRenderMesh, DecalInfo.fSize, hitInfo.vHitPos, hitInfo.vHitNormal, hitInfo.vTri0, hitInfo.vTri1, hitInfo.vTri2);
  540.                         DecalInfo.vPos = hitInfo.vHitPos;
  541.                         DecalInfo.vNormal = hitInfo.vHitNormal;
  542.                 }
  543.  
  544.                 // make decal geometry
  545.                 newDecal.m_pRenderMesh = MakeBigDecalRenderMesh(pSourceRenderMesh, DecalInfo.vPos, DecalInfo.fSize, DecalInfo.vNormal, newDecal.m_pMaterial, pStatObj ? pStatObj->GetMaterial() : NULL);
  546.  
  547.                 if (!newDecal.m_pRenderMesh)
  548.                         return false; // no geometry found
  549.         }
  550.         else if (!DecalInfo.ownerInfo.pRenderNode && DecalInfo.ownerInfo.pDecalReceivers && (DecalInfo.fSize > fWrapMinSize || pCallerManagedDecal) && !DecalInfo.bDeferred)
  551.         {
  552.                 newDecal.m_eDecalType = eDecalType_WS_Merged;
  553.  
  554.                 assert(!newDecal.m_pRenderMesh);
  555.  
  556.                 // put into normal hit direction of projection
  557.                 DecalInfo.vNormal = -DecalInfo.vHitDirection;
  558.                 if (!DecalInfo.vNormal.IsZero())
  559.                         DecalInfo.vNormal.Normalize();
  560.  
  561.                 Vec3 vSize(DecalInfo.fSize * 1.333f, DecalInfo.fSize * 1.333f, DecalInfo.fSize * 1.333f);
  562.                 AABB decalAABB(DecalInfo.vPos - vSize, DecalInfo.vPos + vSize);
  563.  
  564.                 // build list of affected brushes
  565.                 PodArray<SRenderMeshInfoInput> lstRMI;
  566.                 for (int nObj = 0; nObj < DecalInfo.ownerInfo.pDecalReceivers->Count(); nObj++)
  567.                 {
  568.                         IRenderNode* pDecalOwner = DecalInfo.ownerInfo.pDecalReceivers->Get(nObj)->pNode;
  569.                         Matrix34A objMat;
  570.                         if (IStatObj* pEntObject = pDecalOwner->GetEntityStatObj(DecalInfo.ownerInfo.nRenderNodeSlotId, 0, &objMat))
  571.                         {
  572.                                 SRenderMeshInfoInput rmi;
  573.                                 rmi.pMesh = pEntObject->GetRenderMesh();
  574.                                 rmi.pMat = pEntObject->GetMaterial();
  575.                                 rmi.mat = objMat;
  576.  
  577.                                 if (rmi.pMesh)
  578.                                 {
  579.                                         AABB transAABB = AABB::CreateTransformedAABB(rmi.mat, pEntObject->GetAABB());
  580.                                         if (Overlap::AABB_AABB(decalAABB, transAABB))
  581.                                                 lstRMI.Add(rmi);
  582.                                 }
  583.                                 else if (int nSubObjCount = pEntObject->GetSubObjectCount())
  584.                                 {
  585.                                         // multi sub objects
  586.                                         for (int nSubObj = 0; nSubObj < nSubObjCount; nSubObj++)
  587.                                         {
  588.                                                 IStatObj::SSubObject* pSubObj = pEntObject->GetSubObject(nSubObj);
  589.                                                 if (pSubObj->pStatObj)
  590.                                                 {
  591.                                                         rmi.pMesh = pSubObj->pStatObj->GetRenderMesh();
  592.                                                         rmi.pMat = pSubObj->pStatObj->GetMaterial();
  593.                                                         rmi.mat = objMat * pSubObj->tm;
  594.                                                         if (rmi.pMesh)
  595.                                                         {
  596.                                                                 AABB transAABB = AABB::CreateTransformedAABB(rmi.mat, pSubObj->pStatObj->GetAABB());
  597.                                                                 if (Overlap::AABB_AABB(decalAABB, transAABB))
  598.                                                                         lstRMI.Add(rmi);
  599.                                                         }
  600.                                                 }
  601.                                         }
  602.                                 }
  603.                         }
  604.                 }
  605.  
  606.                 if (!lstRMI.Count())
  607.                         return false;
  608.  
  609.                 SDecalClipInfo DecalClipInfo;
  610.                 DecalClipInfo.vPos = DecalInfo.vPos;
  611.                 DecalClipInfo.fRadius = DecalInfo.fSize;
  612.                 DecalClipInfo.vProjDir = DecalInfo.vNormal;
  613.  
  614.                 PodArray<SRenderMeshInfoOutput> outRenderMeshes;
  615.                 CRenderMeshMerger Merger;
  616.                 SMergeInfo info;
  617.                 info.sMeshName = "MergedDecal";
  618.                 info.sMeshType = "MergedDecal";
  619.                 info.pDecalClipInfo = &DecalClipInfo;
  620.                 info.vResultOffset = DecalInfo.vPos;
  621.                 newDecal.m_pRenderMesh = Merger.MergeRenderMeshes(lstRMI.GetElements(), lstRMI.Count(), outRenderMeshes, info);
  622.  
  623.                 if (!newDecal.m_pRenderMesh)
  624.                         return false; // no geometry found
  625.  
  626.                 assert(newDecal.m_pRenderMesh->GetChunks().size() == 1);
  627.         }
  628.         else if (ownerRenderNodeType == eERType_RenderProxy || ownerRenderNodeType == eERType_Vegetation)
  629.         {
  630.                 newDecal.m_eDecalType = eDecalType_OS_SimpleQuad;
  631.  
  632.                 Matrix34A objMat;
  633.  
  634.                 // transform decal from world space into entity space
  635.                 IStatObj* pEntObject = DecalInfo.ownerInfo.GetOwner(objMat);
  636.                 if (!pEntObject)
  637.                         return false;
  638.                 assert(pEntObject);
  639.                 objMat.Invert();
  640.  
  641.                 if (useDefinedUpRight)
  642.                 {
  643.                         userDefinedRight = objMat.TransformVector(userDefinedRight).GetNormalized();
  644.                         userDefinedUp = objMat.TransformVector(userDefinedUp).GetNormalized();
  645.                         assert(fabsf(DecalInfo.vNormal.Dot(-DecalInfo.vHitDirection.GetNormalized()) - 1.0f) < 1e-4f);
  646.                 }
  647.  
  648.                 DecalInfo.vNormal = objMat.TransformVector(DecalInfo.vNormal).GetNormalized();
  649.                 DecalInfo.vPos = objMat.TransformPoint(DecalInfo.vPos);
  650.  
  651.                 // find object scale
  652.                 if (DecalInfo.ownerInfo.pRenderNode->GetRenderNodeType() == eERType_Vegetation)
  653.                         _fObjScale = ((CVegetation*)(DecalInfo.ownerInfo.pRenderNode))->GetScale();
  654.                 else
  655.                 {
  656.                         Vec3 vTest(0, 0, 1.f);
  657.                         vTest = objMat.TransformVector(vTest);
  658.                         _fObjScale = 1.f / vTest.len();
  659.                 }
  660.  
  661.                 DecalInfo.fSize /= _fObjScale;
  662.         }
  663.         else
  664.         {
  665.                 CTerrain* pTerrain = GetTerrain();
  666.                 if (!DecalInfo.preventDecalOnGround && DecalInfo.fSize > (fWrapMinSize * 2.f) && !DecalInfo.ownerInfo.pRenderNode &&
  667.                     (DecalInfo.vPos.z - pTerrain->GetZApr(DecalInfo.vPos.x, DecalInfo.vPos.y, GetDefSID())) < DecalInfo.fSize && !DecalInfo.bDeferred)
  668.                 {
  669.                         newDecal.m_eDecalType = eDecalType_WS_OnTheGround;
  670.  
  671.                         int nUnitSize = CTerrain::GetHeightMapUnitSize();
  672.                         int x1 = int(DecalInfo.vPos.x - DecalInfo.fSize) / nUnitSize * nUnitSize - nUnitSize;
  673.                         int x2 = int(DecalInfo.vPos.x + DecalInfo.fSize) / nUnitSize * nUnitSize + nUnitSize;
  674.                         int y1 = int(DecalInfo.vPos.y - DecalInfo.fSize) / nUnitSize * nUnitSize - nUnitSize;
  675.                         int y2 = int(DecalInfo.vPos.y + DecalInfo.fSize) / nUnitSize * nUnitSize + nUnitSize;
  676.  
  677.                         for (int x = x1; x <= x2; x += CTerrain::GetHeightMapUnitSize())
  678.                                 for (int y = y1; y <= y2; y += CTerrain::GetHeightMapUnitSize())
  679.                                         if (pTerrain->GetHole(x, y, GetDefSID()))
  680.                                                 return false;
  681.                 }
  682.                 else
  683.                         newDecal.m_eDecalType = eDecalType_WS_SimpleQuad;
  684.  
  685.                 DecalInfo.ownerInfo.pRenderNode = NULL;
  686.         }
  687.  
  688.         // spawn
  689.         if (!useDefinedUpRight)
  690.         {
  691.                 if (DecalInfo.vNormal.Dot(Vec3(0, 0, 1)) > 0.999f)
  692.                 {
  693.                         // floor
  694.                         newDecal.m_vRight = Vec3(0, 1, 0);
  695.                         newDecal.m_vUp = Vec3(-1, 0, 0);
  696.                 }
  697.                 else if (DecalInfo.vNormal.Dot(Vec3(0, 0, -1)) > 0.999f)
  698.                 {
  699.                         // ceil
  700.                         newDecal.m_vRight = Vec3(1, 0, 0);
  701.                         newDecal.m_vUp = Vec3(0, -1, 0);
  702.                 }
  703.                 else if (!DecalInfo.vNormal.IsZero())
  704.                 {
  705.                         newDecal.m_vRight = DecalInfo.vNormal.Cross(Vec3(0, 0, 1));
  706.                         newDecal.m_vRight.Normalize();
  707.                         newDecal.m_vUp = DecalInfo.vNormal.Cross(newDecal.m_vRight);
  708.                         newDecal.m_vUp.Normalize();
  709.                 }
  710.  
  711.                 // rotate vectors
  712.                 if (!DecalInfo.vNormal.IsZero())
  713.                 {
  714.                         AngleAxis rotation(DecalInfo.fAngle, DecalInfo.vNormal);
  715.                         newDecal.m_vRight = rotation * newDecal.m_vRight;
  716.                         newDecal.m_vUp = rotation * newDecal.m_vUp;
  717.                 }
  718.         }
  719.         else
  720.         {
  721.                 newDecal.m_vRight = userDefinedRight;
  722.                 newDecal.m_vUp = userDefinedUp;
  723.         }
  724.  
  725.         newDecal.m_vFront = DecalInfo.vNormal;
  726.  
  727.         newDecal.m_vPos = DecalInfo.vPos;
  728.         newDecal.m_vPos += DecalInfo.vNormal * 0.001f / _fObjScale;
  729.  
  730.         newDecal.m_fSize = DecalInfo.fSize;
  731.         newDecal.m_fLifeTime = DecalInfo.fLifeTime * GetCVars()->e_DecalsLifeTimeScale;
  732.         assert(!DecalInfo.pIStatObj); // not used -> not supported
  733.         newDecal.m_vAmbient = Get3DEngine()->GetAmbientColorFromPosition(newDecal.m_vWSPos);
  734.  
  735.         newDecal.m_ownerInfo.pRenderNode = DecalInfo.ownerInfo.pRenderNode;
  736.         if (DecalInfo.ownerInfo.pRenderNode)
  737.                 DecalInfo.ownerInfo.pRenderNode->m_nInternalFlags |= IRenderNode::DECAL_OWNER;
  738.  
  739.         newDecal.m_fGrowTime = DecalInfo.fGrowTime;
  740.         newDecal.m_fGrowTimeAlpha = DecalInfo.fGrowTimeAlpha;
  741.         newDecal.m_fLifeBeginTime = GetTimer()->GetCurrTime();
  742.  
  743.         if (DecalInfo.pIStatObj && !pCallerManagedDecal)
  744.         {
  745.                 //assert(!"Geometry decals neede to be re-debugged");
  746.                 DecalInfo.pIStatObj->AddRef();
  747.         }
  748.  
  749.         if (!pCallerManagedDecal)
  750.         {
  751.                 m_arrbActiveDecals[m_nCurDecal] = true;
  752.                 ++m_nCurDecal;
  753.         }
  754.  
  755. #ifdef _DEBUG
  756.         if (newDecal.m_ownerInfo.pRenderNode)
  757.         {
  758.                 cry_strcpy(newDecal.m_decalOwnerEntityClassName, newDecal.m_ownerInfo.pRenderNode->GetEntityClassName());
  759.                 cry_strcpy(newDecal.m_decalOwnerName, newDecal.m_ownerInfo.pRenderNode->GetName());
  760.                 newDecal.m_decalOwnerType = newDecal.m_ownerInfo.pRenderNode->GetRenderNodeType();
  761.         }
  762.         else
  763.         {
  764.                 newDecal.m_decalOwnerEntityClassName[0] = '\0';
  765.                 newDecal.m_decalOwnerName[0] = '\0';
  766.                 newDecal.m_decalOwnerType = eERType_NotRenderNode;
  767.         }
  768. #endif
  769.  
  770.         return true;
  771. }
  772.  
  773. void CDecalManager::Update(const float fFrameTime)
  774. {
  775.         CryPrefetch(&m_arrbActiveDecals[0]);
  776.         CryPrefetch(&m_arrbActiveDecals[128]);
  777.         CryPrefetch(&m_arrbActiveDecals[256]);
  778.         CryPrefetch(&m_arrbActiveDecals[384]);
  779.  
  780.         for (int i = 0; i < DECAL_COUNT; i++)
  781.         {
  782.                 if (m_arrbActiveDecals[i])
  783.                 {
  784.                         IRenderNode* pRenderNode = m_arrDecals[i].m_ownerInfo.pRenderNode;
  785.                         if (m_arrDecals[i].Update(m_arrbActiveDecals[i], fFrameTime))
  786.                                 if (pRenderNode && m_arrTempUpdatedOwners.Find(pRenderNode) < 0)
  787.                                         m_arrTempUpdatedOwners.Add(pRenderNode);
  788.                 }
  789.         }
  790.  
  791.         for (int i = 0; i < m_arrTempUpdatedOwners.Count(); i++)
  792.         {
  793.                 m_arrTempUpdatedOwners[i]->m_nInternalFlags &= ~IRenderNode::UPDATE_DECALS;
  794.         }
  795.  
  796.         m_arrTempUpdatedOwners.Clear();
  797. }
  798.  
  799. void CDecalManager::Render(const SRenderingPassInfo& passInfo)
  800. {
  801.         FUNCTION_PROFILER_3DENGINE;
  802.  
  803.         if (!passInfo.RenderDecals() || !GetObjManager())
  804.                 return;
  805.  
  806.         float fCurrTime = GetTimer()->GetCurrTime();
  807.         float fZoom = passInfo.GetZoomFactor();
  808.         float fWaterLevel = m_p3DEngine->GetWaterLevel();
  809.  
  810.         static int nLastUpdateStreamingPrioriryRoundId = 0;
  811.         bool bPrecacheMaterial = nLastUpdateStreamingPrioriryRoundId != GetObjManager()->m_nUpdateStreamingPrioriryRoundId;
  812.         nLastUpdateStreamingPrioriryRoundId = GetObjManager()->m_nUpdateStreamingPrioriryRoundId;
  813.  
  814.         static int nLastUpdateStreamingPrioriryRoundIdFast = 0;
  815.         bool bPrecacheMaterialFast = nLastUpdateStreamingPrioriryRoundIdFast != GetObjManager()->m_nUpdateStreamingPrioriryRoundIdFast;
  816.         nLastUpdateStreamingPrioriryRoundIdFast = GetObjManager()->m_nUpdateStreamingPrioriryRoundIdFast;
  817.  
  818.         const CCamera& rCamera = passInfo.GetCamera();
  819.  
  820.         // draw
  821.         for (int i = 0; i < DECAL_COUNT; i++)
  822.                 if (m_arrbActiveDecals[i])
  823.                 {
  824.                         CDecal* pDecal = &m_arrDecals[i];
  825.                         pDecal->m_vWSPos = pDecal->GetWorldPosition();
  826.                         float fDist = rCamera.GetPosition().GetDistance(pDecal->m_vWSPos) * fZoom;
  827.                         float fMaxViewDist = pDecal->m_fWSSize * ENTITY_DECAL_DIST_FACTOR * 3.0f;
  828.                         if (fDist < fMaxViewDist)
  829.                                 if (rCamera.IsSphereVisible_F(Sphere(pDecal->m_vWSPos, pDecal->m_fWSSize)))
  830.                                 {
  831.                                         bool bAfterWater = CObjManager::IsAfterWater(pDecal->m_vWSPos, rCamera.GetPosition(), passInfo, fWaterLevel);
  832.                                         if (pDecal->m_pMaterial)
  833.                                         {
  834.                                                 if (passInfo.IsGeneralPass())
  835.                                                 {
  836.                                                         if (bPrecacheMaterialFast && (fDist < GetFloatCVar(e_StreamPredictionMinFarZoneDistance)))
  837.                                                         {
  838.                                                                 if (CMatInfo* pMatInfo = (CMatInfo*)(IMaterial*)pDecal->m_pMaterial)
  839.                                                                         pMatInfo->PrecacheMaterial(fDist, NULL, true);
  840.                                                         }
  841.  
  842.                                                         if (bPrecacheMaterial)
  843.                                                         {
  844.                                                                 pDecal->m_vAmbient = Get3DEngine()->GetAmbientColorFromPosition(pDecal->m_vWSPos);
  845.                                                                 if (CMatInfo* pMatInfo = (CMatInfo*)(IMaterial*)pDecal->m_pMaterial)
  846.                                                                         pMatInfo->PrecacheMaterial(fDist, NULL, false);
  847.                                                         }
  848.                                                 }
  849.  
  850.                                                 // TODO: take entity orientation into account
  851.                                                 Vec3 vSize(pDecal->m_fWSSize, pDecal->m_fWSSize, pDecal->m_fWSSize);
  852.                                                 AABB aabb(pDecal->m_vWSPos - vSize, pDecal->m_vWSPos + vSize);
  853.  
  854.                                                 float fDistFading = SATURATE((1.f - fDist / fMaxViewDist) * DIST_FADING_FACTOR);
  855.                                                 pDecal->Render(fCurrTime, bAfterWater, fDistFading, fDist, passInfo);
  856.  
  857.                                                 if (GetCVars()->e_Decals > 1)
  858.                                                 {
  859.                                                         Vec3 vCenter = pDecal->m_vWSPos;
  860.                                                         AABB aabbCenter(vCenter - vSize * 0.05f, vCenter + vSize * 0.05f);
  861.  
  862.                                                         DrawBBox(aabb);
  863.                                                         DrawBBox(aabbCenter, Col_Yellow);
  864.  
  865.                                                         Vec3 vNormal(Vec3(pDecal->m_vUp).Cross(-pDecal->m_vRight).GetNormalized());
  866.  
  867.                                                         Matrix34A objMat;
  868.                                                         IStatObj* pEntObject = pDecal->m_ownerInfo.GetOwner(objMat);
  869.                                                         if (pEntObject)
  870.                                                                 vNormal = objMat.TransformVector(vNormal).GetNormalized();
  871.  
  872.                                                         DrawLine(vCenter, vCenter + vNormal * pDecal->m_fWSSize);
  873.  
  874.                                                         if (pDecal->m_pRenderMesh)
  875.                                                         {
  876.                                                                 pDecal->m_pRenderMesh->GetBBox(aabb.min, aabb.max);
  877.                                                                 DrawBBox(aabb, Col_Red);
  878.                                                         }
  879.                                                 }
  880.                                         }
  881.                                 }
  882.                 }
  883. }
  884.  
  885. //////////////////////////////////////////////////////////////////////////
  886. void CDecalManager::OnEntityDeleted(IRenderNode* pRenderNode)
  887. {
  888.         FUNCTION_PROFILER_3DENGINE;
  889.  
  890.         // remove decals of this entity
  891.         for (int i = 0; i < DECAL_COUNT; i++)
  892.         {
  893.                 if (m_arrbActiveDecals[i])
  894.                 {
  895.                         if (m_arrDecals[i].m_ownerInfo.pRenderNode == pRenderNode)
  896.                         {
  897.                                 if (GetCVars()->e_Decals == 2)
  898.                                 {
  899.                                         CDecal& decal = m_arrDecals[i];
  900.                                         Vec3 vPos = decal.GetWorldPosition();
  901.                                         char* szOwnerName = "none";
  902. #ifdef _DEBUG
  903.                                         szOwnerName = decal.m_decalOwnerName;
  904. #endif
  905.                                         PrintMessage("Debug: C3DEngine::OnDecalDeleted: Pos=(%.1f,%.1f,%.1f) Size=%.2f DecalMaterial=%s OwnerName=%s",
  906.                                                      vPos.x, vPos.y, vPos.z, decal.m_fSize, decal.m_pMaterial ? decal.m_pMaterial->GetName() : "none", szOwnerName);
  907.                                 }
  908.  
  909.                                 m_arrbActiveDecals[i] = false;
  910.                                 m_arrDecals[i].FreeRenderData();
  911.                         }
  912.                 }
  913.         }
  914.  
  915.         // update decal render nodes
  916.         PodArray<IRenderNode*> lstObjects;
  917.         Get3DEngine()->GetObjectsByTypeGlobal(lstObjects, eERType_Decal, NULL);
  918.  
  919.         if (Get3DEngine()->GetVisAreaManager())
  920.                 Get3DEngine()->GetVisAreaManager()->GetObjectsByType(lstObjects, eERType_Decal, NULL);
  921.  
  922.         for (int i = 0; i < lstObjects.Count(); i++)
  923.                 ((CDecalRenderNode*)lstObjects[i])->RequestUpdate();
  924. }
  925.  
  926. //////////////////////////////////////////////////////////////////////////
  927. void CDecalManager::OnRenderMeshDeleted(IRenderMesh* pRenderMesh)
  928. {
  929.         // remove decals of this entity
  930.         for (int i = 0; i < DECAL_COUNT; i++)
  931.         {
  932.                 if (m_arrbActiveDecals[i])
  933.                 {
  934.                         if (
  935.                           (m_arrDecals[i].m_ownerInfo.pRenderNode && (
  936.                              m_arrDecals[i].m_ownerInfo.pRenderNode->GetRenderMesh(0) == pRenderMesh ||
  937.                              m_arrDecals[i].m_ownerInfo.pRenderNode->GetRenderMesh(1) == pRenderMesh ||
  938.                              m_arrDecals[i].m_ownerInfo.pRenderNode->GetRenderMesh(2) == pRenderMesh))
  939.                           ||
  940.                           (m_arrDecals[i].m_pRenderMesh && m_arrDecals[i].m_pRenderMesh->GetVertexContainer() == pRenderMesh)
  941.                           )
  942.                         {
  943.                                 m_arrbActiveDecals[i] = false;
  944.                                 m_arrDecals[i].FreeRenderData();
  945.                                 //                              PrintMessage("CDecalManager::OnRenderMeshDeleted succseed");
  946.                         }
  947.                 }
  948.         }
  949. }
  950.  
  951. void CDecalManager::MoveToEdge(IRenderMesh* pRM, const float fRadius, Vec3& vOutPos, Vec3& vOutNormal, const Vec3& vTri0, const Vec3& vTri1, const Vec3& vTri2)
  952. {
  953.         FUNCTION_PROFILER_3DENGINE;
  954.  
  955.         AABB boxRM;
  956.         pRM->GetBBox(boxRM.min, boxRM.max);
  957.         Sphere sphere(vOutPos, fRadius);
  958.         if (!Overlap::Sphere_AABB(sphere, boxRM))
  959.                 return;
  960.  
  961.         // get position offset and stride
  962.         int nPosStride = 0;
  963.         byte* pPos = pRM->GetPosPtr(nPosStride, FSL_READ);
  964.  
  965.         vtx_idx* pInds = pRM->GetIndexPtr(FSL_READ);
  966.  
  967.         if (!pPos || !pInds)
  968.                 return;
  969.  
  970.         int nInds = pRM->GetIndicesCount();
  971.  
  972.         //      if(nInds>6000)
  973.         //      return; // skip insane objects
  974.  
  975.         assert(nInds % 3 == 0);
  976.  
  977.         if (!vOutNormal.IsZero())
  978.                 vOutNormal.Normalize();
  979.         else
  980.                 return;
  981.  
  982.         float bestDot = 2.0f;
  983.         Vec3 bestNormal(ZERO);
  984.         Vec3 bestPoint(ZERO);
  985.  
  986.         // render tris
  987.         TRenderChunkArray& Chunks = pRM->GetChunks();
  988.         for (int nChunkId = 0; nChunkId < Chunks.size(); nChunkId++)
  989.         {
  990.                 CRenderChunk* pChunk = &Chunks[nChunkId];
  991.                 if (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE)
  992.                         continue;
  993.  
  994.                 int nLastIndexId = pChunk->nFirstIndexId + pChunk->nNumIndices;
  995.  
  996.                 for (int i = pChunk->nFirstIndexId; i < nLastIndexId; i += 3)
  997.                 {
  998.                         assert(pInds[i + 0] < pChunk->nFirstVertId + pChunk->nNumVerts);
  999.                         assert(pInds[i + 1] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1000.                         assert(pInds[i + 2] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1001.                         assert(pInds[i + 0] >= pChunk->nFirstVertId);
  1002.                         assert(pInds[i + 1] >= pChunk->nFirstVertId);
  1003.                         assert(pInds[i + 2] >= pChunk->nFirstVertId);
  1004.  
  1005.                         // get tri vertices
  1006.                         Vec3 v0 = (*(Vec3*)&pPos[nPosStride * pInds[i + 0]]);
  1007.                         Vec3 v1 = (*(Vec3*)&pPos[nPosStride * pInds[i + 1]]);
  1008.                         Vec3 v2 = (*(Vec3*)&pPos[nPosStride * pInds[i + 2]]);
  1009.  
  1010.                         bool first = false;
  1011.                         bool second = false;
  1012.                         bool third = false;
  1013.  
  1014.                         if (v0 == vTri0 || v0 == vTri1 || v0 == vTri2)
  1015.                                 first = true;
  1016.                         else if (v1 == vTri0 || v1 == vTri1 || v1 == vTri2)
  1017.                                 second = true;
  1018.                         else if (v2 == vTri0 || v2 == vTri1 || v2 == vTri2)
  1019.                                 third = true;
  1020.  
  1021.                         if (first || second || third)
  1022.                         {
  1023.                                 // get triangle normal
  1024.                                 Vec3 vNormal = (v1 - v0).Cross(v2 - v0).GetNormalized();
  1025.  
  1026.                                 float testDot = vNormal.Dot(vOutNormal);
  1027.                                 if (testDot < bestDot)
  1028.                                 {
  1029.                                         bestDot = testDot;
  1030.                                         bestNormal = vNormal;
  1031.                                         if (first)
  1032.                                                 bestPoint = v0;
  1033.                                         else if (second)
  1034.                                                 bestPoint = v1;
  1035.                                         else if (third)
  1036.                                                 bestPoint = v2;
  1037.                                 }
  1038.  
  1039.                         }
  1040.                 }
  1041.  
  1042.         }
  1043.  
  1044.         if (bestDot < 1.0f)
  1045.         {
  1046.                 vOutNormal = (bestNormal + vOutNormal).GetNormalized();
  1047.                 vOutPos.x = bestPoint.x;
  1048.                 vOutPos.y = bestPoint.y;
  1049.         }
  1050. }
  1051.  
  1052. void CDecalManager::FillBigDecalIndices(IRenderMesh* pRM, Vec3 vPos, float fRadius, Vec3 vProjDirIn, PodArray<vtx_idx>* plstIndices, IMaterial* pMat, AABB& meshBBox, float& texelAreaDensity)
  1053. {
  1054.         FUNCTION_PROFILER_3DENGINE;
  1055.  
  1056.         AABB boxRM;
  1057.         pRM->GetBBox(boxRM.min, boxRM.max);
  1058.  
  1059.         Sphere sphere(vPos, fRadius);
  1060.         if (!Overlap::Sphere_AABB(sphere, boxRM))
  1061.                 return;
  1062.  
  1063.         IRenderMesh::ThreadAccessLock lockrm(pRM);
  1064.  
  1065.         // get position offset and stride
  1066.         int nInds = pRM->GetIndicesCount();
  1067.  
  1068.         if (nInds > GetCVars()->e_DecalsMaxTrisInObject * 3)
  1069.                 return; // skip insane objects
  1070.  
  1071.         CDecalRenderNode::m_nFillBigDecalIndicesCounter++;
  1072.  
  1073.         int nPosStride = 0;
  1074.         byte* pPos = pRM->GetPosPtr(nPosStride, FSL_READ);
  1075.         if (!pPos)
  1076.                 return;
  1077.         vtx_idx* pInds = pRM->GetIndexPtr(FSL_READ);
  1078.         if (!pInds)
  1079.                 return;
  1080.  
  1081.         assert(nInds % 3 == 0);
  1082.  
  1083.         plstIndices->Clear();
  1084.  
  1085.         bool bPointProj(vProjDirIn.IsZeroFast());
  1086.  
  1087.         if (!bPointProj)
  1088.                 vProjDirIn.Normalize();
  1089.  
  1090.         if (!pMat)
  1091.                 return;
  1092.  
  1093.         plstIndices->PreAllocate(16);
  1094.  
  1095.         Vec3 vProjDir = vProjDirIn;
  1096.  
  1097.         int usedTrianglesTotal = 0;
  1098.  
  1099.         TRenderChunkArray& Chunks = pRM->GetChunks();
  1100.  
  1101.         {
  1102.                 Vec3 meshBBoxMin = meshBBox.min;
  1103.                 Vec3 meshBBoxMax = meshBBox.max;
  1104.  
  1105.                 const float fEpsilon = 0.001f;
  1106.  
  1107.                 const int kNumChunks = Chunks.size();
  1108.  
  1109.                 if (bPointProj)
  1110.                 {
  1111.                         for (int nChunkId = 0; nChunkId < kNumChunks; nChunkId++)
  1112.                         {
  1113.                                 CRenderChunk* pChunk = &Chunks[nChunkId];
  1114.  
  1115.                                 PrefetchLine(&Chunks[nChunkId + 1], 0);
  1116.                                 PrefetchLine(&pInds[pChunk->nFirstIndexId], 0);
  1117.  
  1118.                                 if (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE)
  1119.                                         continue;
  1120.  
  1121.                                 const SShaderItem& shaderItem = pMat->GetShaderItem(pChunk->m_nMatID);
  1122.  
  1123.                                 if (!shaderItem.m_pShader || !shaderItem.m_pShaderResources)
  1124.                                         continue;
  1125.  
  1126.                                 if (shaderItem.m_pShader->GetFlags() & (EF_NODRAW | EF_DECAL))
  1127.                                         continue;
  1128.  
  1129.                                 PrefetchLine(plstIndices->GetElements(), 0);
  1130.  
  1131.                                 int usedTriangles = 0;
  1132.                                 int nLastIndexId = pChunk->nFirstIndexId + pChunk->nNumIndices;
  1133.  
  1134.                                 int i = pChunk->nFirstIndexId;
  1135.  
  1136.                                 int iPosIndex0 = nPosStride * pInds[i + 0];
  1137.                                 int iPosIndex1 = nPosStride * pInds[i + 1];
  1138.                                 int iPosIndex2 = nPosStride * pInds[i + 2];
  1139.  
  1140.                                 for (; i < nLastIndexId; i += 3)
  1141.                                 {
  1142.                                         assert(pInds[i + 0] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1143.                                         assert(pInds[i + 1] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1144.                                         assert(pInds[i + 2] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1145.                                         assert(pInds[i + 0] >= pChunk->nFirstVertId);
  1146.                                         assert(pInds[i + 1] >= pChunk->nFirstVertId);
  1147.                                         assert(pInds[i + 2] >= pChunk->nFirstVertId);
  1148.  
  1149.                                         PrefetchLine(&pInds[i], 128);
  1150.  
  1151.                                         int iNextPosIndex0 = 0;
  1152.                                         int iNextPosIndex1 = 0;
  1153.                                         int iNextPosIndex2 = 0;
  1154.  
  1155.                                         if (i + 5 < nLastIndexId)
  1156.                                         {
  1157.                                                 iNextPosIndex0 = nPosStride * pInds[i + 3];
  1158.                                                 iNextPosIndex1 = nPosStride * pInds[i + 4];
  1159.                                                 iNextPosIndex2 = nPosStride * pInds[i + 5];
  1160.  
  1161.                                                 PrefetchLine(&pPos[iNextPosIndex0], 0);
  1162.                                                 PrefetchLine(&pPos[iNextPosIndex1], 0);
  1163.                                                 PrefetchLine(&pPos[iNextPosIndex2], 0);
  1164.                                         }
  1165.  
  1166.                                         // get tri vertices
  1167.                                         const Vec3 v0 = *reinterpret_cast<Vec3*>(&pPos[iPosIndex0]);
  1168.                                         const Vec3 v1 = *reinterpret_cast<Vec3*>(&pPos[iPosIndex1]);
  1169.                                         const Vec3 v2 = *reinterpret_cast<Vec3*>(&pPos[iPosIndex2]);
  1170.  
  1171.                                         // test the face
  1172.                                         Vec3 v0v1Diff = v0 - v1;
  1173.                                         Vec3 v2v1Diff = v2 - v1;
  1174.                                         Vec3 vPosv0Diff = vPos - v0;
  1175.  
  1176.                                         Vec3 vCrossResult = v0v1Diff ^ v2v1Diff;
  1177.  
  1178.                                         float fDot = vPosv0Diff | vCrossResult;
  1179.  
  1180.                                         if (fDot > fEpsilon)
  1181.                                         {
  1182.                                                 if (Overlap::Sphere_Triangle(sphere, Triangle(v0, v1, v2)))
  1183.                                                 {
  1184.                                                         plstIndices->AddList(&pInds[i], 3);
  1185.  
  1186.                                                         Vec3 triBBoxMax1 = max(v1, v0);
  1187.                                                         Vec3 triBBoxMax2 = max(meshBBoxMax, v2);
  1188.  
  1189.                                                         Vec3 triBBoxMin1 = min(v1, v0);
  1190.                                                         Vec3 triBBoxMin2 = min(meshBBoxMin, v2);
  1191.  
  1192.                                                         meshBBoxMax = max(triBBoxMax1, triBBoxMax2);
  1193.                                                         meshBBoxMin = min(triBBoxMin1, triBBoxMin2);
  1194.  
  1195.                                                         usedTriangles++;
  1196.                                                 }
  1197.                                         }
  1198.  
  1199.                                         iPosIndex0 = iNextPosIndex0;
  1200.                                         iPosIndex1 = iNextPosIndex1;
  1201.                                         iPosIndex2 = iNextPosIndex2;
  1202.                                 }
  1203.  
  1204.                                 if (pChunk->m_texelAreaDensity > 0.0f && pChunk->m_texelAreaDensity != (float)UINT_MAX)
  1205.                                 {
  1206.                                         texelAreaDensity += usedTriangles * pChunk->m_texelAreaDensity;
  1207.                                         usedTrianglesTotal += usedTriangles;
  1208.                                 }
  1209.                         }
  1210.                 }
  1211.                 else
  1212.                 {
  1213.                         for (int nChunkId = 0; nChunkId < kNumChunks; nChunkId++)
  1214.                         {
  1215.                                 CRenderChunk* pChunk = &Chunks[nChunkId];
  1216.  
  1217.                                 if (nChunkId + 1 < kNumChunks)
  1218.                                         PrefetchLine(&Chunks[nChunkId + 1], 0);
  1219.                                 PrefetchLine(&pInds[pChunk->nFirstIndexId], 0);
  1220.  
  1221.                                 if (pChunk->m_nMatFlags & MTL_FLAG_NODRAW || !pChunk->pRE)
  1222.                                         continue;
  1223.  
  1224.                                 const SShaderItem& shaderItem = pMat->GetShaderItem(pChunk->m_nMatID);
  1225.  
  1226.                                 if (!shaderItem.m_pShader || !shaderItem.m_pShaderResources)
  1227.                                         continue;
  1228.  
  1229.                                 if (shaderItem.m_pShader->GetFlags() & (EF_NODRAW | EF_DECAL))
  1230.                                         continue;
  1231.  
  1232.                                 PrefetchLine(plstIndices->GetElements(), 0);
  1233.  
  1234.                                 int usedTriangles = 0;
  1235.                                 const int nLastIndexId = pChunk->nFirstIndexId + pChunk->nNumIndices;
  1236.                                 const int nLastValidIndexId = nLastIndexId - 1;
  1237.  
  1238.                                 int i = pChunk->nFirstIndexId;
  1239.  
  1240.                                 int iNextPosIndex0 = 0;
  1241.                                 int iNextPosIndex1 = 0;
  1242.                                 int iNextPosIndex2 = 0;
  1243.  
  1244.                                 if (i + 5 < nLastIndexId)
  1245.                                 {
  1246.                                         iNextPosIndex0 = nPosStride * pInds[i + 3];
  1247.                                         iNextPosIndex1 = nPosStride * pInds[i + 4];
  1248.                                         iNextPosIndex2 = nPosStride * pInds[i + 5];
  1249.  
  1250.                                         PrefetchLine(&pPos[iNextPosIndex0], 0);
  1251.                                         PrefetchLine(&pPos[iNextPosIndex1], 0);
  1252.                                         PrefetchLine(&pPos[iNextPosIndex2], 0);
  1253.                                 }
  1254.  
  1255.                                 Vec3 v0Next = *reinterpret_cast<Vec3*>(&pPos[nPosStride * pInds[i + 0]]);
  1256.                                 Vec3 v1Next = *reinterpret_cast<Vec3*>(&pPos[nPosStride * pInds[i + 1]]);
  1257.                                 Vec3 v2Next = *reinterpret_cast<Vec3*>(&pPos[nPosStride * pInds[i + 2]]);
  1258.  
  1259.                                 const int nLastIndexToUse = nLastIndexId - 3;
  1260.  
  1261.                                 for (; i < nLastIndexToUse; i += 3)
  1262.                                 {
  1263.                                         assert(pInds[i + 0] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1264.                                         assert(pInds[i + 1] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1265.                                         assert(pInds[i + 2] < pChunk->nFirstVertId + pChunk->nNumVerts);
  1266.                                         assert(pInds[i + 0] >= pChunk->nFirstVertId);
  1267.                                         assert(pInds[i + 1] >= pChunk->nFirstVertId);
  1268.                                         assert(pInds[i + 2] >= pChunk->nFirstVertId);
  1269.  
  1270.                                         const int iLookaheadIdx = min_branchless(i + 8, nLastValidIndexId);
  1271.                                         const int iPrefetchIndex2 = nPosStride * pInds[iLookaheadIdx];
  1272.  
  1273.                                         // get tri vertices
  1274.                                         const Vec3 v0 = v0Next;
  1275.                                         const Vec3 v1 = v1Next;
  1276.                                         const Vec3 v2 = v2Next;
  1277.  
  1278.                                         //Need to prefetch further ahead
  1279.                                         byte* pPrefetch = &pPos[iPrefetchIndex2];
  1280.                                         PrefetchLine(pPrefetch, 0);
  1281.  
  1282.                                         v0Next = *reinterpret_cast<Vec3*>(&pPos[iNextPosIndex0]);
  1283.  
  1284.                                         // get triangle normal
  1285.                                         Vec3 v1v0Diff = v1 - v0;
  1286.                                         Vec3 v2v0Diff = v2 - v0;
  1287.  
  1288.                                         v1Next = *reinterpret_cast<Vec3*>(&pPos[iNextPosIndex1]);
  1289.  
  1290.                                         Vec3 vNormal = v1v0Diff ^ v2v0Diff;
  1291.                                         float fDot = vNormal | vProjDir;
  1292.  
  1293.                                         v2Next = *reinterpret_cast<Vec3*>(&pPos[iNextPosIndex2]);
  1294.  
  1295.                                         // test the face
  1296.                                         if (fDot > fEpsilon)
  1297.                                         {
  1298.                                                 if (Overlap::Sphere_Triangle(sphere, Triangle(v0, v1, v2)))
  1299.                                                 {
  1300.                                                         plstIndices->AddList(&pInds[i], 3);
  1301.  
  1302.                                                         Vec3 triBBoxMax1 = max(v1, v0);
  1303.                                                         Vec3 triBBoxMax2 = max(meshBBoxMax, v2);
  1304.  
  1305.                                                         Vec3 triBBoxMin1 = min(v1, v0);
  1306.                                                         Vec3 triBBoxMin2 = min(meshBBoxMin, v2);
  1307.  
  1308.                                                         meshBBoxMax = max(triBBoxMax1, triBBoxMax2);
  1309.                                                         meshBBoxMin = min(triBBoxMin1, triBBoxMin2);
  1310.  
  1311.                                                         usedTriangles++;
  1312.                                                 }
  1313.                                         }
  1314.  
  1315.                                         iNextPosIndex0 = nPosStride * pInds[iLookaheadIdx - 2];
  1316.                                         iNextPosIndex1 = nPosStride * pInds[iLookaheadIdx - 1];
  1317.                                         iNextPosIndex2 = iPrefetchIndex2;
  1318.                                 }
  1319.  
  1320.                                 const Vec3 v0 = v0Next;
  1321.                                 const Vec3 v1 = v1Next;
  1322.                                 const Vec3 v2 = v2Next;
  1323.  
  1324.                                 // get triangle normal
  1325.                                 Vec3 v1v0Diff = v1 - v0;
  1326.                                 Vec3 v2v0Diff = v2 - v0;
  1327.                                 Vec3 vNormal = v1v0Diff ^ v2v0Diff;
  1328.                                 float fDot = vNormal | vProjDir;
  1329.  
  1330.                                 // test the face
  1331.                                 if (fDot > fEpsilon)
  1332.                                 {
  1333.                                         if (Overlap::Sphere_Triangle(sphere, Triangle(v0, v1, v2)))
  1334.                                         {
  1335.                                                 plstIndices->AddList(&pInds[i], 3);
  1336.  
  1337.                                                 Vec3 triBBoxMax1 = max(v1, v0);
  1338.                                                 Vec3 triBBoxMax2 = max(meshBBoxMax, v2);
  1339.  
  1340.                                                 Vec3 triBBoxMin1 = min(v1, v0);
  1341.                                                 Vec3 triBBoxMin2 = min(meshBBoxMin, v2);
  1342.  
  1343.                                                 meshBBoxMax = max(triBBoxMax1, triBBoxMax2);
  1344.                                                 meshBBoxMin = min(triBBoxMin1, triBBoxMin2);
  1345.  
  1346.                                                 usedTriangles++;
  1347.                                         }
  1348.                                 }
  1349.  
  1350.                                 if (pChunk->m_texelAreaDensity > 0.0f && pChunk->m_texelAreaDensity != (float)UINT_MAX)
  1351.                                 {
  1352.                                         texelAreaDensity += usedTriangles * pChunk->m_texelAreaDensity;
  1353.                                         usedTrianglesTotal += usedTriangles;
  1354.                                 }
  1355.                         }
  1356.                 }
  1357.  
  1358.                 meshBBox.max = meshBBoxMax;
  1359.                 meshBBox.min = meshBBoxMin;
  1360.         }
  1361.  
  1362.         if (usedTrianglesTotal != 0)
  1363.         {
  1364.                 texelAreaDensity = texelAreaDensity / usedTrianglesTotal;
  1365.         }
  1366. }
  1367.  
  1368. _smart_ptr<IRenderMesh> CDecalManager::MakeBigDecalRenderMesh(IRenderMesh* pSourceRenderMesh, Vec3 vPos, float fRadius, Vec3 vProjDir, IMaterial* pDecalMat, IMaterial* pSrcMat)
  1369. {
  1370.         if (!pSourceRenderMesh || pSourceRenderMesh->GetVerticesCount() == 0)
  1371.                 return 0;
  1372.  
  1373.         // make indices of this decal
  1374.         PodArray<vtx_idx> lstIndices;
  1375.  
  1376.         AABB meshBBox(vPos, vPos);
  1377.         float texelAreaDensity = 0.0f;
  1378.  
  1379.         if (pSourceRenderMesh && pSourceRenderMesh->GetVerticesCount())
  1380.                 FillBigDecalIndices(pSourceRenderMesh, vPos, fRadius, vProjDir, &lstIndices, pSrcMat, meshBBox, texelAreaDensity);
  1381.  
  1382.         if (!lstIndices.Count())
  1383.                 return 0;
  1384.  
  1385.         // make fake vert buffer with one vertex // todo: remove this
  1386.         PodArray<SVF_P3S_C4B_T2S> EmptyVertBuffer;
  1387.         EmptyVertBuffer.Add(SVF_P3S_C4B_T2S());
  1388.  
  1389.         _smart_ptr<IRenderMesh> pRenderMesh = 0;
  1390.         pRenderMesh = GetRenderer()->CreateRenderMeshInitialized(EmptyVertBuffer.GetElements(), EmptyVertBuffer.Count(), eVF_P3S_C4B_T2S,
  1391.                                                                  lstIndices.GetElements(), lstIndices.Count(), prtTriangleList, "BigDecalOnStatObj", "BigDecal", eRMT_Static, 1, 0, 0, 0, false, false, 0);
  1392.         pRenderMesh->SetVertexContainer(pSourceRenderMesh);
  1393.         pRenderMesh->SetChunk(pDecalMat, 0, pSourceRenderMesh->GetVerticesCount(), 0, lstIndices.Count(), texelAreaDensity);
  1394.         pRenderMesh->SetBBox(meshBBox.min, meshBBox.max);
  1395.  
  1396.         return pRenderMesh;
  1397. }
  1398.  
  1399. void CDecalManager::GetMemoryUsage(ICrySizer* pSizer) const
  1400. {
  1401.         pSizer->Add(*this);
  1402. }
  1403.  
  1404. void CDecalManager::DeleteDecalsInRange(AABB* pAreaBox, IRenderNode* pEntity)
  1405. {
  1406.         if (GetCVars()->e_Decals > 1 && pAreaBox)
  1407.                 DrawBBox(*pAreaBox);
  1408.  
  1409.         for (int i = 0; i < DECAL_COUNT; i++)
  1410.         {
  1411.                 if (!m_arrbActiveDecals[i])
  1412.                         continue;
  1413.  
  1414.                 if (pEntity && (pEntity != m_arrDecals[i].m_ownerInfo.pRenderNode))
  1415.                         continue;
  1416.  
  1417.                 if (pAreaBox)
  1418.                 {
  1419.                         Vec3 vPos = m_arrDecals[i].GetWorldPosition();
  1420.                         Vec3 vSize(m_arrDecals[i].m_fWSSize, m_arrDecals[i].m_fWSSize, m_arrDecals[i].m_fWSSize);
  1421.                         AABB decalBox(vPos - vSize, vPos + vSize);
  1422.                         if (!Overlap::AABB_AABB(*pAreaBox, decalBox))
  1423.                                 continue;
  1424.                 }
  1425.  
  1426.                 if (m_arrDecals[i].m_eDecalType != eDecalType_WS_OnTheGround)
  1427.                         m_arrbActiveDecals[i] = false;
  1428.  
  1429.                 m_arrDecals[i].FreeRenderData();
  1430.  
  1431.                 if (GetCVars()->e_Decals == 2)
  1432.                 {
  1433.                         CDecal& decal = m_arrDecals[i];
  1434.                         PrintMessage("Debug: CDecalManager::DeleteDecalsInRange: Pos=(%.1f,%.1f,%.1f) Size=%.2f DecalMaterial=%s",
  1435.                                      decal.m_vPos.x, decal.m_vPos.y, decal.m_vPos.z, decal.m_fSize, decal.m_pMaterial ? decal.m_pMaterial->GetName() : "none");
  1436.                 }
  1437.         }
  1438. }
  1439.  
  1440. void CDecalManager::Serialize(TSerialize ser)
  1441. {
  1442.         ser.BeginGroup("StaticDecals");
  1443.  
  1444.         if (ser.IsReading())
  1445.                 Reset();
  1446.  
  1447.         uint32 dwDecalCount = 0;
  1448.  
  1449.         for (uint32 dwI = 0; dwI < DECAL_COUNT; dwI++)
  1450.                 if (m_arrbActiveDecals[dwI])
  1451.                         dwDecalCount++;
  1452.  
  1453.         ser.Value("DecalCount", dwDecalCount);
  1454.  
  1455.         if (ser.IsWriting())
  1456.         {
  1457.                 for (uint32 _dwI = 0; _dwI < DECAL_COUNT; _dwI++)
  1458.                         if (m_arrbActiveDecals[_dwI])
  1459.                         {
  1460.                                 CDecal& ref = m_arrDecals[_dwI];
  1461.  
  1462.                                 ser.BeginGroup("Decal");
  1463.                                 ser.Value("Pos", ref.m_vPos);
  1464.                                 ser.Value("Right", ref.m_vRight);
  1465.                                 ser.Value("Up", ref.m_vUp);
  1466.                                 ser.Value("Front", ref.m_vFront);
  1467.                                 ser.Value("Size", ref.m_fSize);
  1468.                                 ser.Value("WSPos", ref.m_vWSPos);
  1469.                                 ser.Value("WSSize", ref.m_fWSSize);
  1470.                                 ser.Value("fLifeTime", ref.m_fLifeTime);
  1471.  
  1472.                                 // serialize material, handle legacy decals with textureID converted to material created at runtime
  1473.                                 string matName("");
  1474.                                 if (ref.m_pMaterial && ref.m_pMaterial->GetName())
  1475.                                         matName = ref.m_pMaterial->GetName();
  1476.                                 ser.Value("MatName", matName);
  1477.  
  1478.                                 //                      TODO:  IStatObj *               m_pStatObj;                                                                                             // only if real 3d object is used as decal ()
  1479.                                 ser.Value("vAmbient", ref.m_vAmbient);
  1480.                                 //                      TODO:  IRenderNode * m_pDecalOwner;                                                                             // transformation parent object (0 means parent is the world)
  1481.                                 ser.Value("nRenderNodeSlotId", ref.m_ownerInfo.nRenderNodeSlotId);
  1482.                                 ser.Value("nRenderNodeSlotSubObjectId", ref.m_ownerInfo.nRenderNodeSlotSubObjectId);
  1483.  
  1484.                                 int nDecalType = (int)ref.m_eDecalType;
  1485.                                 ser.Value("eDecalType", nDecalType);
  1486.  
  1487.                                 ser.Value("fGrowTime", ref.m_fGrowTime);
  1488.                                 ser.Value("fGrowTimeAlpha", ref.m_fGrowTimeAlpha);
  1489.                                 ser.Value("fLifeBeginTime", ref.m_fLifeBeginTime);
  1490.  
  1491.                                 bool bBigDecalUsed = ref.IsBigDecalUsed();
  1492.  
  1493.                                 ser.Value("bBigDecal", bBigDecalUsed);
  1494.  
  1495.                                 // m_arrBigDecalRMs[] will be created on the fly so no need load/save it
  1496.  
  1497.                                 if (bBigDecalUsed)
  1498.                                 {
  1499.                                         for (uint32 dwI = 0; dwI < sizeof(ref.m_arrBigDecalRMCustomData) / sizeof(ref.m_arrBigDecalRMCustomData[0]); ++dwI)
  1500.                                         {
  1501.                                                 char szName[16];
  1502.  
  1503.                                                 cry_sprintf(szName, "BDCD%u", dwI);
  1504.                                                 ser.Value(szName, ref.m_arrBigDecalRMCustomData[dwI]);
  1505.                                         }
  1506.                                 }
  1507.                                 ser.EndGroup();
  1508.                         }
  1509.         }
  1510.         else if (ser.IsReading())
  1511.         {
  1512.                 m_nCurDecal = 0;
  1513.  
  1514.                 for (uint32 _dwI = 0; _dwI < dwDecalCount; _dwI++)
  1515.                         if (m_nCurDecal < DECAL_COUNT)
  1516.                         {
  1517.                                 CDecal& ref = m_arrDecals[m_nCurDecal];
  1518.  
  1519.                                 ref.FreeRenderData();
  1520.  
  1521.                                 ser.BeginGroup("Decal");
  1522.                                 ser.Value("Pos", ref.m_vPos);
  1523.                                 ser.Value("Right", ref.m_vRight);
  1524.                                 ser.Value("Up", ref.m_vUp);
  1525.                                 ser.Value("Front", ref.m_vFront);
  1526.                                 ser.Value("Size", ref.m_fSize);
  1527.                                 ser.Value("WSPos", ref.m_vWSPos);
  1528.                                 ser.Value("WSSize", ref.m_fWSSize);
  1529.                                 ser.Value("fLifeTime", ref.m_fLifeTime);
  1530.  
  1531.                                 // serialize material, handle legacy decals with textureID converted to material created at runtime
  1532.                                 string matName("");
  1533.                                 ser.Value("MatName", matName);
  1534.                                 bool isTempMat(false);
  1535.                                 ser.Value("IsTempMat", isTempMat);
  1536.  
  1537.                                 ref.m_pMaterial = 0;
  1538.                                 if (!matName.empty())
  1539.                                 {
  1540.                                         ref.m_pMaterial = GetMatMan()->LoadMaterial(matName.c_str(), false, true);
  1541.                                         if (!ref.m_pMaterial)
  1542.                                                 Warning("Decal material \"%s\" not found!\n", matName.c_str());
  1543.                                 }
  1544.  
  1545.                                 //                      TODO:  IStatObj *               m_pStatObj;                                                                                             // only if real 3d object is used as decal ()
  1546.                                 ser.Value("vAmbient", ref.m_vAmbient);
  1547.                                 //                      TODO:  IRenderNode * m_pDecalOwner;                                                                             // transformation parent object (0 means parent is the world)
  1548.                                 ser.Value("nRenderNodeSlotId", ref.m_ownerInfo.nRenderNodeSlotId);
  1549.                                 ser.Value("nRenderNodeSlotSubObjectId", ref.m_ownerInfo.nRenderNodeSlotSubObjectId);
  1550.  
  1551.                                 int nDecalType = eDecalType_Undefined;
  1552.                                 ser.Value("eDecalType", nDecalType);
  1553.                                 ref.m_eDecalType = (EDecal_Type)nDecalType;
  1554.  
  1555.                                 ser.Value("fGrowTime", ref.m_fGrowTime);
  1556.                                 ser.Value("fGrowTimeAlpha", ref.m_fGrowTimeAlpha);
  1557.                                 ser.Value("fLifeBeginTime", ref.m_fLifeBeginTime);
  1558.  
  1559.                                 // no need to to store m_arrBigDecalRMs[] as it becomes recreated
  1560.  
  1561.                                 bool bBigDecalsAreaUsed = false;
  1562.  
  1563.                                 ser.Value("bBigDecals", bBigDecalsAreaUsed);
  1564.  
  1565.                                 if (bBigDecalsAreaUsed)
  1566.                                         for (uint32 dwI = 0; dwI < sizeof(ref.m_arrBigDecalRMCustomData) / sizeof(ref.m_arrBigDecalRMCustomData[0]); ++dwI)
  1567.                                         {
  1568.                                                 char szName[16];
  1569.  
  1570.                                                 cry_sprintf(szName, "BDCD%u", dwI);
  1571.                                                 ser.Value(szName, ref.m_arrBigDecalRMCustomData[dwI]);
  1572.                                         }
  1573.  
  1574.                                 // m_arrBigDecalRMs[] will be created on the fly so no need load/save it
  1575.  
  1576.                                 m_arrbActiveDecals[m_nCurDecal] = bool(nDecalType != eDecalType_Undefined);
  1577.  
  1578.                                 ++m_nCurDecal;
  1579.                                 ser.EndGroup();
  1580.                         }
  1581.         }
  1582.  
  1583.         ser.EndGroup();
  1584. }
  1585.  
  1586. IMaterial* CDecalManager::GetMaterialForDecalTexture(const char* pTextureName)
  1587. {
  1588.         if (!pTextureName || *pTextureName == 0)
  1589.                 return 0;
  1590.  
  1591.         IMaterialManager* pMatMan = GetMatMan();
  1592.         IMaterial* pMat = pMatMan->FindMaterial(pTextureName);
  1593.         if (pMat)
  1594.                 return pMat;
  1595.  
  1596.         IMaterial* pMatSrc = pMatMan->LoadMaterial("Materials/Decals/Default", false, true);
  1597.         if (pMatSrc)
  1598.         {
  1599.                 IMaterial* pMatDst = pMatMan->CreateMaterial(pTextureName, pMatSrc->GetFlags() | MTL_FLAG_NON_REMOVABLE);
  1600.                 if (pMatDst)
  1601.                 {
  1602.                         SShaderItem& si = pMatSrc->GetShaderItem();
  1603.                         SInputShaderResourcesPtr pIsr = gEnv->pRenderer->EF_CreateInputShaderResource(si.m_pShaderResources);
  1604.  
  1605.                         pIsr->m_Textures[EFTT_DIFFUSE].m_Name = pTextureName;
  1606.  
  1607.                         SShaderItem siDst = GetRenderer()->EF_LoadShaderItem(si.m_pShader->GetName(), true, 0, pIsr, si.m_pShader->GetGenerationMask());
  1608.  
  1609.                         pMatDst->AssignShaderItem(siDst);
  1610.  
  1611.                         return pMatDst;
  1612.                 }
  1613.         }
  1614.  
  1615.         return 0;
  1616. }
  1617.  
  1618. IStatObj* SDecalOwnerInfo::GetOwner(Matrix34A& objMat)
  1619. {
  1620.         if (!pRenderNode)
  1621.                 return NULL;
  1622.  
  1623.         IStatObj* pStatObj = NULL;
  1624.         if (pStatObj = pRenderNode->GetEntityStatObj(nRenderNodeSlotId, nRenderNodeSlotSubObjectId, &objMat, true))
  1625.         {
  1626.                 if (nRenderNodeSlotSubObjectId >= 0 && nRenderNodeSlotSubObjectId < pStatObj->GetSubObjectCount())
  1627.                 {
  1628.                         IStatObj::SSubObject* pSubObj = pStatObj->GetSubObject(nRenderNodeSlotSubObjectId);
  1629.                         pStatObj = pSubObj->pStatObj;
  1630.                         objMat = objMat * pSubObj->tm;
  1631.                 }
  1632.         }
  1633.         else if (ICharacterInstance* pChar = pRenderNode->GetEntityCharacter(nRenderNodeSlotId, &objMat))
  1634.         {
  1635.                 if (nRenderNodeSlotSubObjectId >= 0)
  1636.                 {
  1637.                         pStatObj = pChar->GetISkeletonPose()->GetStatObjOnJoint(nRenderNodeSlotSubObjectId);
  1638.                         const QuatT q = pChar->GetISkeletonPose()->GetAbsJointByID(nRenderNodeSlotSubObjectId);
  1639.                         objMat = objMat * Matrix34(q);
  1640.                 }
  1641.         }
  1642.  
  1643.         if (pStatObj && (pStatObj->GetFlags() & STATIC_OBJECT_HIDDEN))
  1644.                 return NULL;
  1645.  
  1646.         if (pStatObj)
  1647.                 if (int nMinLod = ((CStatObj*)pStatObj)->GetMinUsableLod())
  1648.                         if (IStatObj* pLodObj = pStatObj->GetLodObject(nMinLod))
  1649.                                 pStatObj = pLodObj;
  1650.  
  1651.         return pStatObj;
  1652. }
  1653.  
downloadDecalManager.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