summaryrefslogtreecommitdiffstats
path: root/src/renderer/Glass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/Glass.cpp')
-rw-r--r--src/renderer/Glass.cpp1027
1 files changed, 1027 insertions, 0 deletions
diff --git a/src/renderer/Glass.cpp b/src/renderer/Glass.cpp
new file mode 100644
index 00000000..b4ec8c7e
--- /dev/null
+++ b/src/renderer/Glass.cpp
@@ -0,0 +1,1027 @@
+#include "common.h"
+
+#include "Glass.h"
+#include "Timer.h"
+#include "Object.h"
+#include "Vehicle.h"
+#include "Pools.h"
+#include "General.h"
+#include "AudioScriptObject.h"
+#include "World.h"
+#include "Timecycle.h"
+#include "Particle.h"
+#include "Camera.h"
+#include "RenderBuffer.h"
+#include "Shadows.h"
+#include "ModelIndices.h"
+#include "main.h"
+#include "soundlist.h"
+#include "SurfaceTable.h"
+
+
+uint32 CGlass::NumGlassEntities;
+CEntity *CGlass::apEntitiesToBeRendered[NUM_GLASSENTITIES];
+CFallingGlassPane CGlass::aGlassPanes[NUM_GLASSPANES];
+
+
+CVector2D CentersWithTriangle[NUM_GLASSTRIANGLES];
+const CVector2D CoorsWithTriangle[NUM_GLASSTRIANGLES][3] =
+{
+ {
+ CVector2D(0.0f, 0.0f),
+ CVector2D(0.0f, 1.0f),
+ CVector2D(0.4f, 0.5f)
+ },
+
+ {
+ CVector2D(0.0f, 1.0f),
+ CVector2D(1.0f, 1.0f),
+ CVector2D(0.4f, 0.5f)
+ },
+
+ {
+ CVector2D(0.0f, 0.0f),
+ CVector2D(0.4f, 0.5f),
+ CVector2D(0.7f, 0.0f)
+ },
+
+ {
+ CVector2D(0.7f, 0.0f),
+ CVector2D(0.4f, 0.5f),
+ CVector2D(1.0f, 1.0f)
+ },
+
+ {
+ CVector2D(0.7f, 0.0f),
+ CVector2D(1.0f, 1.0f),
+ CVector2D(1.0f, 0.0f)
+ }
+};
+
+#define TEMPBUFFERVERTHILIGHTOFFSET 0
+#define TEMPBUFFERINDEXHILIGHTOFFSET 0
+#define TEMPBUFFERVERTHILIGHTSIZE 256
+#define TEMPBUFFERINDEXHILIGHTSIZE 512
+
+#define TEMPBUFFERVERTSHATTEREDOFFSET TEMPBUFFERVERTHILIGHTSIZE
+#define TEMPBUFFERINDEXSHATTEREDOFFSET TEMPBUFFERINDEXHILIGHTSIZE
+#define TEMPBUFFERVERTSHATTEREDSIZE 384
+#define TEMPBUFFERINDEXSHATTEREDSIZE 768
+
+#define TEMPBUFFERVERTREFLECTIONOFFSET TEMPBUFFERVERTSHATTEREDSIZE
+#define TEMPBUFFERINDEXREFLECTIONOFFSET TEMPBUFFERINDEXSHATTEREDSIZE
+#define TEMPBUFFERVERTREFLECTIONSIZE 512
+#define TEMPBUFFERINDEXREFLECTIONSIZE 1024
+
+int32 TempBufferIndicesStoredHiLight = 0;
+int32 TempBufferVerticesStoredHiLight = 0;
+int32 TempBufferIndicesStoredShattered = 0;
+int32 TempBufferVerticesStoredShattered = 0;
+int32 TempBufferIndicesStoredReflection = 0;
+int32 TempBufferVerticesStoredReflection = 0;
+
+void
+CFallingGlassPane::Update(void)
+{
+ if ( CTimer::GetTimeInMilliseconds() >= m_nTimer )
+ {
+ // Apply MoveSpeed
+ if ( m_bCarGlass )
+ GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep() * 0.35f;
+ else
+ GetPosition() += m_vecMoveSpeed * CTimer::GetTimeStep();
+
+ // Apply Gravity
+ if ( m_bCarGlass )
+ m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();
+ else
+ m_vecMoveSpeed.z -= 0.02f * CTimer::GetTimeStep();
+
+ // Apply TurnSpeed
+ GetRight() += CrossProduct(m_vecTurn, GetRight());
+ GetForward() += CrossProduct(m_vecTurn, GetForward());
+ GetUp() += CrossProduct(m_vecTurn, GetUp());
+
+ if ( GetPosition().z < m_fGroundZ )
+ {
+ CVector pos;
+ CVector dir;
+
+ m_bActive = false;
+
+ pos = CVector(GetPosition().x, GetPosition().y, m_fGroundZ);
+
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_LIGHT_BREAK, pos);
+
+ RwRGBA color = { 255, 255, 255, 255 };
+
+ if ( !m_bCarGlass )
+ {
+ static int32 nFrameGen = 0;
+
+ for ( int32 i = 0; i < 4; i++ )
+ {
+ dir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);
+ dir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);
+ dir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f);
+
+ CParticle::AddParticle(PARTICLE_CAR_DEBRIS,
+ pos,
+ dir,
+ nil,
+ CGeneral::GetRandomNumberInRange(0.02f, 0.2f),
+ color,
+ CGeneral::GetRandomNumberInRange(-40, 40),
+ 0,
+ ++nFrameGen & 3,
+ 500);
+ }
+ }
+ }
+ }
+}
+
+void
+CFallingGlassPane::Render(void)
+{
+ float distToCamera = (TheCamera.GetPosition() - GetPosition()).Magnitude();
+
+ CVector fwdNorm = GetForward();
+ fwdNorm.Normalise();
+ uint8 alpha = CGlass::CalcAlphaWithNormal(&fwdNorm);
+
+#ifdef FIX_BUGS
+ uint16 time = Clamp(CTimer::GetTimeInMilliseconds() > m_nTimer ? CTimer::GetTimeInMilliseconds() - m_nTimer : 0u, 0u, 500u);
+#else
+ uint16 time = Clamp(CTimer::GetTimeInMilliseconds() - m_nTimer, 0, 500);
+#endif
+
+ uint8 color = int32( float(alpha) * (float(time) / 500) );
+
+ if ( TempBufferIndicesStoredHiLight >= TEMPBUFFERINDEXHILIGHTSIZE-7 || TempBufferVerticesStoredHiLight >= TEMPBUFFERVERTHILIGHTSIZE-4 )
+ CGlass::RenderHiLightPolys();
+
+ // HiLight Polys
+
+ if ( m_bCarGlass && color < 64 )
+ color = 64;
+
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], color, color, color, color);
+
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], 0.5f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], 0.5f);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], 0.5f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], 0.6f);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], 0.6f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], 0.6f);
+
+ ASSERT(m_nTriIndex < NUM_GLASSTRIANGLES);
+
+ CVector2D p0 = CoorsWithTriangle[m_nTriIndex][0] - CentersWithTriangle[m_nTriIndex];
+ CVector2D p1 = CoorsWithTriangle[m_nTriIndex][1] - CentersWithTriangle[m_nTriIndex];
+ CVector2D p2 = CoorsWithTriangle[m_nTriIndex][2] - CentersWithTriangle[m_nTriIndex];
+ CVector v0 = *this * CVector(p0.x, 0.0f, p0.y);
+ CVector v1 = *this * CVector(p1.x, 0.0f, p1.y);
+ CVector v2 = *this * CVector(p2.x, 0.0f, p2.y);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], v0.x, v0.y, v0.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], v1.x, v1.y, v1.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], v2.x, v2.y, v2.z);
+
+ TempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 0] = TempBufferVerticesStoredHiLight + 0;
+ TempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 1] = TempBufferVerticesStoredHiLight + 1;
+ TempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 2] = TempBufferVerticesStoredHiLight + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 3] = TempBufferVerticesStoredHiLight + 0;
+ TempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 4] = TempBufferVerticesStoredHiLight + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 5] = TempBufferVerticesStoredHiLight + 1;
+
+ TempBufferVerticesStoredHiLight += 3;
+ TempBufferIndicesStoredHiLight += 6;
+
+ if ( m_bShattered )
+ {
+ if ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-7 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-4 )
+ CGlass::RenderShatteredPolys();
+
+ uint8 shatteredColor = 140;
+ if ( distToCamera > 30.0f )
+ shatteredColor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 140);
+
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], shatteredColor, shatteredColor, shatteredColor, shatteredColor);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], shatteredColor, shatteredColor, shatteredColor, shatteredColor);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], shatteredColor, shatteredColor, shatteredColor, shatteredColor);
+
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 4.0f * CoorsWithTriangle[m_nTriIndex][0].x * m_fStep);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 4.0f * CoorsWithTriangle[m_nTriIndex][0].y * m_fStep);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 4.0f * CoorsWithTriangle[m_nTriIndex][1].x * m_fStep);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 4.0f * CoorsWithTriangle[m_nTriIndex][1].y * m_fStep);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 4.0f * CoorsWithTriangle[m_nTriIndex][2].x * m_fStep);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 4.0f * CoorsWithTriangle[m_nTriIndex][2].y * m_fStep);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], v0.x, v0.y, v0.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], v1.x, v1.y, v1.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], v2.x, v2.y, v2.z);
+
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 0] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 0;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 1] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 1;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 2] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 3] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 0;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 4] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 2;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 5] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 1;
+
+ TempBufferIndicesStoredShattered += 6;
+ TempBufferVerticesStoredShattered += 3;
+ }
+}
+
+void
+CGlass::Init(void)
+{
+ for ( int32 i = 0; i < NUM_GLASSPANES; i++ )
+ aGlassPanes[i].m_bActive = false;
+
+ for ( int32 i = 0; i < NUM_GLASSTRIANGLES; i++ )
+ CentersWithTriangle[i] = (CoorsWithTriangle[i][0] + CoorsWithTriangle[i][1] + CoorsWithTriangle[i][2]) / 3;
+}
+
+void
+CGlass::Update(void)
+{
+ for ( int32 i = 0; i < NUM_GLASSPANES; i++ )
+ {
+ if ( aGlassPanes[i].m_bActive )
+ aGlassPanes[i].Update();
+ }
+}
+
+void
+CGlass::Render(void)
+{
+ TempBufferVerticesStoredHiLight = 0;
+ TempBufferIndicesStoredHiLight = 0;
+
+ TempBufferVerticesStoredShattered = TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferIndicesStoredShattered = TEMPBUFFERINDEXSHATTEREDOFFSET;
+
+ TempBufferVerticesStoredReflection = TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferIndicesStoredReflection = TEMPBUFFERINDEXREFLECTIONOFFSET;
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEFOGCOLOR, (void *)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);
+
+ PUSH_RENDERGROUP("CGlass::Render");
+
+ for ( int32 i = 0; i < NUM_GLASSPANES; i++ )
+ {
+ if ( aGlassPanes[i].m_bActive )
+ aGlassPanes[i].Render();
+ }
+
+ for ( uint32 i = 0; i < NumGlassEntities; i++ )
+ RenderEntityInGlass(apEntitiesToBeRendered[i]);
+
+ POP_RENDERGROUP();
+
+ NumGlassEntities = 0;
+
+ RenderHiLightPolys();
+ RenderShatteredPolys();
+ RenderReflectionPolys();
+
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);
+}
+
+CFallingGlassPane *
+CGlass::FindFreePane(void)
+{
+ for ( int32 i = 0; i < NUM_GLASSPANES; i++ )
+ {
+ if ( !aGlassPanes[i].m_bActive )
+ return &aGlassPanes[i];
+ }
+
+ return nil;
+}
+
+void
+CGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center,
+ float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass)
+{
+ float upLen = up.Magnitude();
+ float rightLen = right.Magnitude();
+
+ float upSteps = upLen + 0.75f;
+ if ( upSteps < 1.0f ) upSteps = 1.0f;
+
+ float rightSteps = rightLen + 0.75f;
+ if ( rightSteps < 1.0f ) rightSteps = 1.0f;
+
+ uint32 ysteps = stepmul * (uint32)upSteps;
+ if ( ysteps > 3 ) ysteps = 3;
+
+ uint32 xsteps = stepmul * (uint32)rightSteps;
+ if ( xsteps > 3 ) xsteps = 3;
+
+ if ( explosion )
+ {
+ if ( ysteps > 1 ) ysteps = 1;
+ if ( xsteps > 1 ) xsteps = 1;
+ }
+
+ float upScl = upLen / float(ysteps);
+ float rightScl = rightLen / float(xsteps);
+
+ bool bZFound;
+ float groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &bZFound);
+ if ( !bZFound ) groundZ = pos.z - 2.0f;
+
+ for ( uint32 y = 0; y < ysteps; y++ )
+ {
+ for ( uint32 x = 0; x < xsteps; x++ )
+ {
+ float stepy = float(y) * upLen / float(ysteps);
+ float stepx = float(x) * rightLen / float(xsteps);
+
+ for ( int32 i = 0; i < NUM_GLASSTRIANGLES; i++ )
+ {
+ CFallingGlassPane *pane = FindFreePane();
+ if ( pane )
+ {
+ pane->m_nTriIndex = i;
+
+ pane->GetRight() = (right * rightScl) / rightLen;
+ pane->GetUp() = (up * upScl) / upLen;
+
+ CVector fwd = CrossProduct(pane->GetRight(), pane->GetUp());
+ fwd.Normalise();
+
+ pane->GetForward() = fwd;
+
+ pane->GetPosition() = right / rightLen * (rightScl * CentersWithTriangle[i].x + stepx)
+ + up / upLen * (upScl * CentersWithTriangle[i].y + stepy)
+ + pos;
+
+ pane->m_vecMoveSpeed.x = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0015f + speed.x;
+ pane->m_vecMoveSpeed.y = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0015f + speed.y;
+ pane->m_vecMoveSpeed.z = 0.0f + speed.z;
+
+ if ( moveSpeed != 0.0f )
+ {
+ CVector dist = pane->GetPosition() - center;
+ dist.Normalise();
+
+ pane->m_vecMoveSpeed += moveSpeed * dist;
+ }
+
+ pane->m_vecTurn.x = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.002f;
+ pane->m_vecTurn.y = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.002f;
+ pane->m_vecTurn.z = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.002f;
+
+ switch ( type )
+ {
+ case 0:
+ case 2:
+ pane->m_nTimer = CTimer::GetTimeInMilliseconds();
+ break;
+ case 1:
+ float dist = (pane->GetPosition() - center).Magnitude();
+ pane->m_nTimer = uint32(dist*100 + CTimer::GetTimeInMilliseconds());
+ break;
+ }
+
+ pane->m_fGroundZ = groundZ;
+ pane->m_bShattered = cracked;
+ pane->m_fStep = upLen / float(ysteps);
+ pane->m_bCarGlass = carGlass;
+ pane->m_bActive = true;
+ }
+ }
+ }
+ }
+}
+
+void
+CGlass::AskForObjectToBeRenderedInGlass(CEntity *entity)
+{
+#ifdef FIX_BUGS
+ if ( NumGlassEntities < NUM_GLASSENTITIES )
+#else
+ if ( NumGlassEntities < NUM_GLASSENTITIES-1 )
+#endif
+ {
+ apEntitiesToBeRendered[NumGlassEntities++] = entity;
+ }
+}
+
+void
+CGlass::RenderEntityInGlass(CEntity *entity)
+{
+ ASSERT(entity!=nil);
+ CObject *object = (CObject *)entity;
+
+ if ( object->bGlassBroken )
+ return;
+
+ float distToCamera = (TheCamera.GetPosition() - object->GetPosition()).Magnitude();
+
+ if ( distToCamera > 40.0f )
+ return;
+
+ CVector fwdNorm = object->GetForward();
+ fwdNorm.Normalise();
+ uint8 alpha = CalcAlphaWithNormal(&fwdNorm);
+
+ CColModel *col = object->GetColModel();
+ ASSERT(col!=nil);
+ if ( col->numTriangles >= 2 )
+ {
+ CVector a = object->GetMatrix() * col->vertices[0].Get();
+ CVector b = object->GetMatrix() * col->vertices[1].Get();
+ CVector c = object->GetMatrix() * col->vertices[2].Get();
+ CVector d = object->GetMatrix() * col->vertices[3].Get();
+
+ if ( object->bGlassCracked )
+ {
+ uint8 color = 255;
+ if ( distToCamera > 30.0f )
+ color = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 255);
+
+ if ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-13 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-5 )
+ RenderShatteredPolys();
+
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], color, color, color, color);
+
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 0.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 0.0f);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 16.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 0.0f);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 0.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 16.0f);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], 16.0f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], 16.0f);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], a.x, a.y, a.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], b.x, b.y, b.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], c.x, c.y, c.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], d.x, d.y, d.z);
+
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 0] = col->triangles[0].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 1] = col->triangles[0].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 2] = col->triangles[0].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 3] = col->triangles[1].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 4] = col->triangles[1].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 5] = col->triangles[1].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 6] = col->triangles[0].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 7] = col->triangles[0].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 8] = col->triangles[0].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 9] = col->triangles[1].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 10] = col->triangles[1].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredShattered + 11] = col->triangles[1].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;
+
+ TempBufferIndicesStoredShattered += 12;
+ TempBufferVerticesStoredShattered += 4;
+ }
+
+ if ( TempBufferIndicesStoredReflection >= TEMPBUFFERINDEXREFLECTIONSIZE-13 || TempBufferVerticesStoredReflection >= TEMPBUFFERVERTREFLECTIONSIZE-5 )
+ RenderReflectionPolys();
+
+ uint8 color = 100;
+ if ( distToCamera > 30.0f )
+ color = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 100);
+
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], color, color, color, color);
+ RwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], color, color, color, color);
+
+ float FwdAngle = CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);
+ float v = 2.0f * TheCamera.GetForward().z * 0.2f;
+ float u = float(object->m_randomSeed & 15) * 0.02f + (FwdAngle / TWOPI);
+
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], u);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], v);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], u+0.2f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], v);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], u);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], v+0.2f);
+ RwIm3DVertexSetU (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], u+0.2f);
+ RwIm3DVertexSetV (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], v+0.2f);
+
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], a.x, a.y, a.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], b.x, b.y, b.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], c.x, c.y, c.z);
+ RwIm3DVertexSetPos (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], d.x, d.y, d.z);
+
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 0] = col->triangles[0].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 1] = col->triangles[0].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 2] = col->triangles[0].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 3] = col->triangles[1].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 4] = col->triangles[1].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 5] = col->triangles[1].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 6] = col->triangles[0].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 7] = col->triangles[0].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 8] = col->triangles[0].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 9] = col->triangles[1].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 10] = col->triangles[1].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+ TempBufferRenderIndexList[TempBufferIndicesStoredReflection + 11] = col->triangles[1].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;
+
+ TempBufferIndicesStoredReflection += 12;
+ TempBufferVerticesStoredReflection += 4;
+ }
+}
+
+int32
+CGlass::CalcAlphaWithNormal(CVector *normal)
+{
+ ASSERT(normal!=nil);
+
+ float fwdDir = 2.0f * DotProduct(*normal, TheCamera.GetForward());
+ float fwdDot = DotProduct(TheCamera.GetForward()-fwdDir*(*normal), CVector(0.57f, 0.57f, -0.57f));
+ return int32(lerp(fwdDot*fwdDot*fwdDot*fwdDot*fwdDot*fwdDot, 20.0f, 255.0f));
+}
+
+void
+CGlass::RenderHiLightPolys(void)
+{
+ if ( TempBufferVerticesStoredHiLight != TEMPBUFFERVERTHILIGHTOFFSET )
+ {
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)RwTextureGetRaster(gpShadowExplosionTex));
+
+ LittleTest();
+
+ if ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStoredHiLight, nil, rwIM3D_VERTEXUV) )
+ {
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStoredHiLight);
+ RwIm3DEnd();
+ }
+
+ TempBufferVerticesStoredHiLight = TEMPBUFFERVERTHILIGHTOFFSET;
+ TempBufferIndicesStoredHiLight = TEMPBUFFERINDEXHILIGHTOFFSET;
+ }
+}
+
+void
+CGlass::RenderShatteredPolys(void)
+{
+ if ( TempBufferVerticesStoredShattered != TEMPBUFFERVERTSHATTEREDOFFSET )
+ {
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)RwTextureGetRaster(gpCrackedGlassTex));
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ LittleTest();
+
+ if ( RwIm3DTransform(&TempBufferRenderVertices[TEMPBUFFERVERTSHATTEREDOFFSET], TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET, nil, rwIM3D_VERTEXUV) )
+ {
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, &TempBufferRenderIndexList[TEMPBUFFERINDEXSHATTEREDOFFSET], TempBufferIndicesStoredShattered - TEMPBUFFERINDEXSHATTEREDOFFSET);
+ RwIm3DEnd();
+ }
+
+ TempBufferIndicesStoredShattered = TEMPBUFFERINDEXSHATTEREDOFFSET;
+ TempBufferVerticesStoredShattered = TEMPBUFFERVERTSHATTEREDOFFSET;
+ }
+}
+
+void
+CGlass::RenderReflectionPolys(void)
+{
+ if ( TempBufferVerticesStoredReflection != TEMPBUFFERVERTREFLECTIONOFFSET )
+ {
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)RwTextureGetRaster(gpShadowHeadLightsTex));
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);
+
+ LittleTest();
+
+ if ( RwIm3DTransform(&TempBufferRenderVertices[TEMPBUFFERVERTREFLECTIONOFFSET], TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET, nil, rwIM3D_VERTEXUV) )
+ {
+ RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, &TempBufferRenderIndexList[TEMPBUFFERINDEXREFLECTIONOFFSET], TempBufferIndicesStoredReflection - TEMPBUFFERINDEXREFLECTIONOFFSET);
+ RwIm3DEnd();
+ }
+
+ TempBufferIndicesStoredReflection = TEMPBUFFERINDEXREFLECTIONOFFSET;
+ TempBufferVerticesStoredReflection = TEMPBUFFERVERTREFLECTIONOFFSET;
+ }
+}
+
+void
+CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion)
+{
+ ASSERT(entity!=nil);
+
+ CObject *object = (CObject *)entity;
+
+ if ( object->bGlassBroken )
+ return;
+
+ object->bGlassCracked = true;
+
+ CColModel *col = object->GetColModel();
+ ASSERT(col!=nil);
+
+ if ( col->numTriangles == 2 )
+ {
+ CVector a = col->vertices[0].Get();
+ CVector b = col->vertices[1].Get();
+ CVector c = col->vertices[2].Get();
+ CVector d = col->vertices[3].Get();
+
+ float minx = Min(Min(a.x, b.x), Min(c.x, d.x));
+ float maxx = Max(Max(a.x, b.x), Max(c.x, d.x));
+ float miny = Min(Min(a.y, b.y), Min(c.y, d.y));
+ float maxy = Max(Max(a.y, b.y), Max(c.y, d.y));
+ float minz = Min(Min(a.z, b.z), Min(c.z, d.z));
+ float maxz = Max(Max(a.z, b.z), Max(c.z, d.z));
+
+ CVector pa = object->GetMatrix() * CVector(minx, miny, minz);
+ CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz);
+
+ if ( amount > 300.0f )
+ {
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition());
+
+ GeneratePanesForWindow(0,
+ pa,
+ CVector(0.0f, 0.0f, maxz-minz),
+ pb - pa,
+ speed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false);
+ }
+ else
+ {
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition());
+
+ GeneratePanesForWindow(1,
+ pa,
+ CVector(0.0f, 0.0f, maxz-minz),
+ pb - pa,
+ speed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false);
+ }
+ }
+
+ object->bGlassBroken = true;
+ object->bIsVisible = false;
+ object->bUsesCollision = false;
+}
+
+void
+CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount)
+{
+ ASSERT(entity!=nil);
+
+ CObject *object = (CObject *)entity;
+
+ if ( entity->bUsesCollision && amount > 50.0f && !object->bGlassCracked )
+ {
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());
+ object->bGlassCracked = true;
+ }
+}
+
+void
+CGlass::WasGlassHitByBullet(CEntity *entity, CVector point)
+{
+ ASSERT(entity!=nil);
+
+ CObject *object = (CObject *)entity;
+
+ if ( IsGlass(object->GetModelIndex()) )
+ {
+ if ( object->bUsesCollision )
+ {
+ if ( !object->bGlassCracked )
+ {
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());
+ object->bGlassCracked = true;
+ }
+ else
+ {
+ if ( (CGeneral::GetRandomNumber() & 3) == 2 )
+ WindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false);
+ }
+ }
+ }
+}
+
+void
+CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point)
+{
+ ASSERT(entity!=nil);
+
+ CObject *object = (CObject *)entity;
+
+ if ( object->bUsesCollision )
+ {
+ CVector distToGlass = object->GetPosition() - point;
+
+ float fDistToGlass = distToGlass.Magnitude();
+
+ if ( fDistToGlass < 10.0f )
+ {
+ distToGlass *= (0.3f / fDistToGlass); // normalise
+ WindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true);
+ }
+ else
+ {
+ if ( fDistToGlass < 30.0f )
+ object->bGlassCracked = true;
+ }
+ }
+}
+
+
+void
+CGlass::CarWindscreenShatters(CVehicle *vehicle, bool unk)
+{
+ ASSERT(vehicle!=nil);
+
+ CColModel *col = vehicle->GetColModel();
+ ASSERT(col!=nil);
+
+ if ( col->numTriangles < 2 )
+ return;
+
+ CColTriangle *tria = nil;
+ int32 triIndex = -1;
+ CColTriangle *trib = nil;
+
+ for ( int32 i = 0; i < col->numTriangles; i++ )
+ {
+ CColTriangle *tri = &col->triangles[i];
+ if ( tri->surface == SURFACE_GLASS )
+ {
+ if ( tria )
+ {
+ trib = tri;
+ break;
+ }
+
+ triIndex = i;
+ tria = tri;
+ }
+ }
+
+ if ( trib == nil )
+ return;
+
+ CCollision::CalculateTrianglePlanes(col);
+
+ CColTrianglePlane *triPlanes = col->trianglePlanes;
+
+ if ( triPlanes == nil )
+ return;
+
+ CVector planeNormal;
+ triPlanes[triIndex].GetNormal(planeNormal);
+ planeNormal = Multiply3x3(vehicle->GetMatrix(), planeNormal);
+
+ CVector vec1 = CrossProduct(vehicle->GetRight(), planeNormal);
+ vec1.Normalise();
+
+ CVector vec2 = CrossProduct(planeNormal, vehicle->GetUp());
+ vec2.Normalise();
+
+ CVector v[6];
+ float proj1[6];
+ float proj2[6];
+
+ v[0] = col->vertices[tria->a].Get();
+ v[1] = col->vertices[tria->b].Get();
+ v[2] = col->vertices[tria->c].Get();
+
+ v[3] = col->vertices[trib->a].Get();
+ v[4] = col->vertices[trib->b].Get();
+ v[5] = col->vertices[trib->c].Get();
+
+ v[0] = vehicle->GetMatrix() * v[0];
+ v[1] = vehicle->GetMatrix() * v[1];
+ v[2] = vehicle->GetMatrix() * v[2];
+ v[3] = vehicle->GetMatrix() * v[3];
+ v[4] = vehicle->GetMatrix() * v[4];
+ v[5] = vehicle->GetMatrix() * v[5];
+
+ proj1[0] = DotProduct(v[0], vec1);
+ proj2[0] = DotProduct(v[0], vec2);
+ proj1[1] = DotProduct(v[1], vec1);
+ proj2[1] = DotProduct(v[1], vec2);
+ proj1[2] = DotProduct(v[2], vec1);
+ proj2[2] = DotProduct(v[2], vec2);
+
+ proj1[3] = DotProduct(v[3], vec1);
+ proj2[3] = DotProduct(v[3], vec2);
+ proj1[4] = DotProduct(v[4], vec1);
+ proj2[4] = DotProduct(v[4], vec2);
+ proj1[5] = DotProduct(v[5], vec1);
+ proj2[5] = DotProduct(v[5], vec2);
+
+ int32 originIndex = 0;
+ float max1 = proj1[0];
+ float max2 = proj2[0];
+ float origin = proj1[0] + proj2[0];
+
+ for ( int32 i = 1; i < 6; i++ )
+ {
+ float o = proj1[i] + proj2[i];
+ if ( o < origin )
+ {
+ origin = o;
+ originIndex = i;
+ }
+
+ if ( proj1[i] > max1 )
+ max1 = proj1[i];
+ if ( proj2[i] > max2 )
+ max2 = proj2[i];
+ }
+
+ float bound1 = max1 - proj1[originIndex];
+ float bound2 = max2 - proj2[originIndex];
+
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, vehicle->GetPosition());
+
+ CVector center = v[originIndex] + ((0.5f*bound1) * vec1) + ((0.5f*bound2) * vec2);
+ CVector speed = vehicle->m_vecMoveSpeed;
+ CVector right = bound2 * vec2;
+ CVector up = bound1 * vec1;
+ CVector pos = v[originIndex];
+
+ GeneratePanesForWindow(2, pos, up, right, speed, center, 0.1f, false, false, 2, true);
+}
+
+bool
+CGlass::HasGlassBeenShatteredAtCoors(float x, float y, float z)
+{
+ CEntity *entity = nil;
+ float dist = 20.0f;
+
+ int32 nStartX = Max(CWorld::GetSectorIndexX(x - 30.0f), 0);
+ int32 nStartY = Max(CWorld::GetSectorIndexY(y - 30.0f), 0);
+ int32 nEndX = Min(CWorld::GetSectorIndexX(x + 30.0f), NUMSECTORS_X-1);
+ int32 nEndY = Min(CWorld::GetSectorIndexY(y + 30.0f), NUMSECTORS_Y-1);
+
+ CWorld::AdvanceCurrentScanCode();
+
+ for ( int32 ys = nStartY; ys <= nEndY; ys++ )
+ {
+ for ( int32 xs = nStartX; xs <= nEndX; xs++ )
+ {
+ CSector *sector = CWorld::GetSector(xs, ys);
+
+ ASSERT(sector != nil);
+
+ FindWindowSectorList(sector->m_lists[ENTITYLIST_OBJECTS], &dist, &entity, x, y, z);
+ FindWindowSectorList(sector->m_lists[ENTITYLIST_DUMMIES], &dist, &entity, x, y, z);
+ }
+ }
+
+ if ( entity )
+ {
+ if ( entity->GetType() == ENTITY_TYPE_DUMMY )
+ return false;
+
+ return !!((CObject*)entity)->bGlassBroken;
+ }
+
+ return false;
+}
+
+void
+CGlass::FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z)
+{
+ ASSERT(dist!=nil);
+ ASSERT(entity!=nil);
+
+ CPtrNode *node = list.first;
+
+ while ( node != nil )
+ {
+ CEntity *ent = (CEntity *)node->item;
+ uint16 scanCode = ent->m_scanCode;
+ node = node->next;
+
+ ASSERT(ent!=nil);
+
+ if ( IsGlass(ent->GetModelIndex()) )
+ {
+ if ( scanCode != CWorld::GetCurrentScanCode() )
+ {
+ ent->m_scanCode = CWorld::GetCurrentScanCode();
+
+ float dst = (CVector(x,y,z) - ent->GetPosition()).Magnitude();
+
+ if ( dst < *dist )
+ {
+ *dist = dst;
+ *entity = ent;
+ }
+ }
+ }
+ }
+}
+
+void
+CGlass::BreakGlassPhysically(CVector pos, float radius)
+{
+ static uint32 breakTime = 0;
+
+ if ( CTimer::GetTimeInMilliseconds() < breakTime + 1000 && CTimer::GetTimeInMilliseconds() >= breakTime )
+ return;
+
+ CColSphere sphere;
+ sphere.piece = 0;
+ sphere.radius = radius;
+ sphere.surface = 0;
+
+ for ( int32 i = CPools::GetObjectPool()->GetSize() - 1; i >= 0; i-- )
+ {
+ CObject *object = CPools::GetObjectPool()->GetSlot(i);
+ if (object)
+ {
+ if ( IsGlass(object->GetModelIndex()) )
+ {
+ if ( object->bUsesCollision )
+ {
+ CColModel *col = object->GetColModel();
+ ASSERT(col!=nil);
+
+ if ( col->numTriangles < 2 )
+ continue;
+
+ bool hit = false;
+
+ CVector dist = pos - object->GetPosition();
+
+ sphere.center.x = DotProduct(dist, object->GetRight());
+ sphere.center.y = DotProduct(dist, object->GetForward());
+ sphere.center.z = DotProduct(dist, object->GetUp());
+
+ CCollision::CalculateTrianglePlanes(col);
+
+ for ( int32 j = 0; j < col->numTriangles; j++ )
+ {
+ if ( CCollision::TestSphereTriangle(sphere,
+ col->vertices, col->triangles[j], col->trianglePlanes[j]) )
+ {
+ hit = true;
+ }
+ }
+
+ if ( hit )
+ {
+ breakTime = CTimer::GetTimeInMilliseconds();
+
+ if ( object->bGlassCracked )
+ {
+ CVector a = col->vertices[0].Get();
+ CVector b = col->vertices[1].Get();
+ CVector c = col->vertices[2].Get();
+ CVector d = col->vertices[3].Get();
+
+ float minx = Min(Min(a.x, b.x), Min(c.x, d.x));
+ float maxx = Max(Max(a.x, b.x), Max(c.x, d.x));
+ float miny = Min(Min(a.y, b.y), Min(c.y, d.y));
+ float maxy = Max(Max(a.y, b.y), Max(c.y, d.y));
+ float minz = Min(Min(a.z, b.z), Min(c.z, d.z));
+ float maxz = Max(Max(a.z, b.z), Max(c.z, d.z));
+
+ CVector pa = object->GetMatrix() * CVector(minx, miny, minz);
+ CVector pb = object->GetMatrix() * CVector(maxx, maxy, minz);
+
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition());
+
+ GeneratePanesForWindow(1,
+ pa,
+ CVector(0.0f, 0.0f, maxz-minz),
+ pb - pa,
+ CVector(0.0f, 0.0f, 0.0f), pos, 0.1f, !!object->bGlassCracked, false, 1, false);
+
+ object->bGlassBroken = true;
+ object->bIsVisible = false;
+ object->bUsesCollision = false;
+ }
+ else
+ {
+ PlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());
+ object->bGlassCracked = true;
+ }
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file