You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
675 lines
19 KiB
675 lines
19 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: The Escort's Shield weapon effect |
|
// |
|
// $Workfile: $ |
|
// $Date: $ |
|
// |
|
//----------------------------------------------------------------------------- |
|
// $Log: $ |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "sheetsimulator.h" |
|
#include "edict.h" |
|
#include "collisionutils.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
#define COLLISION_PLANE_OFFSET 6.0f |
|
|
|
//----------------------------------------------------------------------------- |
|
// constructor, destructor |
|
//----------------------------------------------------------------------------- |
|
|
|
CSheetSimulator::CSheetSimulator( TraceLineFunc_t traceline, |
|
TraceHullFunc_t traceHull ) : |
|
m_pFixedPoint(0), m_ControlPoints(0), |
|
m_TraceLine(traceline), m_TraceHull(traceHull) |
|
{ |
|
} |
|
|
|
CSheetSimulator::~CSheetSimulator() |
|
{ |
|
if (m_pFixedPoint) |
|
{ |
|
delete[] m_pFixedPoint; |
|
delete[] m_ControlPoints; |
|
delete[] m_pCollisionPlanes; |
|
delete[] m_pValidCollisionPlane; |
|
} |
|
delete[] m_Particle; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Initialization |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::Init( int w, int h, int fixedPointCount ) |
|
{ |
|
m_ControlPointOffset.Init( 0, 0, 0 ); |
|
m_HorizontalCount = w; |
|
m_VerticalCount = h; |
|
m_Particle = new Particle_t[w * h]; |
|
m_FixedPointCount = fixedPointCount; |
|
if (fixedPointCount) |
|
{ |
|
m_pFixedPoint = new Vector[fixedPointCount]; |
|
m_ControlPoints = new Vector[fixedPointCount]; |
|
m_pCollisionPlanes = new cplane_t[fixedPointCount]; |
|
m_pValidCollisionPlane = new bool[fixedPointCount]; |
|
} |
|
|
|
// Initialize distances and such |
|
m_Origin = Vector(0, 0, 0); |
|
for ( int i = 0; i < NumParticles(); ++i ) |
|
{ |
|
m_Particle[i].m_Mass = 1.0f; |
|
m_Particle[i].m_Collided = false; |
|
m_Particle[i].m_Position = Vector(0,0,0); |
|
m_Particle[i].m_Velocity = Vector(0,0,0); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// adds springs |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::AddSpring( int p1, int p2, float restLength ) |
|
{ |
|
int spring = m_Springs.AddToTail(); |
|
m_Springs[spring].m_Particle1 = p1; |
|
m_Springs[spring].m_Particle2 = p2; |
|
m_Springs[spring].m_RestLength = restLength; |
|
} |
|
|
|
void CSheetSimulator::AddFixedPointSpring( int fixedPoint, int p, float restLength ) |
|
{ |
|
assert( fixedPoint < m_FixedPointCount ); |
|
int spring = m_Springs.AddToTail(); |
|
m_Springs[spring].m_Particle1 = p; |
|
m_Springs[spring].m_Particle2 = -(fixedPoint+1); |
|
m_Springs[spring].m_RestLength = restLength; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Gravity |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SetGravityConstant( float g ) |
|
{ |
|
m_GravityConstant = g; |
|
} |
|
|
|
void CSheetSimulator::AddGravityForce( int particle ) |
|
{ |
|
m_Gravity.AddToTail( particle ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// spring constants.... |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SetPointSpringConstant( float constant ) |
|
{ |
|
m_PointSpringConstant = constant; |
|
} |
|
|
|
void CSheetSimulator::SetFixedSpringConstant( float constant ) |
|
{ |
|
m_FixedSpringConstant = constant; |
|
} |
|
|
|
void CSheetSimulator::SetViscousDrag( float drag ) |
|
{ |
|
m_ViscousDrag = drag; |
|
} |
|
|
|
void CSheetSimulator::SetSpringDampConstant( float damp ) |
|
{ |
|
m_DampConstant = damp; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets the collision group |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SetCollisionGroup( int group ) |
|
{ |
|
m_CollisionGroup = group; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// bounding box for collision |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SetBoundingBox( Vector& mins, Vector& maxs ) |
|
{ |
|
m_FrustumBoxMin = mins; |
|
m_FrustumBoxMax = maxs; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// bounding box for collision |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::ComputeBounds( Vector& mins, Vector& maxs ) |
|
{ |
|
VectorCopy( m_Particle[0].m_Position, mins ); |
|
VectorCopy( m_Particle[0].m_Position, maxs ); |
|
|
|
for (int i = 1; i < NumParticles(); ++i) |
|
{ |
|
VectorMin( mins, m_Particle[i].m_Position, mins ); |
|
VectorMax( maxs, m_Particle[i].m_Position, maxs ); |
|
} |
|
mins -= m_Origin; |
|
maxs -= m_Origin; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Set the shield position |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SetPosition( const Vector& origin, const QAngle& angles ) |
|
{ |
|
// FIXME: Need a better metric for position reset |
|
if (m_Origin.DistToSqr(origin) > 1e3) |
|
{ |
|
for ( int i = 0; i < NumParticles(); ++i ) |
|
{ |
|
m_Particle[i].m_Position = origin; |
|
m_Particle[i].m_Velocity = Vector(0,0,0); |
|
} |
|
} |
|
|
|
m_Origin = origin; |
|
m_Angles = angles; |
|
ComputeControlPoints(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// get at the points |
|
//----------------------------------------------------------------------------- |
|
|
|
int CSheetSimulator::NumHorizontal() const |
|
{ |
|
return m_HorizontalCount; |
|
} |
|
|
|
int CSheetSimulator::NumVertical() const |
|
{ |
|
return m_VerticalCount; |
|
} |
|
|
|
int CSheetSimulator::PointCount() const |
|
{ |
|
return m_HorizontalCount * m_VerticalCount; |
|
} |
|
|
|
const Vector& CSheetSimulator::GetPoint( int x, int y ) const |
|
{ |
|
return m_Particle[y * NumHorizontal() + x].m_Position; |
|
} |
|
|
|
const Vector& CSheetSimulator::GetPoint( int i ) const |
|
{ |
|
return m_Particle[i].m_Position; |
|
} |
|
|
|
// Fixed points |
|
Vector& CSheetSimulator::GetFixedPoint( int i ) |
|
{ |
|
assert( i < m_FixedPointCount ); |
|
return m_pFixedPoint[i]; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// For offseting the control points |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SetControlPointOffset( const Vector& offset ) |
|
{ |
|
VectorCopy( offset, m_ControlPointOffset ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Compute the position of the fixed points |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::ComputeControlPoints() |
|
{ |
|
//trace_t tr; |
|
Vector forward, right, up; |
|
AngleVectors(m_Angles, &forward, &right, &up); |
|
|
|
for (int i = 0; i < m_FixedPointCount; ++i) |
|
{ |
|
VectorAdd( m_Origin, m_ControlPointOffset, m_ControlPoints[i] ); |
|
m_ControlPoints[i] += right * m_pFixedPoint[i].x; |
|
m_ControlPoints[i] += up * m_pFixedPoint[i].z; |
|
m_ControlPoints[i] += forward * m_pFixedPoint[i].y; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Clear forces + velocities affecting each point |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::ClearForces() |
|
{ |
|
int i; |
|
for ( i = 0; i < NumParticles(); ++i) |
|
{ |
|
m_Particle[i].m_Force = Vector(0,0,0); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Update the shield positions |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::ComputeForces() |
|
{ |
|
|
|
float springConstant; |
|
int i; |
|
for ( i = 0; i < m_Springs.Size(); ++i ) |
|
{ |
|
// Hook's law for a damped spring: |
|
// got two particles, a and b with positions xa and xb and velocities va and vb |
|
// and l = xa - xb |
|
// fa = -( ks * (|l| - r) + kd * (va - vb) dot (l) / |l|) * l/|l| |
|
|
|
Vector dx, dv, force; |
|
if (m_Springs[i].m_Particle2 < 0) |
|
{ |
|
// Case where we're connected to a control point |
|
dx = m_Particle[m_Springs[i].m_Particle1].m_Position - |
|
m_ControlPoints[- m_Springs[i].m_Particle2 - 1]; |
|
dv = m_Particle[m_Springs[i].m_Particle1].m_Velocity; |
|
|
|
springConstant = m_FixedSpringConstant; |
|
} |
|
else |
|
{ |
|
// Case where we're connected to another part of the shield |
|
dx = m_Particle[m_Springs[i].m_Particle1].m_Position - |
|
m_Particle[m_Springs[i].m_Particle2].m_Position; |
|
dv = m_Particle[m_Springs[i].m_Particle1].m_Velocity - |
|
m_Particle[m_Springs[i].m_Particle2].m_Velocity; |
|
|
|
springConstant = m_PointSpringConstant; |
|
} |
|
|
|
float length = dx.Length(); |
|
if (length < 1e-6) |
|
continue; |
|
|
|
dx /= length; |
|
|
|
float springfactor = springConstant * ( length - m_Springs[i].m_RestLength); |
|
float dampfactor = m_DampConstant * DotProduct( dv, dx ); |
|
force = dx * -( springfactor + dampfactor ); |
|
|
|
m_Particle[m_Springs[i].m_Particle1].m_Force += force; |
|
if (m_Springs[i].m_Particle2 >= 0) |
|
m_Particle[m_Springs[i].m_Particle2].m_Force -= force; |
|
|
|
assert( IsFinite( m_Particle[m_Springs[i].m_Particle1].m_Force.x ) && |
|
IsFinite( m_Particle[m_Springs[i].m_Particle1].m_Force.y) && |
|
IsFinite( m_Particle[m_Springs[i].m_Particle1].m_Force.z) ); |
|
} |
|
|
|
// gravity term |
|
for (i = 0; i < m_Gravity.Count(); ++i) |
|
{ |
|
m_Particle[m_Gravity[i]].m_Force.z -= m_Particle[m_Gravity[i]].m_Mass * m_GravityConstant; |
|
} |
|
|
|
// viscous drag term |
|
for (i = 0; i < NumParticles(); ++i) |
|
{ |
|
// Factor out bad forces for surface contact |
|
// Do this before the drag term otherwise the drag will be too large |
|
if ((m_Particle[i].m_CollisionPlane) >= 0) |
|
{ |
|
const Vector& planeNormal = m_pCollisionPlanes[m_Particle[i].m_CollisionPlane].normal; |
|
float perp = DotProduct( m_Particle[i].m_Force, planeNormal ); |
|
if (perp < 0) |
|
m_Particle[i].m_Force -= planeNormal * perp; |
|
} |
|
|
|
Vector drag = m_Particle[i].m_Velocity * m_ViscousDrag; |
|
m_Particle[i].m_Force -= drag; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Used for testing neighbors against a particular plane |
|
//----------------------------------------------------------------------------- |
|
void CSheetSimulator::TestVertAgainstPlane( int vert, int plane, bool bFarTest ) |
|
{ |
|
if (!m_pValidCollisionPlane[plane]) |
|
return; |
|
|
|
// Compute distance to the plane under consideration |
|
cplane_t* pPlane = &m_pCollisionPlanes[plane]; |
|
|
|
Ray_t ray; |
|
ray.Init( m_Origin, m_Particle[vert].m_Position ); |
|
float t = IntersectRayWithPlane( ray, *pPlane ); |
|
|
|
if (!bFarTest || (t <= 1.0f)) |
|
{ |
|
if ((t < m_Particle[vert].m_CollisionDist) && (t >= 0.0f)) |
|
{ |
|
m_Particle[vert].m_CollisionDist = t; |
|
m_Particle[vert].m_CollisionPlane = plane; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Collision detect |
|
//----------------------------------------------------------------------------- |
|
void CSheetSimulator::InitPosition( int i ) |
|
{ |
|
// Collision test... |
|
// Check a line that goes farther out than our current point... |
|
// This will let us check for resting contact |
|
trace_t tr; |
|
m_TraceHull(m_Origin, m_ControlPoints[i], m_FrustumBoxMin, m_FrustumBoxMax, |
|
MASK_SOLID_BRUSHONLY, m_CollisionGroup, &tr ); |
|
if ( tr.fraction - 1.0 < 0 ) |
|
{ |
|
memcpy( &m_pCollisionPlanes[i], &tr.plane, sizeof(cplane_t) ); |
|
m_pCollisionPlanes[i].dist += COLLISION_PLANE_OFFSET; |
|
|
|
// The trace endpos represents where the center of the box |
|
// ends up being. We actually want to choose a point which is on the |
|
// collision plane |
|
Vector delta; |
|
VectorSubtract( m_ControlPoints[i], m_Origin, delta ); |
|
int maxdist = VectorNormalize( delta ); |
|
float dist = (m_pCollisionPlanes[i].dist - DotProduct( m_Origin, m_pCollisionPlanes[i].normal )) / |
|
DotProduct( delta, m_pCollisionPlanes[i].normal ); |
|
|
|
if (dist > maxdist) |
|
dist = maxdist; |
|
|
|
VectorMA( m_Origin, dist, delta, m_Particle[i].m_Position ); |
|
|
|
m_pValidCollisionPlane[i] = true; |
|
} |
|
else if (tr.allsolid || tr.startsolid) |
|
{ |
|
m_pValidCollisionPlane[i] = true; |
|
VectorSubtract( m_Origin, m_ControlPoints[i], m_pCollisionPlanes[i].normal ); |
|
VectorNormalize( m_pCollisionPlanes[i].normal ); |
|
m_pCollisionPlanes[i].dist = DotProduct( m_Origin, m_pCollisionPlanes[i].normal ) - COLLISION_PLANE_OFFSET; |
|
m_pCollisionPlanes[i].type = 3; |
|
} |
|
else |
|
{ |
|
VectorCopy( m_ControlPoints[i], m_Particle[i].m_Position ); |
|
m_pValidCollisionPlane[i] = false; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Collision detect |
|
//----------------------------------------------------------------------------- |
|
void CSheetSimulator::DetectCollision( int i, float flPlaneOffset ) |
|
{ |
|
// Collision test... |
|
// Check a line that goes farther out than our current point... |
|
// This will let us check for resting contact |
|
// Vector endpt = m_Particle[i].m_Position; |
|
|
|
trace_t tr; |
|
m_TraceHull(m_Origin, m_ControlPoints[i], m_FrustumBoxMin, m_FrustumBoxMax, |
|
MASK_SOLID_BRUSHONLY, m_CollisionGroup, &tr ); |
|
if ( tr.fraction - 1.0 < 0 ) |
|
{ |
|
m_pValidCollisionPlane[i] = true; |
|
memcpy( &m_pCollisionPlanes[i], &tr.plane, sizeof(cplane_t) ); |
|
m_pCollisionPlanes[i].dist += flPlaneOffset; |
|
} |
|
else if (tr.allsolid || tr.startsolid) |
|
{ |
|
m_pValidCollisionPlane[i] = true; |
|
VectorSubtract( m_Origin, m_ControlPoints[i], m_pCollisionPlanes[i].normal ); |
|
VectorNormalize( m_pCollisionPlanes[i].normal ); |
|
m_pCollisionPlanes[i].dist = DotProduct( m_Origin, m_pCollisionPlanes[i].normal ) - flPlaneOffset; |
|
m_pCollisionPlanes[i].type = 3; |
|
} |
|
else |
|
{ |
|
m_pValidCollisionPlane[i] = false; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Collision plane fixup |
|
//----------------------------------------------------------------------------- |
|
void CSheetSimulator::DetermineBestCollisionPlane( bool bFarTest ) |
|
{ |
|
// Check neighbors for violation of collision plane constraints |
|
for ( int i = 0; i < NumVertical(); ++i) |
|
{ |
|
for ( int j = 0; j < NumHorizontal(); ++j) |
|
{ |
|
// Here's the particle we're making springs for |
|
int idx = i * NumHorizontal() + j; |
|
|
|
// Now that we've seen all collisions, find the best collision plane |
|
// to use (look at myself and all neighbors). The best plane |
|
// is the one that comes closest to the origin. |
|
m_Particle[idx].m_CollisionDist = FLT_MAX; |
|
m_Particle[idx].m_CollisionPlane = -1; |
|
TestVertAgainstPlane( idx, idx, bFarTest ); |
|
if (j > 0) |
|
{ |
|
TestVertAgainstPlane( idx, idx-1, bFarTest ); |
|
} |
|
if (j < NumHorizontal() - 1) |
|
{ |
|
TestVertAgainstPlane( idx, idx+1, bFarTest ); |
|
} |
|
if (i > 0) |
|
TestVertAgainstPlane( idx, idx-NumHorizontal(), bFarTest ); |
|
if (i < NumVertical() - 1) |
|
TestVertAgainstPlane( idx, idx+NumHorizontal(), bFarTest ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// satify collision constraints |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::SatisfyCollisionConstraints() |
|
{ |
|
// Eliminate velocity perp to a collision plane |
|
for ( int i = 0; i < NumParticles(); ++i ) |
|
{ |
|
// The actual collision plane |
|
if (m_Particle[i].m_CollisionPlane >= 0) |
|
{ |
|
cplane_t* pPlane = &m_pCollisionPlanes[m_Particle[i].m_CollisionPlane]; |
|
|
|
// Fix up position so it lies on the plane |
|
Vector delta = m_Particle[i].m_Position - m_Origin; |
|
m_Particle[i].m_Position = m_Origin + delta * m_Particle[i].m_CollisionDist; |
|
|
|
float perp = DotProduct( m_Particle[i].m_Velocity, pPlane->normal ); |
|
if (perp < 0) |
|
m_Particle[i].m_Velocity -= pPlane->normal * perp; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// integrator |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::EulerStep( float dt ) |
|
{ |
|
ClearForces(); |
|
ComputeForces(); |
|
|
|
// Update positions and velocities |
|
for ( int i = 0; i < NumParticles(); ++i) |
|
{ |
|
m_Particle[i].m_Position += m_Particle[i].m_Velocity * dt; |
|
m_Particle[i].m_Velocity += m_Particle[i].m_Force * dt / m_Particle[i].m_Mass; |
|
|
|
assert( IsFinite( m_Particle[i].m_Velocity.x ) && |
|
IsFinite( m_Particle[i].m_Velocity.y) && |
|
IsFinite( m_Particle[i].m_Velocity.z) ); |
|
|
|
// clamp for stability |
|
float lensq = m_Particle[i].m_Velocity.LengthSqr(); |
|
if (lensq > 1e6) |
|
{ |
|
m_Particle[i].m_Velocity *= 1e3 / sqrt(lensq); |
|
} |
|
} |
|
SatisfyCollisionConstraints(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Update the shield position: |
|
//----------------------------------------------------------------------------- |
|
|
|
void CSheetSimulator::Simulate( float dt ) |
|
{ |
|
// Initialize positions if necessary |
|
EulerStep(dt); |
|
} |
|
|
|
|
|
void CSheetSimulator::Simulate( float dt, int steps ) |
|
{ |
|
ComputeControlPoints(); |
|
|
|
// Initialize positions if necessary |
|
dt /= steps; |
|
for (int i = 0; i < steps; ++i) |
|
{ |
|
// Each step, we want to re-select the best collision planes to constrain |
|
// the movement by |
|
DetermineBestCollisionPlane(); |
|
|
|
EulerStep(dt); |
|
} |
|
} |
|
|
|
|
|
#define CLAMP_DIST 6.0 |
|
|
|
void CSheetSimulator::ClampPointsToCollisionPlanes() |
|
{ |
|
// Find collision planes to clamp to |
|
DetermineBestCollisionPlane( false ); |
|
|
|
// Eliminate velocity perp to a collision plane |
|
for ( int i = 0; i < NumParticles(); ++i ) |
|
{ |
|
// The actual collision plane |
|
if (m_Particle[i].m_CollisionPlane >= 0) |
|
{ |
|
cplane_t* pPlane = &m_pCollisionPlanes[m_Particle[i].m_CollisionPlane]; |
|
|
|
// Make sure we have a close enough perpendicular distance to the plane... |
|
float flPerpDist = fabs ( DotProduct( m_Particle[i].m_Position, pPlane->normal ) - pPlane->dist ); |
|
if (flPerpDist >= CLAMP_DIST) |
|
continue; |
|
|
|
// Drop it along the perp |
|
VectorMA( m_Particle[i].m_Position, -flPerpDist, pPlane->normal, m_Particle[i].m_Position ); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Class to help dealing with the iterative computation |
|
//----------------------------------------------------------------------------- |
|
CIterativeSheetSimulator::CIterativeSheetSimulator( TraceLineFunc_t traceline, TraceHullFunc_t traceHull ) : |
|
CSheetSimulator( traceline, traceHull ), |
|
m_SimulationSteps(0) |
|
{ |
|
} |
|
|
|
void CIterativeSheetSimulator::BeginSimulation( float dt, int steps, int substeps, int collisionCount ) |
|
{ |
|
m_CurrentCollisionPt = 0; |
|
m_TimeStep = dt; |
|
m_SimulationSteps = steps; |
|
m_TotalSteps = steps; |
|
m_SubSteps = substeps; |
|
m_InitialPass = true; |
|
m_CollisionCount = collisionCount; |
|
} |
|
|
|
bool CIterativeSheetSimulator::Think( ) |
|
{ |
|
assert( m_SimulationSteps >= 0 ); |
|
|
|
// Need to iteratively perform collision detection |
|
if (m_CurrentCollisionPt >= 0) |
|
{ |
|
DetectCollisions(); |
|
return false; |
|
} |
|
else |
|
{ |
|
// Simulate it a bunch of times |
|
Simulate(m_TimeStep, m_SubSteps); |
|
|
|
// Reset the collision point for collision detect |
|
m_CurrentCollisionPt = 0; |
|
--m_SimulationSteps; |
|
|
|
if ( m_SimulationSteps == 0 ) |
|
{ |
|
ClampPointsToCollisionPlanes(); |
|
} |
|
|
|
return true; |
|
} |
|
} |
|
|
|
// Iterative collision detection |
|
void CIterativeSheetSimulator::DetectCollisions( void ) |
|
{ |
|
for ( int i = 0; i < m_CollisionCount; ++i ) |
|
{ |
|
if (m_InitialPass) |
|
{ |
|
InitPosition( m_CurrentCollisionPt ); |
|
} |
|
else |
|
{ |
|
float flOffset = COLLISION_PLANE_OFFSET * ( (float)(m_SimulationSteps - 1) / (float)(m_TotalSteps - 1) ); |
|
DetectCollision( m_CurrentCollisionPt, flOffset ); |
|
} |
|
|
|
if (++m_CurrentCollisionPt >= NumParticles()) |
|
{ |
|
m_CurrentCollisionPt = -1; |
|
m_InitialPass = false; |
|
break; |
|
} |
|
} |
|
}
|
|
|