BVB Source Codes

CRYENGINE Show PhysCallbacks.cpp Source code

Return Download CRYENGINE: download PhysCallbacks.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:   PhysCallbacks.cpp
  5. //  Created:     14/11/2006 by Anton.
  6. //  Description:
  7. // -------------------------------------------------------------------------
  8. //  History:
  9. //
  10. ////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "StdAfx.h"
  13. #include "PhysCallbacks.h"
  14. #include "RenderMeshUtils.h"
  15. #include "Brush.h"
  16. #include "VisAreas.h"
  17. #include "MatMan.h"
  18. #include <CryEntitySystem/IEntitySystem.h>
  19. #include <CryParticleSystem/IParticles.h>
  20. #include <CryThreading/IJobManager_JobDelegator.h>
  21.  
  22. #define RENDER_MESH_COLLISION_IGNORE_DISTANCE 30.0f
  23. #ifndef RENDER_MESH_TEST_DISTANCE
  24.         #define RENDER_MESH_TEST_DISTANCE           (0.2f)
  25. #endif
  26.  
  27. DECLARE_JOB("RayIntersection", TRayIntersectionJob, CRenderMeshUtils::RayIntersectionAsync);
  28. DECLARE_JOB("DefColEvent_OnPhysCollision", TDeferredCollisionEventOnPhysCollision, CDeferredCollisionEventOnPhysCollision::Execute);
  29.  
  30. CPhysStreamer g_PhysStreamer;
  31.  
  32. // allocator for CDeferredCollisionEventOnPhysCollision(use 4kb pages, should be enough for deferred collision events)
  33. static stl::PoolAllocatorNoMT<sizeof(CDeferredCollisionEventOnPhysCollision), 16> gCDeferredCollisionEventOnPhysCollisionPoolAllocator;
  34.  
  35. void CPhysCallbacks::Init()
  36. {
  37.         GetPhysicalWorld()->AddEventClient(EventPhysBBoxOverlap::id, &CPhysCallbacks::OnFoliageTouched, 1);
  38.         GetPhysicalWorld()->AddEventClient(EventPhysCollision::id, &CDeferredCollisionEventOnPhysCollision::OnCollision, 1, 2000.0f);
  39.         GetPhysicalWorld()->AddEventClient(EventPhysStateChange::id, &CPhysCallbacks::OnPhysStateChange, 1);
  40.         //GetPhysicalWorld()->AddEventClient(EventPhysAreaChange::id, &CPhysCallbacks::OnPhysAreaChange, 0);
  41.         GetPhysicalWorld()->SetPhysicsStreamer(&g_PhysStreamer);
  42. }
  43.  
  44. //////////////////////////////////////////////////////////////////////////
  45. void CPhysCallbacks::Done()
  46. {
  47.         GetPhysicalWorld()->RemoveEventClient(EventPhysBBoxOverlap::id, &CPhysCallbacks::OnFoliageTouched, 1);
  48.         GetPhysicalWorld()->RemoveEventClient(EventPhysCollision::id, &CDeferredCollisionEventOnPhysCollision::OnCollision, 1);
  49.         GetPhysicalWorld()->RemoveEventClient(EventPhysStateChange::id, &CPhysCallbacks::OnPhysStateChange, 1);
  50.         //GetPhysicalWorld()->RemoveEventClient(EventPhysAreaChange::id, &CPhysCallbacks::OnPhysAreaChange, 0);
  51.         GetPhysicalWorld()->SetPhysicsStreamer(0);
  52.         gCDeferredCollisionEventOnPhysCollisionPoolAllocator.FreeMemory();
  53. }
  54.  
  55. //////////////////////////////////////////////////////////////////////////
  56.  
  57. IRenderNode* GetRenderNodeFromPhys(void* pForeignData, int iForeignData)
  58. {
  59.         IEntityRender* pRndProxy;
  60.         if (iForeignData == PHYS_FOREIGN_ID_STATIC)
  61.                 return (IRenderNode*)pForeignData;
  62.         else if (iForeignData == PHYS_FOREIGN_ID_ENTITY && (pRndProxy = ((IEntity*)pForeignData)->GetRenderInterface()))
  63.                 return pRndProxy->GetRenderNode();
  64.         return 0;
  65. }
  66. IStatObj* GetIStatObjFromPhysicalEntity(IPhysicalEntity* pent, int nPartId, Matrix34* pTM, int& nMats, int*& pMatMapping);
  67.  
  68. int       CPhysCallbacks::OnFoliageTouched(const EventPhys* pEvent)
  69. {
  70.         EventPhysBBoxOverlap* pOverlap = (EventPhysBBoxOverlap*)pEvent;
  71.         if (pOverlap->iForeignData[1] == PHYS_FOREIGN_ID_STATIC || pOverlap->iForeignData[1] == PHYS_FOREIGN_ID_ENTITY)
  72.         {
  73.                 pe_params_bbox pbb;
  74.                 pOverlap->pEntity[1]->GetParams(&pbb);
  75.                 pe_params_part pp;
  76.                 pe_status_pos sp;
  77.                 pe_status_nparts snp;
  78.                 primitives::box bbox;
  79.                 OBB obb;
  80.                 Vec3 sz = pbb.BBox[1] - pbb.BBox[0];
  81.                 int nWheels = 0, nParts = pOverlap->pEntity[0]->GetStatus(&snp);
  82.                 if (pOverlap->pEntity[0]->GetType() == PE_WHEELEDVEHICLE)
  83.                 {
  84.                         pe_params_car pc;
  85.                         pOverlap->pEntity[0]->GetParams(&pc);
  86.                         nWheels = pc.nWheels;
  87.                 }
  88.  
  89.                 pOverlap->pEntity[0]->GetStatus(&sp);
  90.                 for (pp.ipart = 0; pp.ipart < nParts - nWheels && pOverlap->pEntity[0]->GetParams(&pp); pp.ipart++, MARK_UNUSED pp.partid)
  91.                         if (pp.flagsOR & (geom_colltype0 | geom_colltype1 | geom_colltype2 | geom_colltype3))
  92.                         {
  93.                                 pp.pPhysGeomProxy->pGeom->GetBBox(&bbox);
  94.                                 obb.SetOBB(Matrix33(sp.q * pp.q) * bbox.Basis.T(), bbox.size * pp.scale, Vec3(ZERO));
  95.                                 if (Overlap::AABB_OBB(AABB(pbb.BBox[0], pbb.BBox[1]), sp.q * (pp.q * bbox.center * pp.scale + pp.pos) + sp.pos, obb))
  96.                                         goto foundbox;
  97.                         }
  98.                 return 1;
  99. foundbox:
  100.  
  101.                 int i;
  102.                 pe_params_foreign_data pfd;
  103.                 C3DEngine* pEngine = (C3DEngine*)gEnv->p3DEngine;
  104.                 pOverlap->pEntity[0]->GetParams(&pfd);
  105.                 if ((i = (pfd.iForeignFlags >> 8 & 255) - 1) < 0)
  106.                 {
  107.                         if ((i = pEngine->m_arrEntsInFoliage.size()) < 255)
  108.                         {
  109.                                 SEntInFoliage eif;
  110.                                 eif.id = gEnv->pPhysicalWorld->GetPhysicalEntityId(pOverlap->pEntity[0]);
  111.                                 eif.timeIdle = 0;
  112.                                 pEngine->m_arrEntsInFoliage.push_back(eif);
  113.                                 MARK_UNUSED pfd.pForeignData, pfd.iForeignData, pfd.iForeignFlags;
  114.                                 pfd.iForeignFlagsOR = (i + 1) << 8;
  115.                                 pOverlap->pEntity[0]->SetParams(&pfd, 1);
  116.                         }
  117.                 }
  118.                 else if (i < (int)pEngine->m_arrEntsInFoliage.size())
  119.                         pEngine->m_arrEntsInFoliage[i].timeIdle = 0;
  120.  
  121.                 IRenderNode* pVeg = GetRenderNodeFromPhys(pOverlap->pForeignData[1], pOverlap->iForeignData[1]);
  122.                 CCamera& cam = gEnv->pSystem->GetViewCamera();
  123.                 int cullDist = GetCVars()->e_CullVegActivation;
  124.                 int iSource = 0;
  125.  
  126.                 if (!cullDist || static_cast<unsigned>(pVeg->GetDrawFrame()) + 10 > gEnv->nMainFrameID &&
  127.                     (cam.GetPosition() - pVeg->GetPos()).len2() * sqr(cam.GetFov()) < sqr(cullDist * 1.04f))
  128.                         if (pVeg->GetPhysics() == pOverlap->pEntity[1] && !pVeg->PhysicalizeFoliage(true, iSource) && nWheels > 0 && sz.x * sz.y < 0.5f)
  129.                                 for (pp.ipart = nParts - 1; pp.ipart >= nParts - nWheels && pOverlap->pEntity[0]->GetParams(&pp); pp.ipart--, MARK_UNUSED pp.partid)
  130.                                         if (pp.pPhysGeomProxy->pGeom->PointInsideStatus(
  131.                                               (((pbb.BBox[1] + pbb.BBox[0]) * 0.5f - sp.pos) * sp.q - pp.pos) * pp.q * (pp.scale == 1.0f ? 1.0f : 1.0f / pp.scale)))
  132.                                         {
  133.                                                 // break the vegetation object
  134.                                                 CStatObj* pStatObj = (CStatObj*)pVeg->GetEntityStatObj();
  135.                                                 if (pStatObj)
  136.                                                 {
  137.                                                         IParticleEffect* pDisappearEffect = pStatObj->GetSurfaceBreakageEffect(SURFACE_BREAKAGE_TYPE("destroy"));
  138.                                                         if (pDisappearEffect)
  139.                                                                 pDisappearEffect->Spawn(true, IParticleEffect::ParticleLoc(pVeg->GetBBox().GetCenter(), Vec3(0, 0, 1), (sz.x + sz.y + sz.z) * 0.3f));
  140.                                                 }
  141.                                                 pVeg->Dephysicalize();
  142.                                                 pEngine->UnRegisterEntityAsJob(pVeg);
  143.                                                 break;
  144.                                         }
  145.         }
  146.         return 1;
  147. }
  148.  
  149. //////////////////////////////////////////////////////////////////////////
  150. int CPhysCallbacks::OnPhysStateChange(const EventPhys* pEvent)
  151. {
  152.         EventPhysStateChange* pepsc = (EventPhysStateChange*)pEvent;
  153.         int i;
  154.         pe_params_foreign_data pfd;
  155.  
  156.         if (pepsc->iSimClass[0] == 2 && pepsc->iSimClass[1] == 1 && pepsc->pEntity->GetParams(&pfd) && (i = (pfd.iForeignFlags >> 8) - 1) >= 0)
  157.         {
  158.                 ((C3DEngine*)gEnv->p3DEngine)->RemoveEntInFoliage(i, pepsc->pEntity);
  159.                 pe_params_bbox pbb;
  160.                 IPhysicalEntity* pentlist[8], ** pents = pentlist;
  161.                 IRenderNode* pBrush;
  162.                 pepsc->pEntity->GetParams(&pbb);
  163.                 for (i = gEnv->pPhysicalWorld->GetEntitiesInBox(pbb.BBox[0], pbb.BBox[1], pents, ent_static | ent_allocate_list, 6) - 1; i >= 0; i--)
  164.                         if (pents[i]->GetParams(&pfd) && (pBrush = GetRenderNodeFromPhys(pfd.pForeignData, pfd.iForeignData)))
  165.                                 pBrush->PhysicalizeFoliage(true, 2, -1);
  166.                 if (pents != pentlist)
  167.                         gEnv->pPhysicalWorld->GetPhysUtils()->DeletePointer(pents);
  168.         }
  169.         return 1;
  170. }
  171.  
  172. //////////////////////////////////////////////////////////////////////////
  173. void CDeferredCollisionEventOnPhysCollision::RayTraceVegetation()
  174. {
  175.         EventPhysCollision* pCollision = &m_CollisionEvent;
  176.  
  177.         if (!(pCollision->iForeignData[1] == PHYS_FOREIGN_ID_STATIC || pCollision->iForeignData[1] == PHYS_FOREIGN_ID_ENTITY))
  178.                 return;
  179.  
  180.         ISurfaceType* pSrfType = GetMatMan()->GetSurfaceType(pCollision->idmat[1]);
  181.         if (!(pSrfType && pSrfType->GetFlags() & SURFACE_TYPE_NO_COLLIDE))
  182.                 return;
  183.  
  184.         FRAME_PROFILER("3dEngine::RaytraceVegetation", GetISystem(), PROFILE_3DENGINE);
  185.  
  186.         IRenderNode* pVeg = GetRenderNodeFromPhys(pCollision->pForeignData[1], pCollision->iForeignData[1]);
  187.         if (!pVeg)
  188.         {
  189.                 MarkFinished(1);
  190.                 return;
  191.         }
  192.  
  193.         CCamera& cam = gEnv->pSystem->GetViewCamera();
  194.         int cullDist = GetCVars()->e_CullVegActivation;
  195.         if (cullDist && (static_cast<unsigned>(pVeg->GetDrawFrame() + 10) < gEnv->nMainFrameID ||
  196.                          (cam.GetPosition() - pVeg->GetPos()).len2() * sqr(cam.GetFov()) > sqr(cullDist * 1.04f)))
  197.         {
  198.                 MarkFinished(0);
  199.                 return;
  200.         }
  201.  
  202.         int i, j, bHit = 0, * pMats, nSlot = pCollision->partid[1] & 1023;
  203.         float tx = 0, ty = 0, len2 = 0, denom2 = 0;
  204.         Matrix34 mtx, mtxInv, mtxw;
  205.         Vec3* pVtx, pt, pt0, dir, pthit, nup, edge, axisx, axisy;
  206.         bool bLocal;
  207.         pe_action_impulse ai;
  208.         pe_status_rope sr;
  209.         CStatObj* pStatObj = (CStatObj*)GetIStatObjFromPhysicalEntity(pCollision->pEntity[1], pCollision->partid[1], &mtx, i, pMats);
  210.         if (!pStatObj)
  211.         {
  212.                 MarkFinished(false);
  213.                 return;
  214.         }
  215.         pe_status_pos sp;
  216.         sp.pMtx3x4 = &mtxw;
  217.         pCollision->pEntity[1]->GetStatus(&sp);
  218.         mtx = mtxw * mtx;
  219.  
  220.         if (pStatObj->m_nSpines && pCollision->n * pCollision->vloc[0] > 0)
  221.         {
  222.                 ai.impulse = pCollision->vloc[0] * (pCollision->mass[0] * 0.5f);
  223.                 pt = pt0 = pCollision->pt;
  224.                 dir = pCollision->vloc[0].normalized();
  225.                 if (bLocal = (pVeg->GetFoliage(nSlot) == 0))
  226.                 {
  227.                         // if branches are not physicalized, operate in local space
  228.                         mtxInv = mtx.GetInverted();
  229.                         pt = mtxInv.TransformPoint(pt);
  230.                         dir = mtxInv.TransformVector(dir);
  231.                 }
  232.                 for (i = 0; i < pStatObj->m_nSpines; i++)
  233.                         if (pStatObj->m_pSpines[i].bActive)
  234.                         {
  235.                                 nup = pStatObj->m_pSpines[i].navg;
  236.                                 if (bLocal)
  237.                                         pVtx = pStatObj->m_pSpines[i].pVtx;
  238.                                 else
  239.                                 {
  240.                                         pVtx = sr.pPoints = pStatObj->m_pSpines[i].pVtxCur;
  241.                                         if (!pVeg->GetBranchPhys(i, nSlot))
  242.                                                 continue;
  243.                                         pVeg->GetBranchPhys(i, nSlot)->GetStatus(&sr);
  244.                                         nup = mtx.TransformVector(nup);
  245.                                 }
  246.                                 //axisx = pVtx[pStatObj->m_pSpines[i].nVtx-1]-pVtx[0]; axisy = pt-pVtx[0];
  247.                                 //if (sqr_signed(axisx*axisy) < 0)//axisx.len2()*axisy.len2()*0.25f)
  248.                                 //      continue;
  249.                                 for (j = 0; j < pStatObj->m_pSpines[i].nVtx - 1; j++)
  250.                                 {
  251.                                         edge = pVtx[j + 1] - pVtx[j];
  252.                                         len2 = edge.len2();
  253.                                         axisx = edge ^ nup;
  254.                                         denom2 = axisx.len2();
  255.                                         axisy = axisx ^ edge;
  256.                                         tx = (pVtx[j] - pt) * axisx;
  257.                                         ty = dir * axisx;
  258.                                         pthit = (pt - pVtx[j]) * ty + dir * tx;
  259.                                         if (inrange(pthit * edge, 0.0f, len2 * ty) && inrange(sqr_signed(pthit * axisy),
  260.                                                                                               sqr_signed(pStatObj->m_pSpines[i].pSegDim[j].z * ty) * denom2, sqr_signed(pStatObj->m_pSpines[i].pSegDim[j].w * ty) * denom2))
  261.                                                 break; // hit y fin
  262.                                         tx = (pVtx[j] - pt) * axisy;
  263.                                         ty = dir * axisy;
  264.                                         pthit = (pt - pVtx[j]) * ty + dir * tx;
  265.                                         if (inrange(pthit * edge, 0.0f, len2 * ty) && inrange(sqr_signed(pthit * axisx),
  266.                                                                                               sqr_signed(pStatObj->m_pSpines[i].pSegDim[j].x * ty) * denom2, sqr_signed(pStatObj->m_pSpines[i].pSegDim[j].y * ty) * denom2))
  267.                                                 break; // hit x fin
  268.                                 }
  269.                                 if (j < pStatObj->m_pSpines[i].nVtx - 1 && pVeg->PhysicalizeFoliage(true, 1, nSlot))
  270.                                 {
  271.                                         pthit = pthit / ty + pVtx[j];
  272.                                         if (bLocal)
  273.                                                 pthit = mtx * pthit;
  274.                                         if ((pthit - pt0) * pCollision->vloc[0] < (pCollision->pt - pt0) * pCollision->vloc[0])
  275.                                                 pCollision->pt = pthit;
  276.                                         ai.point = pthit;
  277.                                         ai.partid = j;
  278.                                         IPhysicalEntity* pent = pCollision->pEntity[1];
  279.                                         (pCollision->pEntity[1] = pVeg->GetBranchPhys(i, nSlot))->Action(&ai);
  280.                                         pCollision->idmat[1] = pStatObj->m_pSpines[i].idmat;
  281.                                         ((CStatObjFoliage*)pCollision->pEntity[1]->GetForeignData(PHYS_FOREIGN_ID_FOLIAGE))->OnHit(pCollision);
  282.                                         pCollision->pEntity[1] = pent;
  283.                                         bHit = 1;
  284.                                 }
  285.                         }
  286.         }
  287.         else if (!pStatObj->m_nSpines && pCollision->n * pCollision->vloc[0] < 0)
  288.         {
  289.                 if (((C3DEngine*)gEnv->p3DEngine)->m_idMatLeaves < 0)
  290.                 {
  291.                         ISurfaceType* pLeavesMat = GetMatMan()->GetSurfaceTypeByName("mat_leaves", "Physical Collision");
  292.                         ((C3DEngine*)gEnv->p3DEngine)->m_idMatLeaves = pLeavesMat ? pLeavesMat->GetId() : 0;
  293.                 }
  294.                 if (!pCollision->idmat[1])
  295.                         pCollision->idmat[1] = ((C3DEngine*)gEnv->p3DEngine)->m_idMatLeaves;
  296.                 bHit = 1;
  297.         }
  298.  
  299.         if (!bHit)
  300.                 pCollision->normImpulse = 0;
  301.         MarkFinished(bHit);
  302.         return;
  303. }
  304.  
  305. //////////////////////////////////////////////////////////////////////////
  306. void CDeferredCollisionEventOnPhysCollision::AdjustBulletVelocity()
  307. {
  308.         if (m_bPierceable)
  309.                 return;
  310.  
  311.         EventPhysCollision* pCollision = &m_CollisionEvent;
  312.  
  313.         // Let bullet fly some more.
  314.         pe_action_set_velocity actionVelocity;
  315.         memcpy(&actionVelocity.v, &pCollision->vloc[0], sizeof(Vec3)); // gcc bug workaround
  316.         pCollision->pEntity[0]->Action(&actionVelocity);
  317.  
  318.         //pe_params_particle paramsPart;
  319.         //pCollision->pEntity[0]->GetParams(&paramsPart);
  320.  
  321.         pe_params_pos ppos;
  322.         ppos.pos = pCollision->pt + pCollision->vloc[0].GetNormalized() * 0.003f;//(paramsPart.size + 0.01f);
  323.         pCollision->pEntity[0]->SetParams(&ppos);
  324. }
  325.  
  326. //////////////////////////////////////////////////////////////////////////
  327. void CDeferredCollisionEventOnPhysCollision::PostStep()
  328. {
  329.         EventPhysCollision* pCollision = &m_CollisionEvent;
  330.         pe_params_rope pr;
  331.  
  332.         if (pCollision->iForeignData[1] == PHYS_FOREIGN_ID_ROPE && pCollision->vloc[0].len2() > sqr(20.0f) && !gEnv->bMultiplayer &&
  333.             !(((IRopeRenderNode*)pCollision->pForeignData[1])->GetParams().nFlags & IRopeRenderNode::eRope_Nonshootable) &&
  334.             pCollision->pEntity[1]->GetParams(&pr) && pr.pEntTiedTo[0] && pr.pEntTiedTo[1])
  335.         {
  336.                 pe_action_slice as;
  337.                 Vec3 pt;
  338.                 as.pt = &pt;
  339.                 as.npt = 1;
  340.                 pt.x = (pCollision->partid[1] + 1 + ((pCollision->partid[1] * 2 - pr.nSegments) >> 31)) * pr.length / pr.nSegments;
  341.                 pCollision->pEntity[1]->Action(&as);
  342.         }
  343.  
  344.         UpdateFoliage();
  345. }
  346.  
  347. void CDeferredCollisionEventOnPhysCollision::UpdateFoliage()
  348. {
  349.         EventPhysCollision* pCollision = &m_CollisionEvent;
  350.  
  351.         if (pCollision->iForeignData[1] == PHYS_FOREIGN_ID_FOLIAGE)
  352.         {
  353.                 ((CStatObjFoliage*)pCollision->pForeignData[1])->m_timeIdle = 0;
  354.                 ((CStatObjFoliage*)pCollision->pForeignData[1])->OnHit(pCollision);
  355.         }
  356. }
  357.  
  358. //////////////////////////////////////////////////////////////////////////
  359. IStatObj* GetIStatObjFromPhysicalEntity(IPhysicalEntity* pent, int nPartId, Matrix34* pTM, int& nMats, int*& pMatMapping)
  360. {
  361.         pe_params_part ppart;
  362.         ppart.partid = nPartId;
  363.         if (pTM)
  364.                 ppart.pMtx3x4 = pTM;
  365.         if (pent->GetParams(&ppart))
  366.         {
  367.                 if (ppart.pPhysGeom && ppart.pPhysGeom->pGeom)
  368.                 {
  369.                         IStatObj* pStatObj = (IStatObj*)ppart.pPhysGeom->pGeom->GetForeignData(0);
  370.                         if (ppart.pPhysGeom->pMatMapping == ppart.pMatMapping)
  371.                         {
  372.                                 // No custom material.
  373.                                 nMats = 0;
  374.                                 pMatMapping = 0;
  375.                         }
  376.                         else
  377.                         {
  378.                                 nMats = ppart.nMats;
  379.                                 pMatMapping = ppart.pMatMapping;
  380.                         }
  381.  
  382.                         IStatObj* pStatObjParent;
  383.                         IStatObj::SSubObject* pSubObj;
  384.                         if (pStatObj &&
  385.                             pStatObj->GetPhysGeom() != ppart.pPhysGeom &&
  386.                             pStatObj->GetPhysGeom(PHYS_GEOM_TYPE_NO_COLLIDE) != ppart.pPhysGeom && pStatObj->GetPhysGeom(PHYS_GEOM_TYPE_OBSTRUCT) != ppart.pPhysGeom &&
  387.                             (pStatObjParent = pStatObj->GetParentObject()) && pStatObjParent != pStatObj)
  388.                                 for (int i = pStatObjParent->GetSubObjectCount() - 1; i >= 0; i--)
  389.                                         if (pTM && (pSubObj = pStatObjParent->GetSubObject(i))->pStatObj == pStatObj)
  390.                                         {
  391.                                                 *pTM = Matrix34::CreateScale(Vec3(ppart.scale)) * pSubObj->localTM;
  392.                                                 break;
  393.                                         }
  394.  
  395.                         return pStatObj;
  396.                 }
  397.         }
  398.         return 0;
  399. }
  400.  
  401. void CDeferredCollisionEventOnPhysCollision::TestCollisionWithRenderMesh()
  402. {
  403.         EventPhysCollision* pCollisionEvent = &m_CollisionEvent;
  404.         assert(pCollisionEvent);
  405.  
  406.         if (pCollisionEvent->iForeignData[0] != PHYS_FOREIGN_ID_ENTITY)
  407.         {
  408.                 MarkFinished(1);
  409.                 return;
  410.         }
  411.  
  412.         if (pCollisionEvent->vloc[0].IsZero())
  413.         {
  414.                 MarkFinished(1);
  415.                 return;
  416.         }
  417.  
  418.         // Ignore it if too far.
  419.         Vec3 vCamPos = GetSystem()->GetViewCamera().GetPosition();
  420.  
  421.         // do not spawn if too far
  422.         float fZoom = gEnv->p3DEngine->GetZoomFactor();
  423.         float fCollisionDistance = pCollisionEvent->pt.GetDistance(vCamPos);
  424.         if (fCollisionDistance * fZoom > GetFloatCVar(e_DecalsRange) && pCollisionEvent->mass[0] < 0.5f)
  425.         {
  426.                 // only apply distance check for bullets; heavier particles should use it always
  427.                 MarkFinished(1);
  428.                 return;
  429.         }
  430.  
  431.         // Check if backface collision.
  432.         if (pCollisionEvent->vloc[0].Dot(pCollisionEvent->n) > 0)
  433.         {
  434.                 // Ignore testing render-mesh for backface collisions.
  435.                 MarkFinished(0);
  436.                 return;
  437.         }
  438.  
  439.         // Get IStatObj from physical entity.
  440.         Matrix34 partTM;
  441.         IStatObj* pStatObj = GetIStatObjFromPhysicalEntity(pCollisionEvent->pEntity[1], pCollisionEvent->partid[1], &partTM, m_nMats, m_pMatMapping);
  442.  
  443.         unsigned int pierceability0 = 0, pierceability1;
  444.         float dummy;
  445.  
  446.         if (pCollisionEvent->pEntity[0])
  447.         {
  448.                 if (pCollisionEvent->pEntity[0]->GetType() == PE_PARTICLE)
  449.                         pierceability0 = pCollisionEvent->partid[0];
  450.                 else
  451.                         GetPhysicalWorld()->GetSurfaceParameters(pCollisionEvent->idmat[0], dummy, dummy, pierceability0);
  452.                 GetPhysicalWorld()->GetSurfaceParameters(pCollisionEvent->idmat[1], dummy, dummy, pierceability1);
  453.                 m_bPierceable = (pierceability0 & 15) < (pierceability1 & 15);
  454.         }
  455.  
  456.         if (pStatObj)
  457.                 if (int nMinLod = ((CStatObj*)pStatObj)->GetMinUsableLod())
  458.                         if (IStatObj* pLodObj = pStatObj->GetLodObject(nMinLod))
  459.                                 pStatObj = pLodObj;
  460.  
  461.         if (pStatObj == NULL)
  462.         {
  463.                 MarkFinished(1);
  464.                 return;
  465.         }
  466.  
  467.         m_pRenderMesh = pStatObj->GetRenderMesh();
  468.  
  469.         IRenderNode* pRenderNode = GetRenderNodeFromPhys(pCollisionEvent->pForeignData[1], pCollisionEvent->iForeignData[1]);
  470.         IMaterial* pRenderNodeMaterial = pRenderNode ? pRenderNode->GetMaterial() : NULL;
  471.         m_pMaterial = pRenderNodeMaterial ? pRenderNodeMaterial : pStatObj->GetMaterial();
  472.  
  473.         m_bDecalPlacementTestRequested = (pCollisionEvent->iForeignData[1] == PHYS_FOREIGN_ID_ENTITY);
  474.  
  475.         if (m_pRenderMesh == NULL)
  476.         {
  477.                 MarkFinished(1);
  478.                 return;
  479.         }
  480.  
  481.         pe_status_pos ppos;
  482.         ppos.pMtx3x4 = &m_worldTM;
  483.         pCollisionEvent->pEntity[1]->GetStatus(&ppos);
  484.         m_worldTM = m_worldTM * partTM;
  485.         m_worldRot = Matrix33(m_worldTM);
  486.         m_worldRot /= m_worldRot.GetColumn(0).GetLength();
  487.         Vec3 dir = pCollisionEvent->vloc[0].GetNormalized();
  488.  
  489.         // transform decal into object space
  490.         Matrix34 worldTM_Inverted = m_worldTM.GetInverted();
  491.  
  492.         // put hit normal into the object space
  493.         Vec3 vRayDir = dir * m_worldRot;
  494.  
  495.         // put hit position into the object space
  496.         Vec3 vHitPos = worldTM_Inverted.TransformPoint(pCollisionEvent->pt);
  497.         Vec3 vLineP1 = vHitPos - vRayDir * RENDER_MESH_TEST_DISTANCE;
  498.  
  499.         // set up hit data
  500.         m_HitInfo.inReferencePoint = vHitPos;
  501.         m_HitInfo.inRay.origin = vLineP1;
  502.         m_HitInfo.inRay.direction = vRayDir;
  503.         m_HitInfo.bInFirstHit = false;
  504.         m_HitInfo.bUseCache = false; // no cache with parallel execution
  505.  
  506.         if (pCollisionEvent->pEntity[0])
  507.         {
  508.                 // Cap the rendermesh linetest, anything past fMaxHitDistance is considered a hole
  509.                 Vec3 ptlim;
  510.                 if (m_bPierceable && pCollisionEvent->next && pCollisionEvent->next->idval == EventPhysCollision::id &&
  511.                     ((EventPhysCollision*)pCollisionEvent->next)->pEntity[0] == pCollisionEvent->pEntity[0])
  512.                 {
  513.                         ptlim = ((EventPhysCollision*)pCollisionEvent->next)->pt;
  514.                 }
  515.                 else
  516.                 {
  517.                         ptlim = pCollisionEvent->pt + dir * (GetCVars()->e_RenderMeshCollisionTolerance + dir * pCollisionEvent->vloc[0] * (GetTimer()->GetFrameTime() * 1.1f));
  518.                 }
  519.                 m_HitInfo.fMaxHitDistance = (worldTM_Inverted * ptlim - m_HitInfo.inRay.origin) * m_HitInfo.inRay.direction;
  520.         }
  521. }
  522.  
  523. void CDeferredCollisionEventOnPhysCollision::FinishTestCollisionWithRenderMesh()
  524. {
  525.         EventPhysCollision* pCollisionEvent = &m_CollisionEvent;
  526.         assert(pCollisionEvent);
  527.  
  528.         //CryLogAlways( "Do Test %f,%f",vHitPos.x,vHitPos.y );
  529.         if (m_RayIntersectionData.bResult == false)
  530.         {
  531.                 pCollisionEvent->normImpulse = 0;
  532.                 MarkFinished(0);
  533.                 return;
  534.         }
  535.  
  536.         Vec3 ptnew = m_worldTM.TransformPoint(m_HitInfo.vHitPos);
  537.         // prevent reporting collisions before for the case that we have a previous valid hit
  538.         //  if ((ptnew-pCollisionEvent->pt)*pCollisionEvent->vloc[0] > (m_ptlim-pCollisionEvent->pt)*pCollisionEvent->vloc[0] )
  539.         //      {
  540.         //              MarkFinished(0);
  541.         //              return;
  542.         //      }
  543.  
  544.         pCollisionEvent->pt = ptnew;
  545.         pCollisionEvent->n = m_worldRot.TransformVector(m_HitInfo.vHitNormal);
  546.         if (pCollisionEvent->penetration >= 0)
  547.         {
  548.                 if (m_pMatMapping)
  549.                 {
  550.                         // When using custom material mapping.
  551.                         if (m_HitInfo.nHitMatID < m_nMats)
  552.                         {
  553.                                 m_HitInfo.nHitSurfaceID = m_pMatMapping[m_HitInfo.nHitMatID];
  554.                         }
  555.                 }
  556.                 if (m_HitInfo.nHitSurfaceID)
  557.                 {
  558.                         pCollisionEvent->idmat[1] = m_HitInfo.nHitSurfaceID;
  559.                 }
  560.         }
  561.  
  562.         pCollisionEvent->fDecalPlacementTestMaxSize = m_RayIntersectionData.fDecalPlacementTestMaxSize;
  563. }
  564.  
  565. int CPhysStreamer::CreatePhysicalEntity(void* pForeignData, int iForeignData, int iForeignFlags)
  566. {
  567.         if (iForeignData == PHYS_FOREIGN_ID_STATIC)
  568.                 if (iForeignFlags & (PFF_BRUSH | PFF_VEGETATION))
  569.                         ((IRenderNode*)pForeignData)->Physicalize(true);
  570.                 else
  571.                         return 0;
  572.         return 1;
  573. }
  574.  
  575. int CPhysStreamer::CreatePhysicalEntitiesInBox(const Vec3& boxMin, const Vec3& boxMax)
  576. {
  577.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_3DENGINE);
  578.         for (int nSID = 0; nSID < ((C3DEngine*)gEnv->p3DEngine)->m_pObjectsTree.Count(); nSID++)
  579.         {
  580.                 if (((C3DEngine*)gEnv->p3DEngine)->IsSegmentSafeToUse(nSID))
  581.                         ((C3DEngine*)gEnv->p3DEngine)->m_pObjectsTree[nSID]->PhysicalizeInBox(AABB(boxMin, boxMax));
  582.         }
  583.         if (((C3DEngine*)gEnv->p3DEngine)->m_pVisAreaManager)
  584.                 ((C3DEngine*)gEnv->p3DEngine)->m_pVisAreaManager->PhysicalizeInBox(AABB(boxMin, boxMax));
  585.         return 1;
  586. }
  587.  
  588. int CPhysStreamer::DestroyPhysicalEntitiesInBox(const Vec3& boxMin, const Vec3& boxMax)
  589. {
  590.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_3DENGINE);
  591.         for (int nSID = 0; nSID < ((C3DEngine*)gEnv->p3DEngine)->m_pObjectsTree.Count(); nSID++)
  592.         {
  593.                 if (((C3DEngine*)gEnv->p3DEngine)->m_pObjectsTree[nSID])
  594.                         ((C3DEngine*)gEnv->p3DEngine)->m_pObjectsTree[nSID]->DephysicalizeInBox(AABB(boxMin, boxMax));
  595.         }
  596.         if (((C3DEngine*)gEnv->p3DEngine)->m_pVisAreaManager)
  597.                 ((C3DEngine*)gEnv->p3DEngine)->m_pVisAreaManager->DephysicalizeInBox(AABB(boxMin, boxMax));
  598.         return 1;
  599. }
  600.  
  601. //////////////////////////////////////////////////////////////////////////
  602. //////////////////////////////////////////////////////////////////////////
  603. int CDeferredCollisionEventOnPhysCollision::OnCollision(const EventPhys* pEvent)
  604. {
  605.         IDeferredPhysicsEventManager* pDeferredPhysicsEventManager = gEnv->p3DEngine->GetDeferredPhysicsEventManager();
  606.  
  607.         // deferred physics event manager handles the logic if an event needs to be deferred and creating/ destruction of it
  608.         return pDeferredPhysicsEventManager->HandleEvent(pEvent, &CDeferredCollisionEventOnPhysCollision::CreateCollisionEvent, IDeferredPhysicsEvent::PhysCallBack_OnCollision);
  609.  
  610. }
  611.  
  612. CDeferredCollisionEventOnPhysCollision::CDeferredCollisionEventOnPhysCollision(const EventPhysCollision* pCollisionEvent) :
  613.         m_bHit(false),
  614.         m_bFinished(false),
  615.         m_bPierceable(false),
  616.         m_nResult(0),
  617.         m_CollisionEvent(*pCollisionEvent),
  618.         m_pMatMapping(NULL),
  619.         m_nMats(-1),
  620.         m_pRenderMesh(NULL),
  621.         m_pMaterial(NULL),
  622.         m_bTaskRunning(false),
  623.         m_bDecalPlacementTestRequested(false),
  624.         m_bNeedMeshThreadUnLock(false)
  625. {
  626.         memset(&m_HitInfo, 0, sizeof(m_HitInfo));
  627.  
  628.         m_nWaitForPrevEvent = 0;
  629.         m_pNextEvent = 0;
  630.         if (IDeferredPhysicsEvent* pLastEvent = gEnv->p3DEngine->GetDeferredPhysicsEventManager()->GetLastCollisionEventForEntity(pCollisionEvent->pEntity[0]))
  631.         {
  632.                 m_nWaitForPrevEvent = 10;
  633.                 ((CDeferredCollisionEventOnPhysCollision*)pLastEvent)->m_pNextEvent = this;
  634.         }
  635. }
  636.  
  637. CDeferredCollisionEventOnPhysCollision::~CDeferredCollisionEventOnPhysCollision()
  638. {
  639.         // make sure nothing is in flight if we are destructed
  640.         Sync();
  641.  
  642.         if (m_pRenderMesh && m_bNeedMeshThreadUnLock)
  643.         {
  644.                 m_pRenderMesh->UnLockForThreadAccess();
  645.                 m_bNeedMeshThreadUnLock = false;
  646.         }
  647.  
  648.         IDeferredPhysicsEventManager* pDeferredPhysicsEventManager = gEnv->p3DEngine->GetDeferredPhysicsEventManager();
  649.         pDeferredPhysicsEventManager->UnRegisterDeferredEvent(this);
  650. }
  651.  
  652. void CDeferredCollisionEventOnPhysCollision::Execute()
  653. {
  654.         // init data for async ray intersection
  655.         if (!m_bNeedMeshThreadUnLock)
  656.         {
  657.                 m_pRenderMesh->LockForThreadAccess();
  658.                 m_bNeedMeshThreadUnLock = true;
  659.         }
  660.         if (m_RayIntersectionData.Init(m_pRenderMesh, &m_HitInfo, m_pMaterial, m_bDecalPlacementTestRequested))
  661.         {
  662.                 TRayIntersectionJob job(&m_RayIntersectionData);
  663.                 job.SetPriorityLevel(JobManager::eLowPriority);
  664.                 job.RegisterJobState(&m_jobStateRayInter);
  665.                 job.Run();
  666.         }
  667.  
  668.         m_bTaskRunning = false;
  669. }
  670.  
  671. void CDeferredCollisionEventOnPhysCollision::Start()
  672. {
  673.         EventPhysCollision* pCollision = &m_CollisionEvent;
  674.         assert(pCollision->pEntity[0]);
  675.  
  676.         if (pCollision->pEntity[0]->GetType() != PE_PARTICLE)
  677.         {
  678.                 UpdateFoliage();
  679.                 MarkFinished(1);
  680.                 return;
  681.         }
  682.  
  683.         RayTraceVegetation();
  684.  
  685.         if (m_bFinished)  // RayTracevegetation already found a hit
  686.                 return;
  687.  
  688.         TestCollisionWithRenderMesh();
  689.  
  690.         if (m_bFinished)  // Early out in TestCollisionWithRenderMesh
  691.         {
  692.                 PostStep();
  693.                 return;
  694.         }
  695.  
  696.         // do the remaining work in a task
  697.         m_bTaskRunning = true;
  698.         IDeferredPhysicsEventManager* pDeferredPhysicsEventManager = gEnv->p3DEngine->GetDeferredPhysicsEventManager();
  699.         pDeferredPhysicsEventManager->DispatchDeferredEvent(this);
  700. }
  701.  
  702. void CDeferredCollisionEventOnPhysCollision::ExecuteAsJob()
  703. {
  704.         TDeferredCollisionEventOnPhysCollision job;
  705.         job.SetClassInstance(this);
  706.         job.SetPriorityLevel(JobManager::eRegularPriority);
  707.         job.RegisterJobState(&m_jobStateOnCollision);
  708.         job.Run();
  709. }
  710.  
  711. int CDeferredCollisionEventOnPhysCollision::Result(EventPhys* pOrigEvent)
  712. {
  713.         Sync();
  714.         if (m_pNextEvent)
  715.                 m_pNextEvent->m_nWaitForPrevEvent = 0;
  716.  
  717.         if (pOrigEvent)
  718.                 ((EventPhysCollision*)pOrigEvent)->normImpulse = m_CollisionEvent.normImpulse;
  719.  
  720.         if (m_bFinished)
  721.                 return m_nResult;
  722.  
  723.         FinishTestCollisionWithRenderMesh();
  724.  
  725.         if (pOrigEvent)
  726.         {
  727.                 EventPhysCollision* pCEvent = (EventPhysCollision*)pOrigEvent;
  728.                 pCEvent->pt = m_CollisionEvent.pt;
  729.                 pCEvent->n = m_CollisionEvent.n;
  730.                 pCEvent->normImpulse = m_CollisionEvent.normImpulse;
  731.                 pCEvent->fDecalPlacementTestMaxSize = m_CollisionEvent.fDecalPlacementTestMaxSize;
  732.                 pCEvent->idmat[1] = m_CollisionEvent.idmat[1];
  733.         }
  734.  
  735.         // no hit, no need for Post-Step
  736.         if (m_bFinished)
  737.         {
  738.                 AdjustBulletVelocity();
  739.                 return m_nResult;
  740.         }
  741.  
  742.         PostStep();
  743.  
  744.         m_bFinished = true;
  745.         m_nResult = 1;
  746.         return m_nResult;
  747. }
  748.  
  749. void CDeferredCollisionEventOnPhysCollision::MarkFinished(int nResult)
  750. {
  751.         m_nResult = nResult;
  752.         m_bFinished = true;
  753. }
  754.  
  755. void CDeferredCollisionEventOnPhysCollision::Sync()
  756. {
  757.         FUNCTION_PROFILER_3DENGINE;
  758.         gEnv->GetJobManager()->WaitForJob(m_jobStateRayInter);
  759.         gEnv->GetJobManager()->WaitForJob(m_jobStateOnCollision);
  760.  
  761.         // in normal execution case, m_bTaskRunning should always be false when we are here
  762.         while (m_bTaskRunning)
  763.         {
  764.                 CrySleep(1); // yield
  765.         }
  766. }
  767.  
  768. bool CDeferredCollisionEventOnPhysCollision::HasFinished()
  769. {
  770.         if (m_bTaskRunning || m_nWaitForPrevEvent > 0)
  771.         {
  772.                 --m_nWaitForPrevEvent;
  773.                 return false;
  774.         }
  775.  
  776.         if (m_jobStateRayInter.IsRunning())
  777.                 return false;
  778.  
  779.         return true;
  780. }
  781.  
  782. IDeferredPhysicsEvent* CDeferredCollisionEventOnPhysCollision::CreateCollisionEvent(const EventPhys* pCollisionEvent)
  783. {
  784.         return new CDeferredCollisionEventOnPhysCollision((EventPhysCollision*)pCollisionEvent);
  785. }
  786.  
  787. void* CDeferredCollisionEventOnPhysCollision::operator new(size_t)
  788. {
  789.         return gCDeferredCollisionEventOnPhysCollisionPoolAllocator.Allocate();
  790. }
  791.  
  792. void CDeferredCollisionEventOnPhysCollision::operator delete(void* ptr)
  793. {
  794.         gCDeferredCollisionEventOnPhysCollisionPoolAllocator.Deallocate(ptr);
  795. }
  796.  
downloadPhysCallbacks.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