BVB Source Codes

CRYENGINE Show BreakableGlassRenderNode.cpp Source code

Return Download CRYENGINE: download BreakableGlassRenderNode.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // Includes
  4. #include "StdAfx.h"
  5. #include "BreakableGlassRenderNode.h"
  6.  
  7. #include "3dEngine.h"
  8. #include <CryPhysics/IPhysics.h>
  9. #include <CryParticleSystem/IParticles.h>
  10. #include <CryParticleSystem/ParticleParams.h>
  11. #include <CryAction/IMaterialEffects.h>
  12. #include <CryRenderer/IShader.h>
  13.  
  14. // Constants
  15. #define DEFAULT_MAX_VIEW_DIST       1000.0f
  16. #define GLASS_IMPACT_BOUNDARY       0.01f
  17. #define LOOSE_FRAG_LIFETIME         4.5f
  18. #define PHYS_FRAG_SHATTER_SIZE      0.65f
  19.  
  20. #define PHYSEVENT_COLLIDER          0
  21.  
  22. #define GLASS_TINT_COLOUR_PARAM     "TintColor"
  23. #define GLASS_TINT_CLOUDINESS_PARAM "TintCloudiness"
  24.  
  25. // State flags
  26. enum EGlassRNState
  27. {
  28.         EGlassRNState_Initial     = 0,
  29.         EGlassRNState_Weakened    = 1 << 0,
  30.         EGlassRNState_Shattering  = 1 << 1,
  31.         EGlassRNState_Shattered   = 1 << 2,
  32.         EGlassRNState_ActiveFrags = 1 << 3
  33. };
  34.  
  35. // Statics
  36. const SBreakableGlassCVars* CBreakableGlassRenderNode::s_pCVars = NULL;
  37.  
  38. // Error logging
  39. #ifndef RELEASE
  40.         #define LOG_GLASS_ERROR(...) CryLogAlways("[BreakGlassSystem Error]: " __VA_ARGS__)
  41. #else
  42.         #define LOG_GLASS_ERROR(...)
  43. #endif
  44.  
  45. //--------------------------------------------------------------------------------------------------
  46. // Name: CBreakableGlassRenderNode
  47. // Desc: Constructor
  48. //--------------------------------------------------------------------------------------------------
  49. CBreakableGlassRenderNode::CBreakableGlassRenderNode()
  50.         : m_pBreakableGlassRE(NULL)
  51.         , m_pPhysEnt(NULL)
  52.         , m_glassTintColour(0.5f, 0.5f, 0.5f, 0.5f)
  53.         , m_id(0)
  54.         , m_state(EGlassRNState_Initial)
  55.         , m_nextPhysFrag(0)
  56. {
  57.         GetInstCount(GetRenderNodeType())++;
  58.  
  59.         m_matrix.SetIdentity();
  60.         m_planeBBox.Reset();
  61.         m_fragBBox.Reset();
  62.         m_maxViewDist = DEFAULT_MAX_VIEW_DIST;
  63.  
  64.         // Start with full array
  65.         for (int i = 0; i < GLASSCFG_MAX_NUM_PHYS_FRAGMENTS; ++i)
  66.         {
  67.                 m_physFrags.push_back();
  68.         }
  69. }//-------------------------------------------------------------------------------------------------
  70.  
  71. //--------------------------------------------------------------------------------------------------
  72. // Name: ~CBreakableGlassRenderNode
  73. // Desc: Destructor
  74. //--------------------------------------------------------------------------------------------------
  75. CBreakableGlassRenderNode::~CBreakableGlassRenderNode()
  76. {
  77.         GetInstCount(GetRenderNodeType())--;
  78.  
  79.         gEnv->p3DEngine->FreeRenderNodeState(this);
  80. }//-------------------------------------------------------------------------------------------------
  81.  
  82. //--------------------------------------------------------------------------------------------------
  83. // Name: InitialiseNode
  84. // Desc: Initialises render node
  85. //--------------------------------------------------------------------------------------------------
  86. bool CBreakableGlassRenderNode::InitialiseNode(const SBreakableGlassInitParams& params, const Matrix34& matrix)
  87. {
  88.         // Store param data
  89.         SetMaterial(params.pGlassMaterial);
  90.         memcpy(&m_glassParams, &params, sizeof(SBreakableGlassInitParams));
  91.  
  92.         // Create glass element
  93.         if (m_pBreakableGlassRE = static_cast<CREBreakableGlass*>(gEnv->pRenderer->EF_CreateRE(eDATA_BreakableGlass)))
  94.         {
  95.                 m_pBreakableGlassRE->InitialiseRenderElement(params);
  96.         }
  97.  
  98.         // Update matrix
  99.         SetMatrix(matrix);
  100.  
  101.         // Finally, physicalize glass
  102.         PhysicalizeGlass();
  103.  
  104.         // Flag for cubemap update if required
  105.         IMaterial* pMaterial = m_glassParams.pGlassMaterial;
  106.         if (pMaterial && (pMaterial->GetFlags() & MTL_FLAG_REQUIRE_NEAREST_CUBEMAP))
  107.         {
  108.                 m_nInternalFlags |= IRenderNode::REQUIRES_NEAREST_CUBEMAP;
  109.         }
  110.         else
  111.         {
  112.                 m_nInternalFlags &= ~IRenderNode::REQUIRES_NEAREST_CUBEMAP;
  113.         }
  114.  
  115.         return true;
  116. }//-------------------------------------------------------------------------------------------------
  117.  
  118. //--------------------------------------------------------------------------------------------------
  119. // Name: ReleaseNode
  120. // Desc: Releases render node
  121. //--------------------------------------------------------------------------------------------------
  122. void CBreakableGlassRenderNode::ReleaseNode(bool bImmediate)
  123. {
  124.         // Remove all remaining glass physics
  125.         DephysicalizeGlass();
  126.  
  127.         const int numPhysFrags = m_physFrags.size();
  128.         SGlassPhysFragment* pPhysFrags = m_physFrags.begin();
  129.  
  130.         for (int i = 0; i < numPhysFrags; ++i)
  131.         {
  132.                 DephysicalizeGlassFragment(pPhysFrags[i]);
  133.         }
  134.  
  135.         // Release glass data
  136.         SAFE_RELEASE(m_glassParams.pGlassMaterial);
  137.  
  138.         if (m_pBreakableGlassRE)
  139.         {
  140.                 m_pBreakableGlassRE->Release(false);
  141.                 m_pBreakableGlassRE = NULL;
  142.         }
  143.  
  144.         bImmediate ? gEnv->p3DEngine->UnRegisterEntityDirect(this) : gEnv->p3DEngine->UnRegisterEntityAsJob(this);
  145. }//-------------------------------------------------------------------------------------------------
  146.  
  147. //--------------------------------------------------------------------------------------------------
  148. // Name: SetId
  149. // Desc: Sets the node's id
  150. //--------------------------------------------------------------------------------------------------
  151. void CBreakableGlassRenderNode::SetId(const uint16 id)
  152. {
  153.         m_id = id;
  154. }//-------------------------------------------------------------------------------------------------
  155.  
  156. //--------------------------------------------------------------------------------------------------
  157. // Name: GetId
  158. // Desc: Returns the node's id
  159. //--------------------------------------------------------------------------------------------------
  160. uint16 CBreakableGlassRenderNode::GetId()
  161. {
  162.         return m_id;
  163. }//-------------------------------------------------------------------------------------------------
  164.  
  165. //--------------------------------------------------------------------------------------------------
  166. // Name: PhysicalizeGlass
  167. // Desc: Creates the physics representation of the plane
  168. //--------------------------------------------------------------------------------------------------
  169. void CBreakableGlassRenderNode::PhysicalizeGlass()
  170. {
  171.         // Generate aabb
  172.         primitives::box box;
  173.         box.Basis.SetIdentity();
  174.         box.center = Vec3(m_glassParams.size.x, m_glassParams.size.y, m_glassParams.thickness) * 0.5f;
  175.         box.size = box.center;
  176.  
  177.         // Create box geometry
  178.         IPhysicalWorld* pPhysWorld = gEnv->pPhysicalWorld;
  179.         IGeomManager* pGeomMan = pPhysWorld->GetGeomManager();
  180.  
  181.         if (IGeometry* pBoxGeom = pGeomMan->CreatePrimitive(primitives::box::type, &box))
  182.         {
  183.                 if (phys_geometry* pPhysGeom = pGeomMan->RegisterGeometry(pBoxGeom))
  184.                 {
  185.                         // Handle ref internally for auto-release w/ phys entity
  186.                         pPhysGeom->nRefCount = 0;
  187.  
  188.                         // Physicalize box
  189.                         if (m_pPhysEnt = pPhysWorld->CreatePhysicalEntity(PE_RIGID, NULL, NULL, PHYS_FOREIGN_ID_BREAKABLE_GLASS))
  190.                         {
  191.                                 // Set box surface params
  192.                                 pe_geomparams geomParams;
  193.                                 geomParams.flags = geom_collides;
  194.                                 geomParams.mass = 0.0f; // Magic number for a static object
  195.                                 geomParams.nMats = 1;
  196.                                 geomParams.pMatMapping = &m_glassParams.surfaceTypeId;
  197.                                 m_pPhysEnt->AddGeometry(pPhysGeom, &geomParams);
  198.  
  199.                                 // Set transformation
  200.                                 pe_params_pos transParams;
  201.                                 transParams.pMtx3x4 = &m_matrix;
  202.                                 m_pPhysEnt->SetParams(&transParams);
  203.  
  204.                                 // Set foreign data to flag this as our glass
  205.                                 pe_params_foreign_data foreignData;
  206.                                 foreignData.pForeignData = this;
  207.                                 foreignData.iForeignData = PHYS_FOREIGN_ID_BREAKABLE_GLASS;
  208.                                 m_pPhysEnt->SetParams(&foreignData);
  209.  
  210.                                 // Limit number of logged collisions
  211.                                 pe_simulation_params simParams;
  212.                                 simParams.maxLoggedCollisions = 2;
  213.                                 m_pPhysEnt->SetParams(&simParams);
  214.                         }
  215.                 }
  216.  
  217.                 pBoxGeom->Release();
  218.         }
  219.  
  220.         // Default state
  221.         m_state = EGlassRNState_Initial;
  222.         m_lastGlassState = SBreakableGlassState();
  223. }//-------------------------------------------------------------------------------------------------
  224.  
  225. //--------------------------------------------------------------------------------------------------
  226. // Name: DephysicalizeGlass
  227. // Desc: Removes the physics representation of the plane
  228. //--------------------------------------------------------------------------------------------------
  229. void CBreakableGlassRenderNode::DephysicalizeGlass()
  230. {
  231.         if (m_pPhysEnt)
  232.         {
  233.                 gEnv->pPhysicalWorld->DestroyPhysicalEntity(m_pPhysEnt);
  234.                 m_pPhysEnt = NULL;
  235.         }
  236. }//-------------------------------------------------------------------------------------------------
  237.  
  238. //--------------------------------------------------------------------------------------------------
  239. // Name: PhysicalizeGlassFragment
  240. // Desc: Creates the physics representation of a glass fragment
  241. //--------------------------------------------------------------------------------------------------
  242. void CBreakableGlassRenderNode::PhysicalizeGlassFragment(SGlassPhysFragment& physFrag, const Vec3& centerOffset)
  243. {
  244.         if (!physFrag.m_pPhysEnt)
  245.         {
  246.                 const float density = 900.0f; // From breakable2DParams
  247.  
  248.                 // Calculate transformation
  249.                 pe_params_pos transParams;
  250.                 transParams.pos = physFrag.m_matrix.TransformPoint(centerOffset);
  251.                 transParams.q = Quat(physFrag.m_matrix);
  252.  
  253.                 // Physicalize particle
  254.                 if (physFrag.m_pPhysEnt = gEnv->pPhysicalWorld->CreatePhysicalEntity(PE_PARTICLE, &transParams))
  255.                 {
  256.                         pe_params_particle particle;
  257.                         particle.size = physFrag.m_size;
  258.                         particle.thickness = m_glassParams.thickness;
  259.                         particle.surface_idx = m_glassParams.surfaceTypeId;
  260.                         particle.mass = particle.size * particle.thickness * density;
  261.                         particle.flags = particle_no_path_alignment | particle_no_roll | particle_traceable | particle_no_self_collisions;
  262.  
  263.                         // Large fragments get logged so we can destroy them on a collision
  264.                         const float shatterSize = 0.65f;
  265.                         if (physFrag.m_size >= shatterSize)
  266.                         {
  267.                                 particle.flags |= pef_log_collisions;
  268.                         }
  269.  
  270.                         particle.normal = Vec3Constants<float>::fVec3_OneZ;
  271.                         particle.q0 = transParams.q;
  272.                         particle.pColliderToIgnore = m_pPhysEnt; // Ignore parent plane
  273.                         physFrag.m_pPhysEnt->SetParams(&particle);
  274.  
  275.                         // Set foreign data to flag this as our glass
  276.                         pe_params_foreign_data foreignData;
  277.                         foreignData.pForeignData = &physFrag;
  278.                         foreignData.iForeignData = PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT;
  279.                         physFrag.m_pPhysEnt->SetParams(&foreignData);
  280.                 }
  281.         }
  282. }//-------------------------------------------------------------------------------------------------
  283.  
  284. //--------------------------------------------------------------------------------------------------
  285. // Name: DephysicalizeGlassFragment
  286. // Desc: Removes the physics representation of a glass fragment
  287. //--------------------------------------------------------------------------------------------------
  288. void CBreakableGlassRenderNode::DephysicalizeGlassFragment(SGlassPhysFragment& physFrag)
  289. {
  290.         // Remove physical entity
  291.         if (physFrag.m_pPhysEnt)
  292.         {
  293.                 gEnv->pPhysicalWorld->DestroyPhysicalEntity(physFrag.m_pPhysEnt);
  294.                 physFrag.m_pPhysEnt = NULL;
  295.  
  296.                 // Push this into the dead list for later syncing
  297.                 uint16 physFragData = physFrag.m_bufferIndex;
  298.                 physFragData |= (uint16)physFrag.m_fragIndex << 8;
  299.                 m_deadPhysFrags.push_back(physFragData);
  300.         }
  301.  
  302.         // Zero lifetime as now dead
  303.         physFrag.m_lifetime = 0.0f;
  304. }//-------------------------------------------------------------------------------------------------
  305.  
  306. //--------------------------------------------------------------------------------------------------
  307. // Name: Update
  308. // Desc: Updates every frame
  309. //--------------------------------------------------------------------------------------------------
  310. void CBreakableGlassRenderNode::Update(SBreakableGlassUpdateParams& params)
  311. {
  312.         if (m_pBreakableGlassRE)
  313.         {
  314.                 // Allow glass to update and isolate fragments to be physicalized
  315.                 TGlassPhysFragmentArray newPhysFrags;
  316.                 TGlassPhysFragmentInitArray newPhysFragsInitData;
  317.  
  318.                 params.m_pPhysFrags = &newPhysFrags;
  319.                 params.m_pPhysFragsInitData = &newPhysFragsInitData;
  320.                 params.m_pDeadPhysFrags = &m_deadPhysFrags;
  321.  
  322.                 m_pBreakableGlassRE->Update(params);
  323.  
  324.                 // Dealt with dead fragments
  325.                 m_deadPhysFrags.clear();
  326.  
  327.                 // Arrays should always be in sync
  328.                 if (newPhysFrags.size() != newPhysFragsInitData.size())
  329.                 {
  330.                         CRY_ASSERT_MESSAGE(0, "Glass physical fragment arrays are out of sync.");
  331.                         LOG_GLASS_ERROR("Physical fragment arrays are out of sync.");
  332.                 }
  333.  
  334.                 // Sync with glass element if data has changed
  335.                 if (params.m_geomChanged)
  336.                 {
  337.                         UpdateGlassState(NULL);
  338.                 }
  339.  
  340.                 // Reset fragment bounding box
  341.                 m_fragBBox.min = m_fragBBox.max = m_planeBBox.GetCenter();
  342.                 float maxFragSize = 0.0f;
  343.  
  344.                 // Add any newly created fragments
  345.                 const int numNewPhysFrags = newPhysFrags.size();
  346.                 bool fragsActive = (numNewPhysFrags > 0);
  347.  
  348.                 for (int i = 0; i < numNewPhysFrags; ++i)
  349.                 {
  350.                         // Recycle next fragment
  351.                         SGlassPhysFragment& physFrag = m_physFrags[m_nextPhysFrag];
  352.                         m_nextPhysFrag = m_nextPhysFrag + 1 < GLASSCFG_MAX_NUM_PHYS_FRAGMENTS ? m_nextPhysFrag + 1 : 0;
  353.  
  354.                         // Remove if slot still in use
  355.                         if (physFrag.m_pPhysEnt)
  356.                         {
  357.                                 DephysicalizeGlassFragment(physFrag);
  358.                         }
  359.  
  360.                         // Initialise
  361.                         const SGlassPhysFragmentInitData& initData = newPhysFragsInitData[i];
  362.                         physFrag = newPhysFrags[i];
  363.  
  364.                         PhysicalizeGlassFragment(physFrag, initData.m_center);
  365.  
  366.                         physFrag.m_pRenderNode = this;
  367.                         physFrag.m_lifetime = LOOSE_FRAG_LIFETIME;
  368.  
  369.                         if (physFrag.m_pPhysEnt)
  370.                         {
  371.                                 // Apply initial impulse
  372.                                 pe_action_impulse applyImpulse;
  373.                                 applyImpulse.impulse = initData.m_impulse;
  374.                                 applyImpulse.point = initData.m_impulsePt;
  375.  
  376.                                 physFrag.m_pPhysEnt->Action(&applyImpulse);
  377.  
  378.                                 // Update bounding box
  379.                                 m_fragBBox.Add(physFrag.m_matrix.GetTranslation());
  380.                                 maxFragSize = max(maxFragSize, physFrag.m_size);
  381.                         }
  382.                 }
  383.  
  384.                 // Update existing loose glass fragments
  385.                 const float frametime = params.m_frametime;
  386.  
  387.                 for (int i = 0; i < GLASSCFG_MAX_NUM_PHYS_FRAGMENTS; ++i)
  388.                 {
  389.                         SGlassPhysFragment& physFrag = m_physFrags[i];
  390.  
  391.                         if (IPhysicalEntity* pPhysEnt = physFrag.m_pPhysEnt)
  392.                         {
  393.                                 fragsActive = true;
  394.  
  395.                                 if (physFrag.m_lifetime > 0.0f)
  396.                                 {
  397.                                         // Age
  398.                                         physFrag.m_lifetime -= frametime;
  399.  
  400.                                         // Sync matrix
  401.                                         pe_status_pos state;
  402.                                         state.pMtx3x4 = &physFrag.m_matrix;
  403.                                         pPhysEnt->GetStatus(&state);
  404.  
  405.                                         // Update bounding box
  406.                                         m_fragBBox.Add(physFrag.m_matrix.GetTranslation());
  407.                                         maxFragSize = max(maxFragSize, physFrag.m_size);
  408.                                 }
  409.                                 else
  410.                                 {
  411.                                         DephysicalizeGlassFragment(physFrag);
  412.                                 }
  413.                         }
  414.                 }
  415.  
  416.                 // Update state flags
  417.                 if (fragsActive)
  418.                 {
  419.                         m_state |= EGlassRNState_ActiveFrags;
  420.                 }
  421.                 else
  422.                 {
  423.                         m_state &= ~EGlassRNState_ActiveFrags;
  424.                 }
  425.  
  426.                 // Expand box to encompass largest fragment
  427.                 m_fragBBox.Expand(Vec3(maxFragSize, maxFragSize, maxFragSize));
  428.         }
  429. }//-------------------------------------------------------------------------------------------------
  430.  
  431. //--------------------------------------------------------------------------------------------------
  432. // Name: HasGlassShattered
  433. // Desc: Used to determine if the glass has fully shattered
  434. //--------------------------------------------------------------------------------------------------
  435. bool CBreakableGlassRenderNode::HasGlassShattered()
  436. {
  437.         return (m_state & EGlassRNState_Shattered) ? true : false;
  438. }//-------------------------------------------------------------------------------------------------
  439.  
  440. //--------------------------------------------------------------------------------------------------
  441. // Name: HasActiveFragments
  442. // Desc: Used to determine if there are any physicalized fragments still active
  443. //--------------------------------------------------------------------------------------------------
  444. bool CBreakableGlassRenderNode::HasActiveFragments()
  445. {
  446.         return (m_state & EGlassRNState_ActiveFrags) ? true : false;
  447. }//-------------------------------------------------------------------------------------------------
  448.  
  449. //--------------------------------------------------------------------------------------------------
  450. // Name: ApplyImpactToGlass
  451. // Desc: Top level impact handler, passes impact down and updates state
  452. //--------------------------------------------------------------------------------------------------
  453. void CBreakableGlassRenderNode::ApplyImpactToGlass(const EventPhysCollision* pPhysEvent)
  454. {
  455.         if (m_pBreakableGlassRE && pPhysEvent)
  456.         {
  457.                 Vec2 impactPt;
  458.                 CalculateImpactPoint(pPhysEvent->pt, impactPt);
  459.  
  460.                 // Break glass if point is within actual bounds
  461.                 SGlassImpactParams params;
  462.                 params.x = impactPt.x;
  463.                 params.y = impactPt.y;
  464.  
  465.                 params.seed = cry_random_uint32();
  466.  
  467.                 // Copy main params
  468.                 params.speed = pPhysEvent->vloc[PHYSEVENT_COLLIDER].len();
  469.                 params.velocity = pPhysEvent->vloc[PHYSEVENT_COLLIDER];
  470.                 params.impulse = params.speed;
  471.  
  472.                 // Try to calculate impulse if valid entity set (Invalid on playback breaks)
  473.                 if (IPhysicalEntity* pCollider = pPhysEvent->pEntity[PHYSEVENT_COLLIDER])
  474.                 {
  475.                         pe_status_dynamics dynamics;
  476.                         if (pCollider->GetStatus(&dynamics))
  477.                         {
  478.                                 params.impulse *= dynamics.mass;
  479.                         }
  480.                 }
  481.                 else if (pPhysEvent->mass[PHYSEVENT_COLLIDER] > 0.0f)
  482.                 {
  483.                         params.impulse *= pPhysEvent->mass[PHYSEVENT_COLLIDER];
  484.                 }
  485.  
  486.                 // Set impact radius to size of entity
  487.                 if (IPhysicalEntity* pPhysEntity = pPhysEvent->pEntity[PHYSEVENT_COLLIDER])
  488.                 {
  489.                         // Test for particle or rigid entity bodies
  490.                         pe_params_particle particle;
  491.                         if (pPhysEntity->GetParams(&particle))
  492.                         {
  493.                                 params.radius = particle.size;
  494.                         }
  495.                         else if (pPhysEntity->GetiForeignData() == PHYS_FOREIGN_ID_ENTITY)
  496.                         {
  497.                                 if (IEntity* pEntity = (IEntity*)pPhysEntity->GetForeignData(PHYS_FOREIGN_ID_ENTITY))
  498.                                 {
  499.                                         AABB aabb;
  500.                                         pEntity->GetLocalBounds(aabb);
  501.  
  502.                                         const float aabbRadiusScale = 0.9f;
  503.                                         params.radius = aabb.GetRadius() * aabbRadiusScale;
  504.                                 }
  505.                         }
  506.                 }
  507.  
  508.                 // Pass impact data into sim
  509.                 m_pBreakableGlassRE->ApplyImpactToGlass(params);
  510.  
  511.                 // Process any changes in glass
  512.                 UpdateGlassState(pPhysEvent);
  513.         }
  514. }//-------------------------------------------------------------------------------------------------
  515.  
  516. //--------------------------------------------------------------------------------------------------
  517. // Name: ApplyExplosionToGlass
  518. // Desc: Passes on the data to the RE and updates glass state
  519. //--------------------------------------------------------------------------------------------------
  520. void CBreakableGlassRenderNode::ApplyExplosionToGlass(const EventPhysCollision* pPhysEvent)
  521. {
  522.         if (m_pBreakableGlassRE && pPhysEvent)
  523.         {
  524.                 Vec2 impactPt;
  525.                 CalculateImpactPoint(pPhysEvent->pt, impactPt);
  526.  
  527.                 // Break glass if point is within actual bounds
  528.                 SGlassImpactParams params;
  529.                 params.x = impactPt.x;
  530.                 params.y = impactPt.y;
  531.  
  532.                 params.seed = cry_random_uint32();
  533.  
  534.                 // Tweak input so values scale better with the system
  535.                 params.speed = GLASSCFG_MIN_BULLET_SPEED * 2.0f;
  536.                 params.velocity = pPhysEvent->vloc[PHYSEVENT_COLLIDER].GetNormalized() * params.speed;
  537.                 params.radius = max(pPhysEvent->radius, 1.0f);
  538.  
  539.                 // Apply a fixed impulse we know will break the glass
  540.                 params.impulse = (GLASSCFG_PLANE_SPLIT_IMPULSE + GLASSCFG_PLANE_SHATTER_IMPULSE) * 0.5f;
  541.  
  542.                 // Pass impact data into sim
  543.                 m_pBreakableGlassRE->ApplyExplosionToGlass(params);
  544.  
  545.                 // Process any changes in glass
  546.                 UpdateGlassState(pPhysEvent);
  547.         }
  548. }//-------------------------------------------------------------------------------------------------
  549.  
  550. //--------------------------------------------------------------------------------------------------
  551. // Name: DestroyPhysFragment
  552. // Desc: Removes a physicalized fragment when it collides
  553. //--------------------------------------------------------------------------------------------------
  554. void CBreakableGlassRenderNode::DestroyPhysFragment(SGlassPhysFragment* pPhysFrag)
  555. {
  556.         if (pPhysFrag && pPhysFrag->m_pPhysEnt)
  557.         {
  558.                 if (pPhysFrag->m_pRenderNode != this)
  559.                 {
  560.                         CRY_ASSERT_MESSAGE(0, "Glass physicalized fragment being destroyed by invalid render node.");
  561.                         LOG_GLASS_ERROR("Physicalized fragment being destroyed by invalid render node.");
  562.                 }
  563.  
  564.                 // Remove glass
  565.                 DephysicalizeGlassFragment(*pPhysFrag);
  566.  
  567.                 // Play effect
  568.                 if (!s_pCVars || s_pCVars->m_particleFXEnable > 0)
  569.                 {
  570.                         if (m_glassParams.pShatterEffect)
  571.                         {
  572.                                 Vec3 center = pPhysFrag->m_matrix.GetTranslation();
  573.                                 Vec3 dir = Vec3Constants<f32>::fVec3_OneZ;
  574.                                 float size = pPhysFrag->m_size;
  575.  
  576.                                 float effectScale = s_pCVars ? s_pCVars->m_particleFXScale : 0.25f;
  577.  
  578.                                 // Update effect colour to match this glass
  579.                                 if (!s_pCVars || s_pCVars->m_particleFXUseColours > 0)
  580.                                 {
  581.                                         // Blend colour so smaller shatters are whiter/cloudier
  582.                                         Vec4 particleColour = m_glassTintColour;
  583.                                         float sizeLerp = min(size, 1.0f);
  584.  
  585.                                         particleColour.x += sizeLerp * (1.0f - particleColour.x);
  586.                                         particleColour.y += sizeLerp * (1.0f - particleColour.y);
  587.                                         particleColour.z += sizeLerp * (1.0f - particleColour.z);
  588.  
  589.                                         SetParticleEffectColours(m_glassParams.pShatterEffect, m_glassTintColour);
  590.                                 }
  591.  
  592.                                 // Spawn effect emitter
  593.                                 SpawnParams spawnParams;
  594.                                 spawnParams.fCountScale = effectScale * size;
  595.                                 spawnParams.fSizeScale = size;
  596.  
  597.                                 QuatTS spawnLoc;
  598.                                 spawnLoc.q = Quat::CreateRotationVDir(dir);
  599.                                 spawnLoc.t = center;
  600.                                 spawnLoc.s = 1.f;
  601.  
  602.                                 m_glassParams.pShatterEffect->Spawn(spawnLoc, &spawnParams);
  603.                         }
  604.                 }
  605.         }
  606. }//-------------------------------------------------------------------------------------------------
  607.  
  608. //--------------------------------------------------------------------------------------------------
  609. // Name: CalculateImpactPoint
  610. // Desc: Calculates an impact point (if any) from the input position
  611. //--------------------------------------------------------------------------------------------------
  612. void CBreakableGlassRenderNode::CalculateImpactPoint(const Vec3& pt, Vec2& impactPt)
  613. {
  614.         // Create point in plane's local space
  615.         Matrix34 invPlaneTransMat = m_matrix.GetInvertedFast();
  616.         Vec3 localPt = invPlaneTransMat.TransformPoint(pt);
  617.  
  618.         // Can assume valid as a phys event led here
  619.         impactPt.x = clamp_tpl<float>(localPt.x, GLASS_IMPACT_BOUNDARY, m_glassParams.size.x - GLASS_IMPACT_BOUNDARY);
  620.         impactPt.y = clamp_tpl<float>(localPt.y, GLASS_IMPACT_BOUNDARY, m_glassParams.size.y - GLASS_IMPACT_BOUNDARY);
  621. }//-------------------------------------------------------------------------------------------------
  622.  
  623. //--------------------------------------------------------------------------------------------------
  624. // Name: UpdateGlassState
  625. // Desc: Spawns/plays glass impact effects
  626. //--------------------------------------------------------------------------------------------------
  627. void CBreakableGlassRenderNode::UpdateGlassState(const EventPhysCollision* pPhysEvent)
  628. {
  629.         if (m_pBreakableGlassRE && m_pPhysEnt)
  630.         {
  631.                 // Get updated glass state
  632.                 uint8 lastNumImpacts = m_lastGlassState.m_numImpacts;
  633.                 uint8 lastNumLooseFrags = m_lastGlassState.m_numLooseFrags;
  634.  
  635.                 m_pBreakableGlassRE->GetGlassState(m_lastGlassState);
  636.                 bool physicsChanged = false;
  637.  
  638.                 // If several loose fragments created, play breakage effect
  639.                 const uint8 minFragsForEffect = 2;
  640.                 if (m_lastGlassState.m_numLooseFrags > lastNumLooseFrags + minFragsForEffect)
  641.                 {
  642.                         PlayBreakageEffect(pPhysEvent);
  643.                 }
  644.  
  645.                 // If glass shatters from impact, de-physicalize
  646.                 if (m_lastGlassState.m_hasShattered && m_pPhysEnt)
  647.                 {
  648.                         DephysicalizeGlass();
  649.                         physicsChanged = true;
  650.                 }
  651.                 else if (!(m_state & EGlassRNState_Weakened)
  652.                          && !m_lastGlassState.m_hasShattered
  653.                          && m_lastGlassState.m_numImpacts > lastNumImpacts)
  654.                 {
  655.                         // Flag all parts with no collision response, to allow objects to pass through
  656.                         // after first successful impact. We also remove the "man_break" flag as some
  657.                         // materials auto-add it during the physics entity initialisation
  658.                         pe_params_part colltype;
  659.                         colltype.flagsOR = geom_no_coll_response;
  660.                         colltype.flagsAND = ~geom_manually_breakable;
  661.                         m_pPhysEnt->SetParams(&colltype);
  662.  
  663.                         // Update surface type with more pierceable material
  664.                         //      pe_params_part partParams;
  665.                         //      partParams.nMats = 1;
  666.                         //      partParams.pMatMapping = &m_weakGlassTypeId;
  667.                         //      m_pPhysEnt->SetParams(&partParams);
  668.  
  669.                         // Update internal flags
  670.                         m_state |= EGlassRNState_Weakened;
  671.                         physicsChanged = true;
  672.                 }
  673.  
  674.                 // On physical state change, wake all entities resting on this glass so they can fall through
  675.                 if (physicsChanged)
  676.                 {
  677.                         AABB glassArea = m_planeBBox;
  678.                         glassArea.Expand(Vec3Constants<f32>::fVec3_One);
  679.  
  680.                         IPhysicalEntity** pEntities = NULL;
  681.                         int numEntities = gEnv->pPhysicalWorld->GetEntitiesInBox(glassArea.min, glassArea.max, pEntities, ent_sleeping_rigid | ent_living | ent_ignore_noncolliding);
  682.  
  683.                         for (int i = 0; i < numEntities; ++i)
  684.                         {
  685.                                 if (IPhysicalEntity* pPhysEnt = pEntities[i])
  686.                                 {
  687.                                         // Only need to wake up sleeping entities
  688.                                         pe_status_awake status;
  689.                                         if (pPhysEnt->GetStatus(&status) == 0)
  690.                                         {
  691.                                                 pe_action_awake wake;
  692.                                                 wake.bAwake = 1;
  693.                                                 pPhysEnt->Action(&wake);
  694.                                         }
  695.                                 }
  696.                         }
  697.                 }
  698.  
  699.                 // If we no longer have a physical presence, no need to exist
  700.                 if (!m_pPhysEnt)
  701.                 {
  702.                         m_state |= EGlassRNState_Shattering;
  703.                 }
  704.         }
  705. }//-------------------------------------------------------------------------------------------------
  706.  
  707. //--------------------------------------------------------------------------------------------------
  708. // Name: SetParticleEffectColours
  709. // Desc: Recursively updates all of a particular particle effect's colour params
  710. //--------------------------------------------------------------------------------------------------
  711. void CBreakableGlassRenderNode::SetParticleEffectColours(IParticleEffect* pEffect, const Vec4& rgba)
  712. {
  713.         if (pEffect)
  714.         {
  715.                 // Set this node
  716.                 ParticleParams partParams = pEffect->GetParticleParams();
  717.                 partParams.cColor.Set(Color3F(rgba.x, rgba.y, rgba.z));
  718.                 partParams.fAlpha.Set(rgba.w);
  719.                 pEffect->SetParticleParams(partParams);
  720.  
  721.                 // Recurse through children
  722.                 const int numSubEffects = pEffect->GetChildCount();
  723.                 for (int i = 0; i < numSubEffects; ++i)
  724.                 {
  725.                         SetParticleEffectColours(pEffect->GetChild(i), rgba);
  726.                 }
  727.         }
  728. }//-------------------------------------------------------------------------------------------------
  729.  
  730. //--------------------------------------------------------------------------------------------------
  731. // Name: PlayBreakageEffect
  732. // Desc: Spawns/plays glass impact breakage effects
  733. //--------------------------------------------------------------------------------------------------
  734. void CBreakableGlassRenderNode::PlayBreakageEffect(const EventPhysCollision* pPhysEvent)
  735. {
  736.         if (m_glassParams.pGlassMaterial && pPhysEvent)
  737.         {
  738.                 if (IMaterialEffects* pMaterialEffects = gEnv->pMaterialEffects)
  739.                 {
  740.                         // Set effect params
  741.                         SMFXBreakageParams breakParams;
  742.                         breakParams.SetHitPos(pPhysEvent->pt);
  743.                         breakParams.SetVelocity(pPhysEvent->vloc[PHYSEVENT_COLLIDER]);
  744.                         breakParams.SetMass(0.0f);
  745.  
  746.                         // Play breakage effect
  747.                         pMaterialEffects->PlayBreakageEffect(m_glassParams.pGlassMaterial->GetSurfaceType(), "Breakage", breakParams);
  748.                 }
  749.         }
  750. }//-------------------------------------------------------------------------------------------------
  751.  
  752. //--------------------------------------------------------------------------------------------------
  753. // Name: GetName
  754. // Desc: Gets the node's name
  755. //--------------------------------------------------------------------------------------------------
  756. const char* CBreakableGlassRenderNode::GetName() const
  757. {
  758.         return "BreakableGlass";
  759. }//-------------------------------------------------------------------------------------------------
  760.  
  761. //--------------------------------------------------------------------------------------------------
  762. // Name: GetEntityClassName
  763. // Desc: Gets the entity's class name
  764. //--------------------------------------------------------------------------------------------------
  765. const char* CBreakableGlassRenderNode::GetEntityClassName() const
  766. {
  767.         return "BreakableGlass";
  768. }//-------------------------------------------------------------------------------------------------
  769.  
  770. //--------------------------------------------------------------------------------------------------
  771. // Name: GetMemoryUsage
  772. // Desc: Gets the node's memory usage
  773. //--------------------------------------------------------------------------------------------------
  774. void CBreakableGlassRenderNode::GetMemoryUsage(ICrySizer* pSizer) const
  775. {
  776.         SIZER_COMPONENT_NAME(pSizer, "BreakableGlassRenderNode");
  777.         pSizer->AddObject(this, sizeof(*this));
  778. }//-------------------------------------------------------------------------------------------------
  779.  
  780. //--------------------------------------------------------------------------------------------------
  781. // Name: SetMaterial
  782. // Desc: Sets the node's material
  783. //--------------------------------------------------------------------------------------------------
  784. void CBreakableGlassRenderNode::SetMaterial(IMaterial* pMaterial)
  785. {
  786.         // Update material pointer if changed
  787.         if (pMaterial == m_glassParams.pGlassMaterial)
  788.                 return;
  789.  
  790.         if (m_glassParams.pGlassMaterial)
  791.         {
  792.                 m_glassParams.pGlassMaterial->Release();
  793.         }
  794.  
  795.         m_glassParams.pGlassMaterial = pMaterial;
  796.  
  797.         if (m_glassParams.pGlassMaterial)
  798.         {
  799.                 m_glassParams.pGlassMaterial->AddRef();
  800.  
  801.                 // Extract glass tint colour parameters
  802.                 const SShaderItem& shaderItem = pMaterial->GetShaderItem();
  803.                 float tintCloudiness = 0.0f;
  804.  
  805.                 if (shaderItem.m_pShaderResources && shaderItem.m_pShader)
  806.                 {
  807.                         DynArrayRef<SShaderParam>& shaderParams = shaderItem.m_pShaderResources->GetParameters();
  808.                         const int numParams = shaderParams.size();
  809.  
  810.                         for (int i = 0; i < numParams; ++i)
  811.                         {
  812.                                 if (SShaderParam* sp = &shaderParams[i])
  813.                                 {
  814.                                         if (!stricmp(sp->m_Name, GLASS_TINT_COLOUR_PARAM)
  815.                                             || !stricmp(sp->m_Name, GLASS_TINT_CLOUDINESS_PARAM))
  816.                                         {
  817.                                                 switch (sp->m_Type)
  818.                                                 {
  819.                                                 case eType_FLOAT:
  820.                                                         tintCloudiness = sp->m_Value.m_Float;
  821.                                                         break;
  822.  
  823.                                                 case eType_FCOLOR:
  824.                                                         m_glassTintColour[0] = sp->m_Value.m_Vector[0];
  825.                                                         m_glassTintColour[1] = sp->m_Value.m_Vector[1];
  826.                                                         m_glassTintColour[2] = sp->m_Value.m_Vector[2];
  827.                                                         break;
  828.                                                 }
  829.                                         }
  830.                                 }
  831.                         }
  832.  
  833.                         // Blend diffuse colour with tint colour based on cloudiness
  834.                         const ColorF& diffuse = shaderItem.m_pShaderResources->GetColorValue(EFTT_DIFFUSE);
  835.  
  836.                         m_glassTintColour.x = LERP(diffuse.r * m_glassTintColour.x, diffuse.r + m_glassTintColour.x, tintCloudiness);
  837.                         m_glassTintColour.y = LERP(diffuse.g * m_glassTintColour.y, diffuse.g + m_glassTintColour.y, tintCloudiness);
  838.                         m_glassTintColour.z = LERP(diffuse.b * m_glassTintColour.z, diffuse.b + m_glassTintColour.z, tintCloudiness);
  839.  
  840.                         // Finally store alpha
  841.                         m_glassTintColour.w = shaderItem.m_pShaderResources->GetStrengthValue(EFTT_OPACITY);
  842.                 }
  843.                 else
  844.                 {
  845.                         // Default to mid-grey
  846.                         m_glassTintColour = Vec4(0.5f, 0.5f, 0.5f, 0.5f);
  847.                 }
  848.         }
  849. }//-------------------------------------------------------------------------------------------------
  850.  
  851. //--------------------------------------------------------------------------------------------------
  852. // Name: SetMatrix
  853. // Desc: Sets the node's matrix and updates the bbox
  854. //--------------------------------------------------------------------------------------------------
  855. void CBreakableGlassRenderNode::SetMatrix(const Matrix34& matrix)
  856. {
  857.         gEnv->p3DEngine->UnRegisterEntityAsJob(this);
  858.         m_matrix = matrix;
  859.  
  860.         // Update world-space bounding box
  861.         m_planeBBox.min.Set(0.0f, 0.0f, 0.0f);
  862.         m_planeBBox.max.Set(m_glassParams.size.x, m_glassParams.size.y, m_glassParams.thickness);
  863.         m_planeBBox.SetTransformedAABB(m_matrix, m_planeBBox);
  864.  
  865.         // Update render element
  866.         if (SBreakableGlassREParams* pREParams = (SBreakableGlassREParams*)m_pBreakableGlassRE->GetParams())
  867.         {
  868.                 pREParams->matrix = m_matrix;
  869.         }
  870.  
  871.         // Update physics entity
  872.         if (m_pPhysEnt)
  873.         {
  874.                 pe_params_pos transParams;
  875.                 transParams.pMtx3x4 = &m_matrix;
  876.                 m_pPhysEnt->SetParams(&transParams);
  877.         }
  878.  
  879.         gEnv->p3DEngine->RegisterEntity(this);
  880. }//-------------------------------------------------------------------------------------------------
  881.  
  882. //--------------------------------------------------------------------------------------------------
  883. // Name: SetBBox
  884. // Desc: Sets the node's bbox
  885. //--------------------------------------------------------------------------------------------------
  886. void CBreakableGlassRenderNode::SetBBox(const AABB& worldSpaceBoundingBox)
  887. {
  888.         m_planeBBox = worldSpaceBoundingBox;
  889. }//-------------------------------------------------------------------------------------------------
  890.  
  891. //--------------------------------------------------------------------------------------------------
  892. // Name: GetPhysics
  893. // Desc: Gets the node's physics
  894. //--------------------------------------------------------------------------------------------------
  895. IPhysicalEntity* CBreakableGlassRenderNode::GetPhysics() const
  896. {
  897.         return m_pPhysEnt;
  898. }//-------------------------------------------------------------------------------------------------
  899.  
  900. //--------------------------------------------------------------------------------------------------
  901. // Name: SetPhysics
  902. // Desc: Sets the node's physics
  903. //--------------------------------------------------------------------------------------------------
  904. void CBreakableGlassRenderNode::SetPhysics(IPhysicalEntity* pPhysics)
  905. {
  906. }//-------------------------------------------------------------------------------------------------
  907.  
  908. //--------------------------------------------------------------------------------------------------
  909. // Name: GetMaterialOverride
  910. // Desc: Returns the material override
  911. //--------------------------------------------------------------------------------------------------
  912. IMaterial* CBreakableGlassRenderNode::GetMaterialOverride()
  913. {
  914.         return m_glassParams.pGlassMaterial;
  915. }//-------------------------------------------------------------------------------------------------
  916.  
  917. //--------------------------------------------------------------------------------------------------
  918. // Name: SetCVars
  919. // Desc: Updates the cvar pointer
  920. //--------------------------------------------------------------------------------------------------
  921. void CBreakableGlassRenderNode::SetCVars(const SBreakableGlassCVars* pCVars)
  922. {
  923.         s_pCVars = pCVars;
  924.  
  925.         if (m_pBreakableGlassRE)
  926.         {
  927.                 m_pBreakableGlassRE->SetCVars(pCVars);
  928.         }
  929. }
  930. //--------------------------------------------------------------------------------------------------
  931.  
  932. //--------------------------------------------------------------------------------------------------
  933. // Name: Render
  934. // Desc: Renders the node
  935. //--------------------------------------------------------------------------------------------------
  936. void CBreakableGlassRenderNode::Render(const SRendParams& renderParams, const SRenderingPassInfo& passInfo)
  937. {
  938.         if (m_glassParams.pGlassMaterial && m_pBreakableGlassRE)
  939.         {
  940.                 const int renderThreadListID = passInfo.ThreadID();
  941.                 IMaterial* pMaterial = m_glassParams.pGlassMaterial;
  942.  
  943.                 // Set render element parameters
  944.                 SBreakableGlassREParams* pREParams = (SBreakableGlassREParams*)m_pBreakableGlassRE->GetParams();
  945.  
  946.                 const CCamera& camera = gEnv->pRenderer->GetCamera();
  947.                 const Vec3 cameraPos = camera.GetPosition();
  948.                 pREParams->centre = cameraPos;
  949.  
  950.                 const int beforeWater = 0;
  951.                 const int afterWater = 1;
  952.                 const bool isShattering = (m_state & EGlassRNState_Shattering) ? true : false;
  953.  
  954.                 if (!m_lastGlassState.m_hasShattered || isShattering)
  955.                 {
  956.                         // We allow one final draw to avoid popping during updates
  957.                         if (isShattering)
  958.                         {
  959.                                 m_state &= ~EGlassRNState_Shattering;
  960.                                 m_state |= EGlassRNState_Shattered;
  961.                         }
  962.  
  963.                         // Submit render object for cracks
  964.                         if (CRenderObject* pRenderObject = gEnv->pRenderer->EF_GetObject_Temp(renderThreadListID))
  965.                         {
  966.                                 // Set render object properties
  967.                                 pRenderObject->m_II.m_Matrix = m_matrix;
  968.                                 pRenderObject->m_ObjFlags |= FOB_TRANS_MASK;
  969.                                 pRenderObject->m_fSort = 0;
  970.                                 pRenderObject->m_fDistance = renderParams.fDistance;
  971.                                 pRenderObject->m_pCurrMaterial = NULL;  // Null flags as cracks
  972.                                 pRenderObject->m_pRenderNode = this;
  973.                                 pRenderObject->m_II.m_AmbColor = renderParams.AmbientColor;
  974.                                 pRenderObject->m_breakableGlassSubFragIndex = GLASSCFG_GLASS_PLANE_FLAG_LOD;
  975.                                 pRenderObject->m_nTextureID = renderParams.nTextureID;
  976.  
  977.                                 // Add render element and render object to render list
  978.                                 gEnv->pRenderer->EF_AddEf(m_pBreakableGlassRE, pMaterial->GetShaderItem(), pRenderObject, passInfo, EFSLIST_TRANSP, beforeWater);
  979.                         }
  980.  
  981.                         // Submit render object for plane
  982.                         if (CRenderObject* pRenderObject = gEnv->pRenderer->EF_GetObject_Temp(renderThreadListID))
  983.                         {
  984.                                 // Offset glass surface towards edge nearest viewer
  985.                                 const Vec3 normal = m_matrix.GetColumn2().GetNormalizedFast();
  986.                                 const Vec3 camDir = (m_matrix.GetTranslation() - cameraPos).GetNormalizedFast();
  987.  
  988.                                 const float viewerSide = normal.Dot(camDir) > 0.0f ? -1.0f : 1.0f;
  989.                                 const float halfThickness = m_glassParams.thickness * 0.5f;
  990.                                 Vec3 offset = normal * (halfThickness * viewerSide);
  991.  
  992.                                 // Set render object properties
  993.                                 pRenderObject->m_II.m_Matrix = m_matrix;
  994.                                 pRenderObject->m_II.m_Matrix.AddTranslation(offset);
  995.                                 pRenderObject->m_ObjFlags |= FOB_TRANS_MASK;
  996.                                 pRenderObject->m_fSort = 0;
  997.                                 pRenderObject->m_fDistance = renderParams.fDistance;
  998.                                 pRenderObject->m_pCurrMaterial = pMaterial;  // Material flags as plane
  999.                                 pRenderObject->m_pRenderNode = this;
  1000.                                 pRenderObject->m_II.m_AmbColor = renderParams.AmbientColor;
  1001.                                 pRenderObject->m_breakableGlassSubFragIndex = GLASSCFG_GLASS_PLANE_FLAG_LOD;
  1002.                                 pRenderObject->m_nTextureID = renderParams.nTextureID;
  1003.  
  1004.                                 // Add render element and render object to render list
  1005.                                 gEnv->pRenderer->EF_AddEf(m_pBreakableGlassRE, pMaterial->GetShaderItem(), pRenderObject, passInfo, EFSLIST_TRANSP, afterWater);
  1006.                         }
  1007.                 }
  1008.  
  1009.                 // Draw any physicalized fragment cracks
  1010.                 SGlassPhysFragment* pPhysFrags = m_physFrags.begin();
  1011.                 CRY_ASSERT(GLASSCFG_MAX_NUM_PHYS_FRAGMENTS == m_physFrags.max_size());
  1012.  
  1013.                 for (int i = 0; i < GLASSCFG_MAX_NUM_PHYS_FRAGMENTS; ++i)
  1014.                 {
  1015.                         SGlassPhysFragment& physFrag = pPhysFrags[i];
  1016.  
  1017.                         if (physFrag.m_pPhysEnt || !physFrag.m_initialised)
  1018.                         {
  1019.                                 // Calculate distance and fragment alpha
  1020.                                 const float dist = (cameraPos - physFrag.m_matrix.GetTranslation()).GetLengthFast();
  1021.                                 const float alpha = min(physFrag.m_lifetime * physFrag.m_lifetime, 1.0f);
  1022.  
  1023.                                 // Submit render object for full fragment
  1024.                                 if (CRenderObject* pRenderObject = gEnv->pRenderer->EF_GetObject_Temp(renderThreadListID))
  1025.                                 {
  1026.                                         // All phys fragments have to be drawn at least once regardless of state
  1027.                                         // - This allows internal buffer states/syncs to remain balanced
  1028.                                         physFrag.m_initialised = true;
  1029.  
  1030.                                         // Set render object properties
  1031.                                         pRenderObject->m_II.m_Matrix = physFrag.m_matrix;
  1032.                                         pRenderObject->m_ObjFlags |= FOB_TRANS_MASK;
  1033.                                         pRenderObject->m_fSort = 0;
  1034.                                         pRenderObject->m_fAlpha = alpha;
  1035.                                         pRenderObject->m_fDistance = dist;
  1036.                                         pRenderObject->m_pCurrMaterial = pMaterial;  // Material flags as plane
  1037.                                         pRenderObject->m_pRenderNode = this;
  1038.                                         pRenderObject->m_II.m_AmbColor = renderParams.AmbientColor;
  1039.                                         pRenderObject->m_breakableGlassSubFragIndex = physFrag.m_bufferIndex;
  1040.                                         pRenderObject->m_nTextureID = renderParams.nTextureID;
  1041.  
  1042.                                         // Add render element and render object to render list
  1043.                                         gEnv->pRenderer->EF_AddEf(m_pBreakableGlassRE, pMaterial->GetShaderItem(), pRenderObject, passInfo, EFSLIST_TRANSP, afterWater);
  1044.                                 }
  1045.  
  1046. #ifdef GLASS_DEBUG_MODE
  1047.                                 // Draw debug data
  1048.                                 if (s_pCVars && s_pCVars->m_drawFragData)
  1049.                                 {
  1050.                                         m_pBreakableGlassRE->DrawFragmentDebug(physFrag.m_fragIndex, physFrag.m_matrix, physFrag.m_bufferIndex, alpha);
  1051.                                 }
  1052. #endif
  1053.                         }
  1054.                 }
  1055.         }
  1056. }//-------------------------------------------------------------------------------------------------
  1057.  
  1058. void CBreakableGlassRenderNode::OffsetPosition(const Vec3& delta)
  1059. {
  1060.         if (m_pTempData) m_pTempData->OffsetPosition(delta);
  1061.         m_planeBBox.Move(delta);
  1062.         m_fragBBox.Move(delta);
  1063.         m_matrix.SetTranslation(m_matrix.GetTranslation() + delta);
  1064.         if (m_pPhysEnt)
  1065.         {
  1066.                 pe_params_pos par_pos;
  1067.                 par_pos.pos = m_matrix.GetTranslation();
  1068.                 m_pPhysEnt->SetParams(&par_pos);
  1069.         }
  1070. }
  1071.  
  1072. void CBreakableGlassRenderNode::FillBBox(AABB& aabb)
  1073. {
  1074.         aabb = CBreakableGlassRenderNode::GetBBox();
  1075. }
  1076.  
  1077. const AABB CBreakableGlassRenderNode::GetBBox() const
  1078. {
  1079.         AABB bbox = m_planeBBox;
  1080.         bbox.Add(m_fragBBox);
  1081.         return bbox;
  1082. }
  1083.  
  1084. EERType CBreakableGlassRenderNode::GetRenderNodeType()
  1085. {
  1086.         return eERType_BreakableGlass;
  1087. }
  1088.  
  1089. float CBreakableGlassRenderNode::GetMaxViewDist()
  1090. {
  1091.         return m_maxViewDist;
  1092. }
  1093.  
  1094. Vec3 CBreakableGlassRenderNode::GetPos(bool worldOnly) const
  1095. {
  1096.         return m_matrix.GetTranslation();
  1097. }
  1098.  
  1099. IMaterial* CBreakableGlassRenderNode::GetMaterial(Vec3* pHitPos) const
  1100. {
  1101.         return m_glassParams.pGlassMaterial;
  1102. }
  1103.  
downloadBreakableGlassRenderNode.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