BVB Source Codes

CRYENGINE Show ParticleEnviron.cpp Source code

Return Download CRYENGINE: download ParticleEnviron.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:   ParticleEnviron.cpp
  5. //  Created:     28/08/2007 by Scott Peter
  6. //  Description: World environment interface
  7. // -------------------------------------------------------------------------
  8. //  History:             Refactored from ParticleEmitter.cpp
  9. //
  10. ////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "StdAfx.h"
  13. #include "ParticleEnviron.h"
  14. #include "ParticleEmitter.h"
  15. #include "VisAreas.h"
  16.  
  17. //////////////////////////////////////////////////////////////////////////
  18. // SPhysEnviron implementation.
  19. //////////////////////////////////////////////////////////////////////////
  20.  
  21. void SPhysEnviron::Clear()
  22. {
  23.         m_UniformForces = SPhysForces(ZERO);
  24.         m_tUnderWater = false;
  25.         m_nNonUniformFlags = 0;
  26.         m_nNonCachedFlags = 0;
  27.         m_NonUniformAreas.resize(0);
  28. }
  29.  
  30. void SPhysEnviron::FreeMemory()
  31. {
  32.         Clear();
  33.         stl::free_container(m_NonUniformAreas);
  34. }
  35.  
  36. void SPhysEnviron::OnPhysAreaChange(const EventPhysAreaChange& event)
  37. {
  38.         // Require re-querying of world physics areas
  39.         m_nNonUniformFlags &= ~EFF_LOADED;
  40.  
  41.         EventPhysAreaChange* pepac = (EventPhysAreaChange*)&event;
  42.  
  43.         SAreaChangeRecord rec;
  44.         rec.boxAffected = AABB(pepac->boxAffected[0], pepac->boxAffected[1]);
  45.         rec.uPhysicsMask = Area_Other;
  46.  
  47.         // Determine area medium types
  48.         if (pepac->pEntity)
  49.         {
  50.                 pe_simulation_params psim;
  51.                 if (pepac->pEntity->GetParams(&psim) && !is_unused(psim.gravity))
  52.                         rec.uPhysicsMask |= Area_Gravity;
  53.  
  54.                 pe_params_buoyancy pbuoy;
  55.                 if (pepac->pEntity->GetParams(&pbuoy) && pbuoy.iMedium >= 0 && pbuoy.iMedium < 14)
  56.                         rec.uPhysicsMask |= 1 << pbuoy.iMedium;
  57.         }
  58.  
  59.         CParticleManager::Instance()->AddUpdatedPhysArea(rec);
  60.  
  61. }
  62.  
  63. void SPhysEnviron::GetWorldPhysAreas(uint32 nFlags, bool bNonUniformAreas)
  64. {
  65.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  66.  
  67.         // Recycle shared SArea objects
  68.         SmartPtrArray<SArea> aPrevAreas = m_NonUniformAreas;
  69.  
  70.         Clear();
  71.  
  72.         // Mark areas as queried.
  73.         m_nNonUniformFlags |= EFF_LOADED;
  74.  
  75.         Vec3 vWorldSize(GetTerrain() ? float(GetTerrain()->GetTerrainSize()) : 0.f);
  76.  
  77.         // Atomic iteration.
  78.         for (IPhysicalEntity* pArea = 0; pArea = GetPhysicalWorld()->GetNextArea(pArea); )
  79.         {
  80.                 // Initial check for areas of interest.
  81.                 int nAreaFlags = 0;
  82.                 Plane plWater = m_UniformForces.plWater;
  83.  
  84.                 pe_params_area parea;
  85.                 if (!pArea->GetParams(&parea))
  86.                         continue;
  87.  
  88.                 // Determine which forces are in area.
  89.                 if (!is_unused(parea.gravity))
  90.                         nAreaFlags |= ENV_GRAVITY;
  91.  
  92.                 pe_params_buoyancy pbuoy;
  93.                 if (pArea->GetParams(&pbuoy))
  94.                 {
  95.                         if (pbuoy.iMedium == 1)
  96.                                 nAreaFlags |= ENV_WIND;
  97.                         else if (pbuoy.iMedium == 0 && !is_unused(pbuoy.waterPlane.n))
  98.                         {
  99.                                 plWater.SetPlane(pbuoy.waterPlane.n, pbuoy.waterPlane.origin);
  100.                                 nAreaFlags |= ENV_WATER;
  101.                         }
  102.                 }
  103.  
  104.                 // Skip if unneeded gravity or wind.
  105.                 // All emitters require m_tUnderwater intersection test.
  106.                 nAreaFlags &= nFlags;
  107.                 if (nAreaFlags == 0)
  108.                         continue;
  109.  
  110.                 // Query area for intersection and forces, uniform only.
  111.                 pe_status_area sarea;
  112.                 sarea.ctr.zero();
  113.                 sarea.size = vWorldSize;
  114.                 sarea.bUniformOnly = true;
  115.                 int nStatus = pArea->GetStatus(&sarea);
  116.                 if (!nStatus)
  117.                         continue;
  118.  
  119.                 if (nAreaFlags & ENV_WATER)
  120.                 {
  121.                         m_tUnderWater = ETrinary();
  122.                 }
  123.  
  124.                 pe_status_pos spos;
  125.                 Matrix33 matArea;
  126.                 spos.pMtx3x3 = &matArea;
  127.                 if (!pArea->GetStatus(&spos))
  128.                         continue;
  129.  
  130.                 // Get correct force directions.
  131.                 if (parea.bUniform == 2)
  132.                 {
  133.                         if (nAreaFlags & ENV_GRAVITY)
  134.                                 parea.gravity = spos.q * parea.gravity;
  135.                         if (nAreaFlags & ENV_WIND)
  136.                                 pbuoy.waterFlow = spos.q * pbuoy.waterFlow;
  137.                 }
  138.  
  139.                 SPhysForces area_forces;
  140.                 area_forces.vAccel = nAreaFlags & ENV_GRAVITY ? parea.gravity : Vec3(0.f);
  141.                 area_forces.vWind = nAreaFlags & ENV_WIND ? pbuoy.waterFlow : Vec3(0.f);
  142.                 area_forces.plWater = plWater;
  143.  
  144.                 if (nStatus < 0)
  145.                 {
  146.                         if (bNonUniformAreas)
  147.                         {
  148.                                 // Add to NonUniformAreas list, re-using previous SAreas
  149.                                 _smart_ptr<SArea> pAreaRec;
  150.                                 int i = 0;
  151.                                 for (auto& area : aPrevAreas)
  152.                                 {
  153.                                         if (area.m_pArea == pArea)
  154.                                         {
  155.                                                 pAreaRec = &area;
  156.                                                 aPrevAreas.erase(i);
  157.                                                 break;
  158.                                         }
  159.                                         i++;
  160.                                 }
  161.  
  162.                                 if (!pAreaRec)
  163.                                 {
  164.                                         pAreaRec = new SArea;
  165.                                         pAreaRec->m_pArea = pArea;
  166.                                 }
  167.  
  168.                                 SArea& area = *pAreaRec;
  169.                                 m_NonUniformAreas.push_back(pAreaRec);
  170.  
  171.                                 area.m_pEnviron = this;
  172.                                 area.m_nFlags = nAreaFlags;
  173.                                 area.m_pLock = sarea.pLockUpdate;
  174.                                 area.m_bbArea.min = spos.BBox[0] + spos.pos;
  175.                                 area.m_bbArea.max = spos.BBox[1] + spos.pos;
  176.                                 area.m_Forces = area_forces;
  177.  
  178.                                 if (nAreaFlags & ENV_WATER)
  179.                                 {
  180.                                         // Expand water test area
  181.                                         area.m_bbArea.min.z = -fHUGE;
  182.                                 }
  183.  
  184.                                 pe_params_foreign_data pfd;
  185.                                 if (pArea->GetParams(&pfd))
  186.                                 {
  187.                                         if (pfd.iForeignFlags & PFF_OUTDOOR_AREA)
  188.                                                 area.m_bOutdoorOnly = true;
  189.                                 }
  190.  
  191.                                 area.m_bCacheForce = false;
  192.  
  193.                                 if (nAreaFlags & (ENV_GRAVITY | ENV_WIND))
  194.                                 {
  195.                                         // Test whether we can cache force information for quick evaluation.
  196.                                         int geom_type;
  197.                                         if (parea.pGeom && ((geom_type = parea.pGeom->GetType()) == GEOM_BOX || geom_type == GEOM_SPHERE))
  198.                                         {
  199.                                                 area.m_bRadial = !parea.bUniform;
  200.                                                 area.m_nGeomShape = geom_type;
  201.                                                 area.m_fFalloffScale = div_min(1.f, 1.f - parea.falloff0, fHUGE);
  202.  
  203.                                                 // Construct world-to-unit-sphere transform.
  204.                                                 area.m_vCenter = spos.pos;
  205.                                                 area.m_matToLocal = (matArea * Matrix33::CreateScale(area.m_bbArea.GetSize() * 0.5f)).GetInverted();
  206.                                                 area.m_bCacheForce = true;
  207.                                         }
  208.                                         if (!area.m_bCacheForce)
  209.                                                 m_nNonCachedFlags |= nAreaFlags & (ENV_GRAVITY | ENV_WIND);
  210.                                 }
  211.                         }
  212.                         m_nNonUniformFlags |= nAreaFlags;
  213.                 }
  214.                 else
  215.                 {
  216.                         // Uniform area.
  217.                         m_UniformForces.Add(area_forces, nAreaFlags);
  218.                 }
  219.         }
  220. }
  221.  
  222. void SPhysEnviron::GetPhysAreas(SPhysEnviron const& envSource, AABB const& box, bool bIndoors, uint32 nFlags, bool bNonUniformAreas, const CParticleEmitter* pEmitterSkip)
  223. {
  224.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  225.  
  226.         Clear();
  227.  
  228.         // Mark areas as queried.
  229.         m_nNonUniformFlags |= EFF_LOADED;
  230.  
  231.         m_UniformForces.vAccel = envSource.m_UniformForces.vAccel;
  232.         if (!bIndoors)
  233.         {
  234.                 m_UniformForces.vWind = envSource.m_UniformForces.vWind;
  235.                 m_UniformForces.plWater = envSource.m_UniformForces.plWater;
  236.  
  237.                 // Set status of box with respect to water plane.
  238.                 float fDistMin, fDistMax;
  239.                 Distance::AABB_Plane(&fDistMin, &fDistMax, box, m_UniformForces.plWater);
  240.                 m_tUnderWater = fDistMin > 0.f ? ETrinary(false)
  241.                                 : fDistMax < 0.f ? ETrinary(true)
  242.                                 : ETrinary();
  243.         }
  244.  
  245.         if (bNonUniformAreas && envSource.m_nNonUniformFlags & nFlags && !box.IsReset())
  246.         {
  247.                 pe_status_area sarea;
  248.                 sarea.ctr = box.GetCenter();
  249.                 sarea.size = box.GetSize() * 0.5f;
  250.                 sarea.vel.zero();
  251.                 sarea.bUniformOnly = true;
  252.  
  253.                 for (auto& area : envSource.m_NonUniformAreas)
  254.                 {
  255.                         if (area.m_nFlags & nFlags)
  256.                         {
  257.                                 // Query area for intersection and forces, uniform only.
  258.                                 if (!bIndoors || !area.m_bOutdoorOnly)
  259.                                 {
  260.                                         // Test bb intersection.
  261.                                         if (area.m_bbArea.IsIntersectBox(box))
  262.                                         {
  263.                                                 if (pEmitterSkip)
  264.                                                 {
  265.                                                         pe_params_foreign_data fd;
  266.                                                         if (area.m_pArea->GetParams(&fd))
  267.                                                         {
  268.                                                                 if (fd.pForeignData == pEmitterSkip)
  269.                                                                         continue;
  270.                                                         }
  271.                                                 }
  272.  
  273.                                                 int nStatus = area.m_pArea->GetStatus(&sarea);
  274.  
  275.                                                 if (nStatus)
  276.                                                 {
  277.                                                         // Update underwater status.
  278.                                                         if ((area.m_nFlags & ENV_WATER) && m_tUnderWater * false)
  279.                                                         {
  280.                                                                 // Check box underwater status.
  281.                                                                 float fDistMin, fDistMax;
  282.                                                                 Distance::AABB_Plane(&fDistMin, &fDistMax, box, area.m_Forces.plWater);
  283.                                                                 if (fDistMax < 0.f)
  284.                                                                 {
  285.                                                                         // Underwater.
  286.                                                                         m_tUnderWater = nStatus < 0 ? ETrinary() : ETrinary(true);
  287.                                                                 }
  288.                                                                 else if (fDistMin < 0.f)
  289.                                                                 {
  290.                                                                         // Partially underwater.
  291.                                                                         m_tUnderWater = ETrinary();
  292.                                                                 }
  293.                                                         }
  294.  
  295.                                                         if (area.m_nFlags & nFlags)
  296.                                                         {
  297.                                                                 if (nStatus < 0)
  298.                                                                 {
  299.                                                                         // Store in local nonuniform area list.
  300.                                                                         m_NonUniformAreas.push_back(&area);
  301.                                                                         m_nNonUniformFlags |= area.m_nFlags;
  302.                                                                         if (!area.m_bCacheForce)
  303.                                                                                 m_nNonCachedFlags |= area.m_nFlags & (ENV_GRAVITY | ENV_WIND);
  304.                                                                 }
  305.                                                                 else
  306.                                                                 {
  307.                                                                         // Uniform within this volume.
  308.                                                                         m_UniformForces.Add(area.m_Forces, area.m_nFlags);
  309.                                                                 }
  310.                                                         }
  311.                                                 }
  312.                                         }
  313.                                 }
  314.                         }
  315.                 }
  316.         }
  317. }
  318.  
  319. void SPhysEnviron::GetNonUniformForces(SPhysForces& forces, Vec3 const& vPos, uint32 nFlags) const
  320. {
  321.         for (auto& area : m_NonUniformAreas)
  322.         {
  323.                 if (area.m_nFlags & nFlags)
  324.                         area.GetForces(forces, vPos, nFlags);
  325.         }
  326. }
  327.  
  328. bool SPhysEnviron::PhysicsCollision(ray_hit& hit, Vec3 const& vStart, Vec3 const& vEnd, float fRadius, uint32 nEnvFlags, IPhysicalEntity* pTestEntity)
  329. {
  330.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  331.  
  332.         bool bHit = false;
  333.         Vec3 vMove = vEnd - vStart;
  334.         float fMoveSqr = vMove.GetLengthSquared();
  335.         if (fMoveSqr == 0.f)
  336.                 return false;
  337.         float fInvMove = isqrt_tpl(fMoveSqr);
  338.  
  339.         // Extend movement by particle radius.
  340.         float fRadiusRel = fRadius * fInvMove;
  341.         vMove *= 1.f + fRadiusRel;
  342.  
  343.         float fMoveNorm = 0.f;
  344.         ZeroStruct(hit);
  345.         hit.dist = 1.f;
  346.  
  347.         // Collide terrain first (if set as separately colliding).
  348.         if ((nEnvFlags & ~ENV_COLLIDE_PHYSICS & ENV_TERRAIN) && !pTestEntity && GetTerrain())
  349.         {
  350.                 nEnvFlags &= ~ENV_TERRAIN;
  351.                 CHeightMap::SRayTrace rt;
  352.                 if (GetTerrain()->RayTrace(vStart, vStart + vMove, &rt, GetDefSID()))
  353.                 {
  354.                         if ((fMoveNorm = rt.vNorm * vMove) < 0.f)
  355.                         {
  356.                                 bHit = true;
  357.                                 hit.dist = rt.fInterp;
  358.                                 hit.pt = rt.vHit;
  359.                                 hit.n = rt.vNorm;
  360.                                 if (rt.pMaterial)
  361.                                         hit.surface_idx = rt.pMaterial->GetSurfaceTypeId();
  362.                                 else
  363.                                         hit.surface_idx = 0;
  364.                                 hit.bTerrain = true;
  365.                         }
  366.                 }
  367.         }
  368.  
  369.         if (pTestEntity)
  370.         {
  371.                 // Test specified entity only.
  372.                 bHit = GetPhysicalWorld()->RayTraceEntity(pTestEntity, vStart, vMove, &hit)
  373.                        && hit.n * vMove < 0.f;
  374.         }
  375.         else if (hit.dist > 0.f)
  376.         {
  377.                 int ent_collide = 0;
  378.                 if (nEnvFlags & ENV_TERRAIN)
  379.                         ent_collide |= ent_terrain;
  380.                 if (nEnvFlags & ENV_STATIC_ENT)
  381.                         ent_collide |= ent_static;
  382.                 if (nEnvFlags & ENV_DYNAMIC_ENT)
  383.                         ent_collide |= ent_rigid | ent_sleeping_rigid | ent_living | ent_independent;
  384.  
  385.                 IF (ent_collide, false)
  386.                 {
  387.                         // rwi_ flags copied from similar code in CParticleEntity.
  388.                         ray_hit hit_loc;
  389.                         if (GetPhysicalWorld()->RayWorldIntersection(
  390.                               vStart, vMove * hit.dist,
  391.                               ent_collide | ent_no_ondemand_activation,
  392.                               sf_max_pierceable | (geom_colltype_ray | geom_colltype13) << rwi_colltype_bit | rwi_colltype_any | rwi_ignore_noncolliding,
  393.                               &hit_loc, 1) > 0
  394.                             )
  395.                         {
  396.                                 if ((fMoveNorm = hit_loc.n * vMove) < 0.f)
  397.                                 {
  398.                                         bHit = true;
  399.                                         hit = hit_loc;
  400.                                         hit.dist *= fInvMove;
  401.                                 }
  402.                         }
  403.                 }
  404.         }
  405.  
  406.         if (bHit)
  407.         {
  408.                 hit.pt += hit.n * fRadius;
  409.                 hit.dist -= div_min(fRadius, -fMoveNorm, 1.f);
  410.                 hit.dist = clamp_tpl(hit.dist, 0.f, 1.f);
  411.         }
  412.         return bHit;
  413. }
  414.  
  415. void SPhysEnviron::SArea::GetForcesPhys(SPhysForces& forces, Vec3 const& vPos) const
  416. {
  417.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  418.  
  419.         pe_status_area sarea;
  420.         sarea.ctr = vPos;
  421.         if (m_pArea->GetStatus(&sarea))
  422.         {
  423.                 if (!is_unused(sarea.gravity))
  424.                         forces.vAccel = sarea.gravity;
  425.                 if (sarea.pb.iMedium == 1 && !is_unused(sarea.pb.waterFlow))
  426.                         forces.vWind += sarea.pb.waterFlow;
  427.         }
  428. }
  429.  
  430. void SPhysEnviron::SArea::GetForces(SPhysForces& forces, Vec3 const& vPos, uint32 nFlags) const
  431. {
  432.         nFlags &= m_nFlags;
  433.  
  434.         if (nFlags & (ENV_GRAVITY | ENV_WIND))
  435.         {
  436.                 if (!m_bCacheForce)
  437.                 {
  438.                         GetForcesPhys(forces, vPos);
  439.                 }
  440.                 else
  441.                 {
  442.                         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  443.  
  444. #ifdef DEBUG_FORCES
  445.                         // Compare locally computed results to physics system.
  446.                         // Occasionally fails because of threaded physics area updates.
  447.                         SPhysForces forcesPhys = forces;
  448.                         GetForcesPhys(forcesPhys, vPos);
  449. #endif
  450.  
  451.                         Vec3 vPosRel = vPos - m_vCenter;
  452.  
  453.                         // Update with current position.
  454.                         if (!m_pEnviron->IsCurrent())
  455.                         {
  456.                                 pe_status_pos spos;
  457.                                 if (m_pArea->GetStatus(&spos))
  458.                                         vPosRel = vPos - spos.pos;
  459.                         }
  460.  
  461.                         Vec3 vDist = m_matToLocal * vPosRel;
  462.                         float fDist = m_nGeomShape == GEOM_BOX ? max(max(abs(vDist.x), abs(vDist.y)), abs(vDist.z))
  463.                                       : vDist.GetLengthFast();
  464.                         if (fDist <= 1.f)
  465.                         {
  466.                                 float fStrength = min((1.f - fDist) * m_fFalloffScale, 1.f);
  467.  
  468.                                 if (m_bRadial && fDist > 0.f)
  469.                                 {
  470.                                         // Normalize vOffset for force scaling.
  471.                                         fStrength *= isqrt_fast_tpl(vPosRel.GetLengthSquared());
  472.                                         if (m_nFlags & ENV_GRAVITY)
  473.                                                 forces.vAccel = vPosRel * (m_Forces.vAccel.z * fStrength);
  474.                                         if (m_nFlags & ENV_WIND)
  475.                                                 forces.vWind += vPosRel * (m_Forces.vWind.z * fStrength);
  476.                                 }
  477.                                 else
  478.                                 {
  479.                                         if (m_nFlags & ENV_GRAVITY)
  480.                                                 forces.vAccel = m_Forces.vAccel * fStrength;
  481.                                         if (m_nFlags & ENV_WIND)
  482.                                                 forces.vWind += m_Forces.vWind * fStrength;
  483.                                 }
  484.                         }
  485.  
  486. #ifdef DEBUG_FORCES
  487.                         assert(forcesPhys.vAccel.IsEquivalent(forces.vAccel));
  488.                         assert(forcesPhys.vWind.IsEquivalent(forces.vWind));
  489. #endif
  490.                 }
  491.         }
  492.  
  493.         if (nFlags & ENV_WATER)
  494.         {
  495.                 GetWaterPlane(forces.plWater, vPos, forces.plWater.DistFromPlane(vPos));
  496.         }
  497. }
  498.  
  499. float SPhysEnviron::SArea::GetWaterPlane(Plane& plane, Vec3 const& vPos, float fMaxDist) const
  500. {
  501.         float fDist = m_Forces.plWater.DistFromPlane(vPos);
  502.         if (fDist < fMaxDist)
  503.         {
  504.                 pe_status_contains_point st;
  505.                 st.pt = vPos - m_Forces.plWater.n * fDist;
  506.                 if (m_pArea->GetStatus(&st))
  507.                 {
  508.                         plane = m_Forces.plWater;
  509.                         return fDist;
  510.                 }
  511.         }
  512.         return fMaxDist;
  513. }
  514.  
  515. float SPhysEnviron::GetNonUniformWaterPlane(Plane& plWater, Vec3 const& vPos, float fMaxDist) const
  516. {
  517.         FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  518.  
  519.         for (auto& area : m_NonUniformAreas)
  520.         {
  521.                 if (area.m_nFlags & ENV_WATER)
  522.                         fMaxDist = area.GetWaterPlane(plWater, vPos, fMaxDist);
  523.         }
  524.  
  525.         return fMaxDist;
  526. }
  527.  
  528. /*
  529.    Emitters render either entirely inside or entirely outside VisAreas (due to rendering architecture).
  530.     Emitter origin in vis area:
  531.       Params.VisibleInside == false? Don't render
  532.       else entire emitter in vis area: we're good
  533.       else (intersecting): Test each particle for dist, shrink / fade-out near boundary
  534.     Emitter origin outside vis areas:
  535.       Params.VisibleInside == true ? Don't render
  536.       else entirely outside vis areas: we're good
  537.       else (intersecting): Test each particle for dist, shrink / fade-out near boundary
  538.  */
  539.  
  540. void SVisEnviron::Update(Vec3 const& vOrigin, AABB const& bb)
  541. {
  542.         if (!m_bValid)
  543.         {
  544.                 // Determine emitter's vis area, by origin.
  545.                 FUNCTION_PROFILER(GetISystem(), PROFILE_PARTICLE);
  546.  
  547.                 m_pVisArea = Get3DEngine()->GetVisAreaFromPos(vOrigin);
  548.                 m_pVisNodeCache = 0;
  549.  
  550.                 // See whether it crosses boundaries.
  551.                 if (m_pVisArea)
  552.                         m_bCrossesVisArea = m_pVisArea->GetAABBox()->IsIntersectBox(bb);
  553.                 else
  554.                         m_bCrossesVisArea = Get3DEngine()->IntersectsVisAreas(bb, &m_pVisNodeCache);
  555.  
  556.                 m_bValid = true;
  557.         }
  558. }
  559.  
  560. IVisArea* SVisEnviron::GetClipVisArea(IVisArea* pVisAreaCam, AABB const& bb) const
  561. {
  562.         if (m_bCrossesVisArea)
  563.         {
  564.                 // Clip only against cam area.
  565.                 if (pVisAreaCam != m_pVisArea)
  566.                 {
  567.                         if (pVisAreaCam)
  568.                         {
  569.                                 if (pVisAreaCam->GetAABBox()->IsIntersectBox(bb))
  570.                                 {
  571.                                         if (!m_pVisArea || !pVisAreaCam->FindVisArea(m_pVisArea, 3, true))
  572.                                                 return pVisAreaCam;
  573.                                 }
  574.                         }
  575.                         else if (m_pVisArea)
  576.                                 return m_pVisArea;
  577.                 }
  578.         }
  579.         return 0;
  580. }
  581.  
downloadParticleEnviron.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