1896 lines
63 KiB
C++
1896 lines
63 KiB
C++
//========================================================================
|
|
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// File: IntersectManager.cpp
|
|
//
|
|
// Description: Implementation for IntersectManager class.
|
|
//
|
|
// History: Implemented --Devin [5/5/2002]
|
|
//========================================================================
|
|
|
|
//========================================
|
|
// System Includes
|
|
//========================================
|
|
#include <raddebug.hpp>
|
|
//#include <radtime.hpp>
|
|
//#include <raddebugwatch.hpp>
|
|
#include <radmath/radmath.hpp>
|
|
#include <simcollision/proximitydetection.hpp>
|
|
|
|
//========================================
|
|
// Project Includes
|
|
//========================================
|
|
#include <debug/profiler.h>
|
|
|
|
#include <render/IntersectManager/IntersectManager.h>
|
|
#include <render/RenderManager/RenderManager.h>
|
|
#include <render/Culling/SphereSP.h>
|
|
#include <render/Culling/WorldScene.h>
|
|
#include <render/DSG/IntersectDSG.h>
|
|
#include <render/DSG/StaticPhysDSG.h>
|
|
#include <render/DSG/DynaPhysDSG.h>
|
|
#include <render/DSG/FenceEntityDSG.h>
|
|
#include <render/DSG/animcollisionentitydsg.h>
|
|
#include <meta/triggervolume.h>
|
|
#include <roads/roadsegment.h>
|
|
#include <roads/geometry.h>
|
|
#include <roads/road.h>
|
|
#include <pedpaths/pathsegment.h>
|
|
#include <render/dsg/staticentitydsg.h>
|
|
|
|
#include <memory/srrmemory.h>
|
|
#include <mission/gameplaymanager.h>
|
|
#include <camera/supercammanager.h>
|
|
|
|
|
|
//************************************************************************
|
|
//
|
|
// Global Data, Local Data, Local Classes
|
|
//
|
|
//************************************************************************
|
|
//
|
|
// Static pointer to instance of this singleton.
|
|
//
|
|
IntersectManager* IntersectManager::mspInstance = NULL;
|
|
|
|
//******************************************************************************
|
|
// Public Member Functions : Instance Interface
|
|
//******************************************************************************
|
|
//==============================================================================
|
|
// IntersectManager::CreateInstance
|
|
//==============================================================================
|
|
//
|
|
// Description: Create the IntersectManager controller if needed.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: Pointer to the created IntersectManager controller.
|
|
//
|
|
// Constraints: This is a singleton so only one instance is allowed.
|
|
//
|
|
//==============================================================================
|
|
IntersectManager* IntersectManager::CreateInstance()
|
|
{
|
|
MEMTRACK_PUSH_GROUP( "IntersectManager" );
|
|
rAssert( mspInstance == NULL );
|
|
mspInstance = new(GMA_PERSISTENT) IntersectManager();
|
|
MEMTRACK_POP_GROUP( "IntersectManager" );
|
|
|
|
return mspInstance;
|
|
}
|
|
|
|
//==============================================================================
|
|
// IntersectManager::GetInstance
|
|
//==============================================================================
|
|
//
|
|
// Description: Get the IntersectManager controller if exists.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: Pointer to the created IntersectManager controller.
|
|
//
|
|
// Constraints: This is a singleton so only one instance is allowed.
|
|
//
|
|
//==============================================================================
|
|
IntersectManager* IntersectManager::GetInstance()
|
|
{
|
|
rAssert( mspInstance != NULL );
|
|
|
|
return mspInstance;
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
// IntersectManager::DestroyInstance
|
|
//==============================================================================
|
|
//
|
|
// Description: Destroy the IntersectManager controller.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
//==============================================================================
|
|
void IntersectManager::DestroyInstance()
|
|
{
|
|
//
|
|
// Make sure this doesn't get called twice.
|
|
//
|
|
rAssert( mspInstance != NULL );
|
|
delete mspInstance;
|
|
mspInstance = NULL;
|
|
}
|
|
|
|
//************************************************************************
|
|
// Public Member Functions : IntersectManager "Meat" Interface
|
|
//************************************************************************
|
|
|
|
bool IntersectManager::IntersectWithPlane( rmt::Vector planeOrigin,
|
|
rmt::Vector planeNormal,
|
|
rmt::Vector rayOrigin,
|
|
rmt::Vector rayVector,
|
|
float& time )
|
|
{
|
|
float numer, denom;
|
|
|
|
denom = rayVector.Dot( planeNormal );
|
|
|
|
if( rmt::Fabs( denom ) <= 0.0001f)
|
|
{
|
|
return( false );
|
|
}
|
|
|
|
numer = planeNormal.Dot( rayOrigin ) - planeNormal.Dot( planeOrigin );
|
|
|
|
time = -numer / denom;
|
|
|
|
return( true );
|
|
}
|
|
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::ResetCache( const rmt::Vector& irPosn, float iRadius )
|
|
{
|
|
mCachedPosn = irPosn;
|
|
mCachedRadius = iRadius;
|
|
mbSameFrame = true;
|
|
}
|
|
#define SPHERE_TEST
|
|
//#define VIEW_FRUSTUM_TEST
|
|
|
|
//========================================================================
|
|
// intersectmanager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindClosestRoad
|
|
(
|
|
const rmt::Vector& irPosn,
|
|
float iRadius,
|
|
RoadSegment*& orpRoad,
|
|
float& oDistSqr
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindClosestRoad")
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
rmt::Sphere segmentSphere;
|
|
|
|
orpRoad = NULL;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
|
|
unsigned int itCount = 0;
|
|
|
|
oDistSqr = 100000.0f;
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mRoadSegmentElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
RoadSegment* segment = pTreeIter->rCurrent().mRoadSegmentElems[i];
|
|
|
|
if( segment->GetRoad()->GetShortCut() )
|
|
continue;
|
|
|
|
itCount++;
|
|
|
|
segment->GetBoundingSphere( &segmentSphere );
|
|
|
|
rmt::Vector vec0, vec1, vec2, vec3;
|
|
rmt::Vector start, end;
|
|
segment->GetCorner( 0, vec0 );
|
|
segment->GetCorner( 1, vec1 );
|
|
segment->GetCorner( 2, vec2 );
|
|
segment->GetCorner( 3, vec3 );
|
|
|
|
start = ( vec0 + vec3 ) * 0.5f;
|
|
end = ( vec1 + vec2 ) * 0.5f;
|
|
|
|
rmt::Vector closestPtOnSeg;
|
|
FindClosestPointOnLine( start, end, irPosn, closestPtOnSeg );
|
|
|
|
float distSqr = ( closestPtOnSeg - irPosn ).MagnitudeSqr();
|
|
if( distSqr < oDistSqr )
|
|
{
|
|
orpRoad = segment;
|
|
oDistSqr = distSqr;
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindClosestRoad")
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void IntersectManager::FindClosestAnyRoad
|
|
(
|
|
const rmt::Vector& irPosn,
|
|
float iRadius,
|
|
RoadSegment*& orpRoad,
|
|
float& oDistSqr
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindClosestAnyRoad")
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
rmt::Sphere segmentSphere;
|
|
|
|
orpRoad = NULL;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
|
|
unsigned int itCount = 0;
|
|
|
|
oDistSqr = 100000.0f;
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mRoadSegmentElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
RoadSegment* segment = pTreeIter->rCurrent().mRoadSegmentElems[i];
|
|
|
|
itCount++;
|
|
|
|
segment->GetBoundingSphere( &segmentSphere );
|
|
|
|
rmt::Vector vec0, vec1, vec2, vec3;
|
|
rmt::Vector start, end;
|
|
segment->GetCorner( 0, vec0 );
|
|
segment->GetCorner( 1, vec1 );
|
|
segment->GetCorner( 2, vec2 );
|
|
segment->GetCorner( 3, vec3 );
|
|
|
|
start = ( vec0 + vec3 ) * 0.5f;
|
|
end = ( vec1 + vec2 ) * 0.5f;
|
|
|
|
rmt::Vector closestPtOnSeg;
|
|
FindClosestPointOnLine( start, end, irPosn, closestPtOnSeg );
|
|
|
|
float distSqr = ( closestPtOnSeg - irPosn ).MagnitudeSqr();
|
|
if( distSqr < oDistSqr )
|
|
{
|
|
orpRoad = segment;
|
|
oDistSqr = distSqr;
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindClosestAnyRoad")
|
|
}
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindFenceElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<FenceEntityDSG*>& orList
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindFenceElems")
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
// rmt::Sphere tempSphere;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msStaticPhys );
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
// pTreeIter->SetIterFilter( WorldScene::msStaticPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mFenceElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
#ifdef SPHERE_TEST
|
|
//pTreeIter->rCurrent().mFenceElems[i]->GetBoundingSphere(&tempSphere);
|
|
rmt::Vector pt1 = pTreeIter->rCurrent().mFenceElems[i]->mStartPoint;
|
|
rmt::Vector pt2 = pTreeIter->rCurrent().mFenceElems[i]->mEndPoint;
|
|
|
|
rmt::Vector center = pt1;
|
|
center.Add( pt2 );
|
|
center.Scale(0.5f);
|
|
|
|
pt1.y = 0.0f;
|
|
pt2.y = 0.0f;
|
|
center.y = 0.0f;
|
|
|
|
pt1.Sub(center,pt2);
|
|
|
|
float circleRadiusSqr = pt1.MagnitudeSqr();
|
|
|
|
float maxDistSqr = (iRadius*iRadius)+circleRadiusSqr;//* (iRadius+circleRadius);
|
|
|
|
//tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
center.y = irPosn.y;
|
|
center.Sub(irPosn);
|
|
|
|
if( center.MagnitudeSqr() < maxDistSqr )
|
|
#endif
|
|
{
|
|
orList.Add( pTreeIter->rCurrent().mFenceElems[i] );
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindFenceElems")
|
|
}
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindStaticPhysElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<StaticPhysDSG*>& orList
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindStaticPhysElems")
|
|
//SpatialNode<StaticEntityDSG,StaticPhysDSG,IntersectDSG>& rCurrentLeaf =
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
int i,j;
|
|
rmt::Sphere tempSphere;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
//BEGIN_PROFILE( "AndTree" );
|
|
//pTreeIter->AndTree( ~WorldScene::msStaticPhys );
|
|
//END_PROFILE( "AndTree" );
|
|
// BEGIN_PROFILE( "MarkAll" );
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
// END_PROFILE( "MarkAll" );
|
|
//pTreeIter->SetIterFilter( WorldScene::msStaticPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
//BEGIN_PROFILE( "Iter" );
|
|
//for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
//{
|
|
// for( i=pTreeIter->rCurrent().mSPhysElems.mUseSize-1; i>-1; i-- )
|
|
// {
|
|
// pTreeIter->rCurrent().mSPhysElems[i]->GetBoundingSphere(&tempSphere);
|
|
//
|
|
// maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
//
|
|
// tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
//
|
|
// if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
// {
|
|
// orList.Add( pTreeIter->rCurrent().mSPhysElems[i] );
|
|
// }
|
|
// }
|
|
//}
|
|
//END_PROFILE( "Iter" );
|
|
j= pTreeIter->mCurNodes.mUseSize-1;
|
|
if(j>100)
|
|
{
|
|
rReleasePrintf("\n\nWTF? %d nodes \n\n", j);
|
|
}
|
|
|
|
// BEGIN_PROFILE( "Quack" );
|
|
for(j=pTreeIter->mCurNodes.mUseSize-1; j>-1; j--)
|
|
{
|
|
for( i=pTreeIter->mCurNodes[j]->mSPhysElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
#ifdef SPHERE_TEST
|
|
pTreeIter->mCurNodes[j]->mSPhysElems[i]->GetBoundingSphere(&tempSphere);
|
|
|
|
float maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
|
|
tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
|
|
if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
#endif
|
|
{
|
|
orList.Add( pTreeIter->mCurNodes[j]->mSPhysElems[i] );
|
|
}
|
|
}
|
|
}
|
|
// END_PROFILE( "Quack" );
|
|
END_PROFILE("::FindStaticPhysElems")
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindStaticElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<StaticEntityDSG*>& orList
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindStaticElems")
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
int i,j;
|
|
rmt::Sphere tempSphere;
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
orList.Allocate(200);
|
|
|
|
//BEGIN_PROFILE( "Iter" );
|
|
//for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
//{
|
|
// for( i=pTreeIter->rCurrent().mSPhysElems.mUseSize-1; i>-1; i-- )
|
|
// {
|
|
// pTreeIter->rCurrent().mSPhysElems[i]->GetBoundingSphere(&tempSphere);
|
|
//
|
|
// maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
//
|
|
// tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
//
|
|
// if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
// {
|
|
// orList.Add( pTreeIter->rCurrent().mSPhysElems[i] );
|
|
// }
|
|
// }
|
|
//}
|
|
//END_PROFILE( "Iter" );
|
|
j= pTreeIter->mCurNodes.mUseSize-1;
|
|
if(j>100)
|
|
{
|
|
rReleasePrintf("\n\nWTF? %d nodes \n\n", j);
|
|
}
|
|
|
|
// BEGIN_PROFILE( "Quack" );
|
|
for(j=pTreeIter->mCurNodes.mUseSize-1; j>-1; j--)
|
|
{
|
|
for( i=pTreeIter->mCurNodes[j]->mSEntityElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
#ifdef SPHERE_TEST
|
|
pTreeIter->mCurNodes[j]->mSEntityElems[i]->GetBoundingSphere(&tempSphere);
|
|
|
|
float maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
|
|
tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
|
|
if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
#endif
|
|
{
|
|
orList.Add( pTreeIter->mCurNodes[j]->mSEntityElems[i] );
|
|
}
|
|
}
|
|
}
|
|
// END_PROFILE( "Quack" );
|
|
END_PROFILE("::FindStaticElems")
|
|
}
|
|
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindDynaPhysElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<DynaPhysDSG*>& orList
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindDynaPhysElems")
|
|
//SpatialNode<StaticEntityDSG,StaticPhysDSG,IntersectDSG>& rCurrentLeaf =
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
rmt::Sphere tempSphere;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mDPhysElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
#ifdef SPHERE_TEST
|
|
pTreeIter->rCurrent().mDPhysElems[i]->GetBoundingSphere(&tempSphere);
|
|
|
|
float maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
|
|
tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
|
|
if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
#endif
|
|
{
|
|
orList.Add( pTreeIter->rCurrent().mDPhysElems[i] );
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindDynaPhysElems")
|
|
}
|
|
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindAnimPhysElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<AnimCollisionEntityDSG*>& orList
|
|
)
|
|
{
|
|
#ifndef RAD_RELEASE
|
|
char temp[100];
|
|
sprintf(temp, "::FindAnimPhysElems %f", iRadius);
|
|
#endif
|
|
BEGIN_PROFILE("::FindAnimPhysElems")
|
|
//SpatialNode<StaticEntityDSG,StaticPhysDSG,IntersectDSG>& rCurrentLeaf =
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
rmt::Sphere tempSphere;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mAnimCollElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
bool addToList = false;
|
|
|
|
#ifdef VIEW_FRUSTUM_TEST
|
|
// Test the object and see if it is within any of the view frustums
|
|
pTreeIter->rCurrent().mAnimCollElems[i]->GetBoundingSphere(&tempSphere);
|
|
|
|
int numPlayers = GetGameplayManager()->GetNumPlayers();
|
|
for ( int player = 0 ; player < numPlayers ; player++)
|
|
{
|
|
if (GetSuperCamManager()->GetSCC( player )->GetCamera()->SphereVisible( tempSphere.centre, tempSphere.radius ) )
|
|
{
|
|
addToList = true;
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
#ifdef SPHERE_TEST
|
|
// Use the sphere test if the view frustum test is not enabled
|
|
pTreeIter->rCurrent().mAnimCollElems[i]->GetBoundingSphere(&tempSphere);
|
|
|
|
float maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
|
|
tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
|
|
if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
{
|
|
addToList = true;
|
|
}
|
|
#else
|
|
// Neither test is activated, always add it to the list
|
|
addToList = true;
|
|
#endif
|
|
|
|
#endif
|
|
if ( addToList )
|
|
{
|
|
orList.Add( pTreeIter->rCurrent().mAnimCollElems[i] );
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindAnimPhysElems")
|
|
}
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindTrigVolElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<TriggerVolume*>& orList
|
|
)
|
|
{
|
|
#ifndef RAD_RELEASE
|
|
char temp[100];
|
|
sprintf(temp, "::FindTrigVolElems %f", iRadius);
|
|
#endif
|
|
BEGIN_PROFILE(temp)
|
|
//SpatialNode<StaticEntityDSG,StaticPhysDSG,IntersectDSG>& rCurrentLeaf =
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
|
|
rmt::Sphere tempSphere;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mTrigVolElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
#ifdef SPHERE_TEST
|
|
pTreeIter->rCurrent().mTrigVolElems[i]->GetBoundingSphere(&tempSphere);
|
|
|
|
float maxDistSqr = (iRadius+tempSphere.radius) * (iRadius+tempSphere.radius);
|
|
|
|
tempSphere.centre.Sub(tempSphere.centre,irPosn);
|
|
|
|
if( tempSphere.centre.MagnitudeSqr() < maxDistSqr )
|
|
#endif
|
|
{
|
|
orList.Add( pTreeIter->rCurrent().mTrigVolElems[i] );
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE(temp)
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindRoadSegmentElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<RoadSegment*>& orList
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindRoadSegmentElems")
|
|
//SpatialNode<StaticEntityDSG,StaticPhysDSG,IntersectDSG>& rCurrentLeaf =
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
rmt::Sphere segmentSphere;
|
|
//rmt::Vector segmentPos;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
unsigned int itCount = 0;
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mRoadSegmentElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
RoadSegment* segment = pTreeIter->rCurrent().mRoadSegmentElems[i];
|
|
#ifdef SPHERE_TEST
|
|
itCount++;
|
|
|
|
segment->GetBoundingSphere( &segmentSphere );
|
|
//segment->GetPosition( &segmentPos );
|
|
|
|
float halfrad = segmentSphere.radius;// / 2.0f;
|
|
float maxDistSqr = (iRadius+halfrad) * (iRadius+halfrad);
|
|
float minDistSqr;
|
|
if( halfrad > iRadius )
|
|
{
|
|
minDistSqr = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
minDistSqr = (iRadius-halfrad) * (iRadius-halfrad);
|
|
}
|
|
|
|
rmt::Vector temp;
|
|
//temp.Sub(segmentPos,irPosn);
|
|
temp.Sub( segmentSphere.centre, irPosn );
|
|
|
|
if( temp.MagnitudeSqr() < maxDistSqr &&
|
|
temp.MagnitudeSqr() > minDistSqr)
|
|
#endif
|
|
{
|
|
orList.Add( segment );
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindRoadSegmentElems")
|
|
}
|
|
|
|
//========================================================================
|
|
// IntersectManager::
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
void IntersectManager::FindPathSegmentElems
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
ReserveArray<PathSegment*>& orList
|
|
)
|
|
{
|
|
BEGIN_PROFILE("::FindPathSegmentElems")
|
|
//SpatialNode<StaticEntityDSG,StaticPhysDSG,IntersectDSG>& rCurrentLeaf =
|
|
SphereSP desiredVol;
|
|
desiredVol.SetTo(irPosn,iRadius);
|
|
|
|
|
|
rmt::Sphere segmentSphere;
|
|
//rmt::Vector segmentPos;
|
|
|
|
SpatialTreeIter* pTreeIter = &(GetRenderManager()->pWorldScene()->mStaticTreeWalker);
|
|
// pTreeIter->OrTree( WorldScene::msStaticPhys );
|
|
// pTreeIter->AndTree( ~WorldScene::msDynaPhys );
|
|
if( !mbSameFrame ||
|
|
(mCachedPosn != irPosn) ||
|
|
(mCachedRadius != iRadius) )
|
|
{
|
|
ResetCache( irPosn, iRadius );
|
|
pTreeIter->MarkAll( desiredVol, WorldScene::msStaticPhys );
|
|
}
|
|
// pTreeIter->SetIterFilter( WorldScene::msDynaPhys );
|
|
|
|
orList.Allocate(200);
|
|
|
|
unsigned int itCount = 0;
|
|
|
|
for(pTreeIter->MoveToFirst(); pTreeIter->NotDone(); pTreeIter->MoveToNext())
|
|
{
|
|
for( int i=pTreeIter->rCurrent().mPathSegmentElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
PathSegment* segment = pTreeIter->rCurrent().mPathSegmentElems[i];
|
|
#ifdef SPHERE_TEST
|
|
itCount++;
|
|
|
|
segment->GetBoundingSphere( &segmentSphere );
|
|
//segment->GetPosition( &segmentPos );
|
|
|
|
float halfrad = segmentSphere.radius;// / 2.0f;
|
|
float maxDistSqr = (iRadius+halfrad) * (iRadius+halfrad);
|
|
float minDistSqr;
|
|
if( halfrad > iRadius )
|
|
{
|
|
minDistSqr = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
minDistSqr = (iRadius-halfrad) * (iRadius-halfrad);
|
|
}
|
|
|
|
rmt::Vector temp;
|
|
//temp.Sub(segmentPos,irPosn);
|
|
temp.Sub( segmentSphere.centre, irPosn );
|
|
|
|
if( temp.MagnitudeSqr() < maxDistSqr &&
|
|
temp.MagnitudeSqr() > minDistSqr)
|
|
#endif
|
|
{
|
|
orList.Add( segment );
|
|
}
|
|
}
|
|
}
|
|
END_PROFILE("::FindPathSegmentElems")
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#ifndef RAD_RELEASE
|
|
IntersectDSG* IntersectManager::FindIntersectionTri
|
|
(
|
|
rmt::Vector& irPosn,
|
|
rmt::Vector* opTriPoints,
|
|
rmt::Vector& orIntersectPosn,
|
|
rmt::Vector& orIntersectNorm
|
|
)
|
|
{
|
|
SpatialNode& rCurrentLeaf = GetRenderManager()->pWorldScene()->mStaticTreeWalker.rSeekLeaf((Vector3f&)irPosn);
|
|
|
|
rmt::Vector tmpVect, tmpVect2, TriPts[3], TriNorm;//, TriCtr;
|
|
float DistToPlane, ClosestDistToPlane = 20000.0f;//TriRadius,
|
|
int foundTerrainType;
|
|
|
|
// iRadius *= 2.5f;
|
|
//MS7 Default, in case we don't find an intersection
|
|
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mTri(j,TriPts,TriNorm );//TriCtr,
|
|
// This first test finds the ground plane directly beneath the sphere (on the y axis)
|
|
|
|
// make tmpVect a vector from the sphere position towards the ground
|
|
tmpVect2.Set( 0.0f, -1.0f, 0.0f );
|
|
|
|
//if(( !obFoundPlane ) && ( tmpVect2.Dot( TriNorm ) < 0 ))
|
|
{
|
|
tmpVect.Set( irPosn.x, 10000.0f, irPosn.z );
|
|
|
|
if( IntersectWithPlane( TriPts[ 0 ], TriNorm, tmpVect, tmpVect2, DistToPlane ) )
|
|
{
|
|
if(( DistToPlane >= 0.0f ) /*&& ( DistToPlane <= iRadius )*/)
|
|
{
|
|
rmt::Vector pointOnPlane = tmpVect2;
|
|
pointOnPlane.Scale( DistToPlane );
|
|
|
|
pointOnPlane.Add( tmpVect );
|
|
// pointOnPlane.Add( irPosn );
|
|
|
|
tmpVect.Sub(TriPts[0],TriPts[1]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[1]);
|
|
if( tmpVect.Dot(tmpVect2) >= -0.00f )
|
|
{
|
|
tmpVect.Sub(TriPts[1],TriPts[2]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[2]);
|
|
if( tmpVect.Dot(tmpVect2) >= -0.00f )
|
|
{
|
|
tmpVect.Sub(TriPts[2],TriPts[0]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[0]);
|
|
if( tmpVect.Dot(tmpVect2) >= -0.00f )
|
|
{
|
|
opTriPoints[0] = TriPts[0];
|
|
opTriPoints[1] = TriPts[1];
|
|
opTriPoints[2] = TriPts[2];
|
|
orIntersectPosn = pointOnPlane;
|
|
orIntersectNorm = TriNorm;
|
|
|
|
return rCurrentLeaf.mIntersectElems[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
IntersectDSG* IntersectManager::FindIntersectionTriNew
|
|
(
|
|
rmt::Vector& irPosn,
|
|
rmt::Vector* opTriPoints,
|
|
rmt::Vector& orIntersectPosn,
|
|
rmt::Vector& orIntersectNorm
|
|
)
|
|
{
|
|
SpatialNode& rCurrentLeaf = GetRenderManager()->pWorldScene()->mStaticTreeWalker.rSeekLeaf((Vector3f&)irPosn);
|
|
|
|
rmt::Vector tmpVect, tmpVect2, TriPts[3], TriNorm;//, TriCtr;
|
|
float DistToPlane, ClosestDistToPlane = 20000.0f;//TriRadius,
|
|
int foundTerrainType;
|
|
|
|
// iRadius *= 2.5f;
|
|
//MS7 Default, in case we don't find an intersection
|
|
|
|
#if defined(RAD_PS2) && !defined(RAD_MW)
|
|
radTime64 time = radTimeGetMicroseconds64();
|
|
static rmt::Vector4 alignedVertices[3] __attribute__((aligned(16))); //vf1,vf2,vf3
|
|
static rmt::Vector4 alignedNormal __attribute__((aligned(16))); //vf4
|
|
|
|
static rmt::Vector4 alignedRayOrigin __attribute__((aligned(16))); //vf5
|
|
|
|
static rmt::Vector4 alignedPointOnPlane __attribute__((aligned(16))); //vf7
|
|
static rmt::Vector4 alignedDistFromPlane __attribute__((aligned(16)));//vf8
|
|
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
rCurrentLeaf.mIntersectElems[i]->IntoTheVoid_WithGoFastaStripes();
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
/*
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mTri(j,alignedVertices,alignedNormal);//TriCtr,
|
|
|
|
alignedRayVector.Set( 0.0f, -1.0f, 0.0f );
|
|
alignedRayOrigin.Set( irPosn.x, 10000.0f, irPosn.z );
|
|
|
|
if( IntersectWithPlane( alignedVertices[0], alignedNormal, alignedRayOrigin, alignedRayVector, alignedDistFromPlane.x) )
|
|
{
|
|
*/
|
|
TriPts[0] = irPosn;
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mFlatTriFast(j,TriPts,TriNorm );//TriCtr,
|
|
if(foundTerrainType==-1) continue;
|
|
alignedVertices[0] = TriPts[0];
|
|
alignedVertices[1] = TriPts[1];
|
|
alignedVertices[2] = TriPts[2];
|
|
alignedNormal = TriNorm;
|
|
|
|
TriPts[2].Set( 0.0f, -1.0f, 0.0f );
|
|
TriPts[1].Set( irPosn.x, 10000.0f, irPosn.z );
|
|
if( IntersectWithPlane( TriPts[ 0 ], TriNorm, TriPts[1], TriPts[2], DistToPlane ) )
|
|
{
|
|
if( DistToPlane >= 0.0f )//alignedDistFromPlane.x >= 0.0f )
|
|
{
|
|
alignedDistFromPlane.Set( DistToPlane, DistToPlane, DistToPlane, 1.0f );
|
|
//alignedDistFromPlane.y = alignedDistFromPlane.x;
|
|
//alignedDistFromPlane.z = alignedDistFromPlane.x;
|
|
|
|
alignedPointOnPlane = TriPts[2];
|
|
alignedRayOrigin = TriPts[1];
|
|
|
|
asm __volatile__("
|
|
lqc2 vf7, 0(%5) # load pointOnPlane
|
|
lqc2 vf8, 0(%6) # load distFromPlane
|
|
lqc2 vf5, 0(%4) # load rayOrigin
|
|
vmul.xyz vf7, vf7, vf8 # pointOnPlane.Scale( DistToPlane );
|
|
lqc2 vf1, 0(%0) # load vertex0
|
|
lqc2 vf2, 0(%1) # load vertex1
|
|
vadd.xyz vf7, vf7, vf5 # pointOnPlane.Add( tmpVect ); tempVect == alignedRayOrigin, tempVect2 == alignedRayVector
|
|
lqc2 vf4, 0(%3) # load normal
|
|
vsub.xyz vf9, vf1, vf2 # tmpVect.Sub(TriPts[0],TriPts[1]);
|
|
lqc2 vf3, 0(%2) # load vertex2
|
|
vopmula.xyz ACC, vf9, vf4 # outer product stage 1 tmpVect.CrossProduct(TriNorm);
|
|
vopmsub.xyz vf9, vf4, vf9 # outer product stage 2
|
|
vsub.xyz vf10,vf7, vf2 # tmpVect2.Sub(pointOnPlane,TriPts[1]);
|
|
vmul.xyz vf20,vf10, vf9 # ==if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
sqc2 vf20, 0(%0) # store result in vertex 0
|
|
vsub.xyz vf9, vf2, vf3 # tmpVect.Sub(TriPts[1],TriPts[2]);
|
|
vopmula.xyz ACC, vf9, vf4 # outer product stage 1 tmpVect.CrossProduct(TriNorm);
|
|
vopmsub.xyz vf9, vf4, vf9 # outer product stage 2
|
|
vsub.xyz vf10,vf7, vf3 # tmpVect2.Sub(pointOnPlane,TriPts[2]);
|
|
vmul.xyz vf21,vf10, vf9 # ==if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
sqc2 vf21, 0(%1) # store result in vertex 1
|
|
vsub.xyz vf9, vf3, vf1 # tmpVect.Sub(TriPts[2],TriPts[0]);
|
|
vopmula.xyz ACC, vf9, vf4 # outer product stage 1 tmpVect.CrossProduct(TriNorm);
|
|
vopmsub.xyz vf9, vf4, vf9 # outer product stage 2
|
|
vsub.xyz vf10,vf7, vf1 # tmpVect2.Sub(pointOnPlane,TriPts[0]);
|
|
vmul.xyz vf22,vf10, vf9 # ==if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
sqc2 vf22, 0(%2) # store result in vertex 2
|
|
sqc2 vf7, 0(%5) # store result in vertex 2
|
|
": // no outputs
|
|
: "r" (&(alignedVertices[0])),
|
|
"r" (&(alignedVertices[1])),
|
|
"r" (&(alignedVertices[2])),
|
|
"r" (&alignedNormal),
|
|
"r" (&alignedRayOrigin),
|
|
"r" (&alignedPointOnPlane),
|
|
"r" (&alignedDistFromPlane)
|
|
: "memory" );
|
|
|
|
if( ((alignedVertices[0].x+alignedVertices[0].y+alignedVertices[0].z) >= 0.00f)
|
|
&& ((alignedVertices[1].x+alignedVertices[1].y+alignedVertices[1].z) >= 0.00f)
|
|
&& ((alignedVertices[2].x+alignedVertices[2].y+alignedVertices[2].z) >= 0.00f)
|
|
)
|
|
{
|
|
orIntersectNorm = alignedNormal;
|
|
orIntersectPosn = alignedPointOnPlane;
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
|
|
//time = radTimeGetMicroseconds64()-time;
|
|
//rReleasePrintf("vu0 found t=%d \t-=- ",(int)time);
|
|
|
|
return rCurrentLeaf.mIntersectElems[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
}
|
|
|
|
//time = radTimeGetMicroseconds64()-time;
|
|
//rReleasePrintf("vu0 miss t=%d \t-=- ",(int)time);
|
|
return NULL;
|
|
|
|
#else
|
|
// time = radTimeGetMicroseconds64();
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
rCurrentLeaf.mIntersectElems[i]->IntoTheVoid_WithGoFastaStripes();
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mTri(j,TriPts,TriNorm );//TriCtr,
|
|
// This first test finds the ground plane directly beneath the sphere (on the y axis)
|
|
|
|
// make tmpVect a vector from the sphere position towards the ground
|
|
tmpVect2.Set( 0.0f, -1.0f, 0.0f );
|
|
|
|
//if(( !obFoundPlane ) && ( tmpVect2.Dot( TriNorm ) < 0 ))
|
|
{
|
|
tmpVect.Set( irPosn.x, 10000.0f, irPosn.z );
|
|
|
|
if( IntersectWithPlane( TriPts[ 0 ], TriNorm, tmpVect, tmpVect2, DistToPlane ) )
|
|
{
|
|
if(( DistToPlane >= 0.0f ) )
|
|
{
|
|
rmt::Vector pointOnPlane = tmpVect2;
|
|
pointOnPlane.Scale( DistToPlane );
|
|
|
|
pointOnPlane.Add( tmpVect );
|
|
|
|
tmpVect.Sub(TriPts[0],TriPts[1]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[1]);
|
|
if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
{
|
|
tmpVect.Sub(TriPts[1],TriPts[2]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[2]);
|
|
if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
{
|
|
tmpVect.Sub(TriPts[2],TriPts[0]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[0]);
|
|
if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
{
|
|
orIntersectNorm = TriNorm;
|
|
orIntersectPosn = pointOnPlane;
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
|
|
//time = radTimeGetMicroseconds64()-time;
|
|
//rReleasePrintf("normal found t=%d\n",(int)time);
|
|
|
|
return rCurrentLeaf.mIntersectElems[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
}
|
|
|
|
return NULL;
|
|
#endif
|
|
}
|
|
//#endif
|
|
|
|
#if 1
|
|
//========================================================================
|
|
// IntersectManager::FindIntersection
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
int IntersectManager::FindIntersection
|
|
(
|
|
rmt::Vector& irPosn,
|
|
bool& obFoundPlane,
|
|
rmt::Vector& orGroundPlaneNorm,
|
|
rmt::Vector& orGroundPlanePosn
|
|
)
|
|
{
|
|
SpatialNode& rCurrentLeaf = GetRenderManager()->pWorldScene()->mStaticTreeWalker.rSeekLeaf((Vector3f&)irPosn);
|
|
|
|
rmt::Vector tmpVect, tmpVect2, TriPts[3], TriNorm;//, TriCtr;
|
|
float DistToPlane, ClosestDistToPlane = 20000.0f;//TriRadius,
|
|
int foundTerrainType;
|
|
|
|
// iRadius *= 2.5f;
|
|
//MS7 Default, in case we don't find an intersection
|
|
obFoundPlane = false;
|
|
|
|
#if defined(RAD_PS2) && !defined(RAD_MW)
|
|
//radTime64 time = radTimeGetMicroseconds64();
|
|
static rmt::Vector4 alignedVertices[3] __attribute__((aligned(16))); //vf1,vf2,vf3
|
|
static rmt::Vector4 alignedNormal __attribute__((aligned(16))); //vf4
|
|
|
|
static rmt::Vector4 alignedRayOrigin __attribute__((aligned(16))); //vf5
|
|
|
|
static rmt::Vector4 alignedPointOnPlane __attribute__((aligned(16))); //vf7
|
|
static rmt::Vector4 alignedDistFromPlane __attribute__((aligned(16)));//vf8
|
|
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
rCurrentLeaf.mIntersectElems[i]->IntoTheVoid_WithGoFastaStripes();
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
/*
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mTri(j,alignedVertices,alignedNormal);//TriCtr,
|
|
|
|
alignedRayVector.Set( 0.0f, -1.0f, 0.0f );
|
|
alignedRayOrigin.Set( irPosn.x, 10000.0f, irPosn.z );
|
|
|
|
if( IntersectWithPlane( alignedVertices[0], alignedNormal, alignedRayOrigin, alignedRayVector, alignedDistFromPlane.x) )
|
|
{
|
|
*/
|
|
TriPts[0] = irPosn;
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mFlatTriFast(j,TriPts,TriNorm );//TriCtr,
|
|
if(foundTerrainType==-1) continue;
|
|
alignedVertices[0] = TriPts[0];
|
|
alignedVertices[1] = TriPts[1];
|
|
alignedVertices[2] = TriPts[2];
|
|
alignedNormal = TriNorm;
|
|
|
|
TriPts[2].Set( 0.0f, -1.0f, 0.0f );
|
|
TriPts[1].Set( irPosn.x, 10000.0f, irPosn.z );
|
|
if( IntersectWithPlane( TriPts[ 0 ], TriNorm, TriPts[1], TriPts[2], DistToPlane ) )
|
|
{
|
|
if( DistToPlane >= 0.0f )//alignedDistFromPlane.x >= 0.0f )
|
|
{
|
|
alignedDistFromPlane.Set( DistToPlane, DistToPlane, DistToPlane, 1.0f );
|
|
//alignedDistFromPlane.y = alignedDistFromPlane.x;
|
|
//alignedDistFromPlane.z = alignedDistFromPlane.x;
|
|
|
|
alignedPointOnPlane = TriPts[2];
|
|
alignedRayOrigin = TriPts[1];
|
|
|
|
asm __volatile__("
|
|
lqc2 vf7, 0(%5) # load pointOnPlane
|
|
lqc2 vf8, 0(%6) # load distFromPlane
|
|
lqc2 vf5, 0(%4) # load rayOrigin
|
|
vmul.xyz vf7, vf7, vf8 # pointOnPlane.Scale( DistToPlane );
|
|
lqc2 vf1, 0(%0) # load vertex0
|
|
lqc2 vf2, 0(%1) # load vertex1
|
|
vadd.xyz vf7, vf7, vf5 # pointOnPlane.Add( tmpVect ); tempVect == alignedRayOrigin, tempVect2 == alignedRayVector
|
|
lqc2 vf4, 0(%3) # load normal
|
|
vsub.xyz vf9, vf1, vf2 # tmpVect.Sub(TriPts[0],TriPts[1]);
|
|
lqc2 vf3, 0(%2) # load vertex2
|
|
vopmula.xyz ACC, vf9, vf4 # outer product stage 1 tmpVect.CrossProduct(TriNorm);
|
|
vopmsub.xyz vf9, vf4, vf9 # outer product stage 2
|
|
vsub.xyz vf10,vf7, vf2 # tmpVect2.Sub(pointOnPlane,TriPts[1]);
|
|
vmul.xyz vf20,vf10, vf9 # ==if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
sqc2 vf20, 0(%0) # store result in vertex 0
|
|
vsub.xyz vf9, vf2, vf3 # tmpVect.Sub(TriPts[1],TriPts[2]);
|
|
vopmula.xyz ACC, vf9, vf4 # outer product stage 1 tmpVect.CrossProduct(TriNorm);
|
|
vopmsub.xyz vf9, vf4, vf9 # outer product stage 2
|
|
vsub.xyz vf10,vf7, vf3 # tmpVect2.Sub(pointOnPlane,TriPts[2]);
|
|
vmul.xyz vf21,vf10, vf9 # ==if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
sqc2 vf21, 0(%1) # store result in vertex 1
|
|
vsub.xyz vf9, vf3, vf1 # tmpVect.Sub(TriPts[2],TriPts[0]);
|
|
vopmula.xyz ACC, vf9, vf4 # outer product stage 1 tmpVect.CrossProduct(TriNorm);
|
|
vopmsub.xyz vf9, vf4, vf9 # outer product stage 2
|
|
vsub.xyz vf10,vf7, vf1 # tmpVect2.Sub(pointOnPlane,TriPts[0]);
|
|
vmul.xyz vf22,vf10, vf9 # ==if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
sqc2 vf22, 0(%2) # store result in vertex 2
|
|
sqc2 vf7, 0(%5) # store result in vertex 2
|
|
": // no outputs
|
|
: "r" (&(alignedVertices[0])),
|
|
"r" (&(alignedVertices[1])),
|
|
"r" (&(alignedVertices[2])),
|
|
"r" (&alignedNormal),
|
|
"r" (&alignedRayOrigin),
|
|
"r" (&alignedPointOnPlane),
|
|
"r" (&alignedDistFromPlane)
|
|
: "memory" );
|
|
|
|
if( ((alignedVertices[0].x+alignedVertices[0].y+alignedVertices[0].z) >= 0.00f)
|
|
&& ((alignedVertices[1].x+alignedVertices[1].y+alignedVertices[1].z) >= 0.00f)
|
|
&& ((alignedVertices[2].x+alignedVertices[2].y+alignedVertices[2].z) >= 0.00f)
|
|
)
|
|
{
|
|
orGroundPlaneNorm = alignedNormal;
|
|
orGroundPlanePosn = alignedPointOnPlane;
|
|
obFoundPlane = true;
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
|
|
//time = radTimeGetMicroseconds64()-time;
|
|
//rReleasePrintf("vu0 found t=%d \t-=- ",(int)time);
|
|
|
|
return foundTerrainType;
|
|
//j=-1; //i=-1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
}
|
|
|
|
//time = radTimeGetMicroseconds64()-time;
|
|
//rReleasePrintf("vu0 miss t=%d \t-=- ",(int)time);
|
|
return 0;
|
|
|
|
#else
|
|
obFoundPlane = false;
|
|
// time = radTimeGetMicroseconds64();
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
rCurrentLeaf.mIntersectElems[i]->IntoTheVoid_WithGoFastaStripes();
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
//foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mTri(j,TriPts,TriNorm );//TriCtr,
|
|
TriPts[0] = irPosn;
|
|
foundTerrainType = rCurrentLeaf.mIntersectElems[i]->mFlatTriFast(j,TriPts,TriNorm );
|
|
if(foundTerrainType==-1) continue;
|
|
// This first test finds the ground plane directly beneath the sphere (on the y axis)
|
|
|
|
// make tmpVect a vector from the sphere position towards the ground
|
|
tmpVect2.Set( 0.0f, -1.0f, 0.0f );
|
|
|
|
//if(( !obFoundPlane ) && ( tmpVect2.Dot( TriNorm ) < 0 ))
|
|
{
|
|
tmpVect.Set( irPosn.x, 10000.0f, irPosn.z );
|
|
|
|
if( IntersectWithPlane( TriPts[ 0 ], TriNorm, tmpVect, tmpVect2, DistToPlane ) )
|
|
{
|
|
if(( DistToPlane >= 0.0f ) )
|
|
{
|
|
rmt::Vector pointOnPlane = tmpVect2;
|
|
pointOnPlane.Scale( DistToPlane );
|
|
|
|
pointOnPlane.Add( tmpVect );
|
|
|
|
tmpVect.Sub(TriPts[0],TriPts[1]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[1]);
|
|
if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
{
|
|
tmpVect.Sub(TriPts[1],TriPts[2]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[2]);
|
|
if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
{
|
|
tmpVect.Sub(TriPts[2],TriPts[0]);
|
|
tmpVect.CrossProduct(TriNorm);
|
|
|
|
tmpVect2.Sub(pointOnPlane,TriPts[0]);
|
|
if( tmpVect.Dot(tmpVect2) >= 0.00f)
|
|
{
|
|
orGroundPlaneNorm = TriNorm;
|
|
orGroundPlanePosn = pointOnPlane;
|
|
obFoundPlane = true;
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
|
|
//time = radTimeGetMicroseconds64()-time;
|
|
//rReleasePrintf("normal found t=%d\n",(int)time);
|
|
|
|
return foundTerrainType;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
rCurrentLeaf.mIntersectElems[i]->OutOfTheVoid_WithGoFastaStripes();
|
|
}
|
|
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
//========================================================================
|
|
// IntersectManager::FindIntersection
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
int IntersectManager::FindIntersection
|
|
(
|
|
rmt::Vector& irPosn,
|
|
float iRadius,
|
|
rmt::Vector& orDeepestIntersectPosn,
|
|
rmt::Vector& orDeepestIntersectNorm
|
|
)
|
|
{
|
|
SpatialNode<tGeometry,tGeometry,IntersectDSG>& rCurrentLeaf = GetRenderManager()->GetWorldScene()->mStaticTreeWalker.rSeekLeaf((Vector3f&)irPosn);
|
|
|
|
rmt::Vector tmpVect, tmpVect2, TriPts[3], TriNorm, TriCtr;
|
|
float TriRadius, DistToPlane, ClosestDistToPlane = 20000.0f;
|
|
int foundTerrainType = -1;
|
|
// iRadius *= 2.5f;
|
|
//MS7 Default, in case we don't find an intersection
|
|
orDeepestIntersectPosn = irPosn;
|
|
orDeepestIntersectPosn.y -= 2.0f*iRadius;
|
|
|
|
orDeepestIntersectNorm.Set(0.0f,1.0f,0.0f);
|
|
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
TriRadius = rCurrentLeaf.mIntersectElems[i]->mTri(j,TriPts,TriNorm,TriCtr, &foundTerrainType );
|
|
|
|
// make tmpVect a vector from the wheel position towards the ground
|
|
tmpVect2.Set( 0.0f, -1.0f, 0.0f );
|
|
|
|
if( TriNorm.y < 0 )
|
|
{
|
|
int i = 0;
|
|
}
|
|
|
|
if( tmpVect2.Dot( TriNorm ) < 0 )
|
|
{
|
|
if( IntersectWithPlane( TriPts[ 0 ], TriNorm, irPosn, tmpVect2, DistToPlane ) )
|
|
{
|
|
// if( (DistToPlane >= 0) && (DistToPlane <= iRadius) && (DistToPlane < ClosestDistToPlane) )
|
|
{
|
|
rmt::Vector pointOnPlane = tmpVect2;
|
|
pointOnPlane.Scale( DistToPlane );
|
|
pointOnPlane.Add( irPosn );
|
|
|
|
(tmpVect.Sub(TriPts[0],TriPts[1])).CrossProduct(TriNorm);
|
|
|
|
if( tmpVect.Dot(tmpVect2.Sub(pointOnPlane,TriPts[1])) >= 0.0f )
|
|
{
|
|
(tmpVect.Sub(TriPts[1],TriPts[2])).CrossProduct(TriNorm);
|
|
|
|
if( tmpVect.Dot(tmpVect2.Sub(pointOnPlane,TriPts[1])) >= 0.0f )
|
|
{
|
|
(tmpVect.Sub(TriPts[2],TriPts[0])).CrossProduct(TriNorm);
|
|
|
|
if( tmpVect.Dot(tmpVect2.Sub(pointOnPlane,TriPts[0])) >= 0.0f )
|
|
{
|
|
ClosestDistToPlane = DistToPlane;
|
|
|
|
orDeepestIntersectNorm = TriNorm;
|
|
orDeepestIntersectPosn = pointOnPlane;
|
|
return foundTerrainType;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
for( int i=rCurrentLeaf.mIntersectElems.mUseSize-1; i>-1; i-- )
|
|
{
|
|
for( int j=rCurrentLeaf.mIntersectElems[i]->nTris()-1; j>-1; j-- )
|
|
{
|
|
TriRadius = rCurrentLeaf.mIntersectElems[i]->mTri(j,TriPts,TriNorm,TriCtr);
|
|
//if( tmpVect.Sub(irPosn,TriCtr).MagnitudeSqr() < (TriRadius+iRadius)*(TriRadius+iRadius))
|
|
{
|
|
DistToPlane = TriNorm.Dot(tmpVect.Sub(irPosn,TriPts[0]));
|
|
//if( (DistToPlane >= 0.0f)&&(DistToPlane <= iRadius)&&(DistToPlane < ClosestDistToPlane) )
|
|
{
|
|
{
|
|
(tmpVect.Sub(TriPts[0],TriPts[1])).CrossProduct(TriNorm);
|
|
|
|
//rAssert( tmpVect.Dot(tmpVect2.Sub(TriCtr,TriPts[1])) >= 0.0f );
|
|
|
|
if( tmpVect.Dot(tmpVect2.Sub(irPosn,TriPts[1])) >= 0.0f )
|
|
{
|
|
(tmpVect.Sub(TriPts[1],TriPts[2])).CrossProduct(TriNorm);
|
|
|
|
//rAssert( tmpVect.Dot(tmpVect2.Sub(TriCtr,TriPts[2])) >= 0.0f );
|
|
|
|
if( tmpVect.Dot(tmpVect2.Sub(irPosn,TriPts[1])) >= 0.0f )
|
|
{
|
|
(tmpVect.Sub(TriPts[2],TriPts[0])).CrossProduct(TriNorm);
|
|
|
|
//rAssert( tmpVect.Dot(tmpVect2.Sub(TriCtr,TriPts[0])) >= 0.0f );
|
|
|
|
if( tmpVect.Dot(tmpVect2.Sub(irPosn,TriPts[0])) >= 0.0f )
|
|
{
|
|
tmpVect2 = TriNorm;
|
|
tmpVect.Sub(irPosn,TriNorm.Scale(DistToPlane));
|
|
|
|
ClosestDistToPlane = DistToPlane;
|
|
|
|
orDeepestIntersectNorm = tmpVect2;
|
|
orDeepestIntersectPosn = tmpVect;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
if( ClosestDistToPlane == 20000.0f )
|
|
{
|
|
return -1;
|
|
}
|
|
else if( orDeepestIntersectNorm.y < 0.0001f )
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
bool IntersectManager::LineOfSightXZ( const rmt::Vector& start, const rmt::Vector& end, const DynaPhysDSG* avoidObject )
|
|
{
|
|
|
|
rmt::Vector segmentCenter = ( start + end ) / 2;
|
|
float radius = ( segmentCenter - start ).Magnitude();
|
|
|
|
rmt::Vector2 midPoint;
|
|
midPoint.x = ( start.x + end.x ) * 0.5f;
|
|
midPoint.y = ( start.z + end.z ) * 0.5f;
|
|
|
|
float length;
|
|
rmt::Vector2 direction;
|
|
{
|
|
float diffX = end.x - start.x;
|
|
float diffZ = end.z - start.z;
|
|
length = rmt::Sqrt( diffX * diffX + diffZ * diffZ );
|
|
float scale = 1.0f / length;
|
|
direction.x = diffX * scale;
|
|
direction.y = diffZ * scale;
|
|
}
|
|
float halfLen = length * 0.5f;
|
|
|
|
ReserveArray< StaticPhysDSG* > staticsList( 200 );
|
|
|
|
bool lineOfSight = true;
|
|
// Test static objects
|
|
FindStaticPhysElems( segmentCenter, radius, staticsList );
|
|
for ( int i = 0 ; i < staticsList.mUseSize ; i++ )
|
|
{
|
|
rmt::Box3D box;
|
|
staticsList[i]->GetBoundingBox( &box );
|
|
if ( IntersectsXZ( direction, midPoint, halfLen, box ) )
|
|
{
|
|
lineOfSight = false;
|
|
break;
|
|
}
|
|
}
|
|
// Test fence pieces
|
|
if ( lineOfSight )
|
|
{
|
|
ReserveArray< FenceEntityDSG* > fenceList(400);
|
|
FindFenceElems( segmentCenter, radius, fenceList );
|
|
for ( int i = 0 ; i < fenceList.mUseSize ; i++ )
|
|
{
|
|
rmt::Box3D box;
|
|
fenceList[i]->GetBoundingBox( &box );
|
|
if ( IntersectsXZ( direction, midPoint, halfLen, box ) )
|
|
{
|
|
lineOfSight = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Test dynamic objects
|
|
if ( lineOfSight )
|
|
{
|
|
ReserveArray< DynaPhysDSG* > dynaList(200);
|
|
FindDynaPhysElems( segmentCenter, radius, dynaList );
|
|
for ( int i = 0 ; i < dynaList.mUseSize ; i++ )
|
|
{
|
|
// Avoid testing line of sight with the actor's DSG object
|
|
if ( dynaList[i] == avoidObject )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rmt::Box3D box;
|
|
dynaList[i]->GetBoundingBox( &box );
|
|
if ( IntersectsXZ( direction, midPoint, halfLen, box ) )
|
|
{
|
|
lineOfSight = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return lineOfSight;
|
|
|
|
}
|
|
bool IntersectManager::LineOfSight( const rmt::Vector& start, const rmt::Vector& end, const DynaPhysDSG* avoidObject )
|
|
{
|
|
|
|
rmt::Vector segmentCenter = ( start + end ) / 2;
|
|
float radius = ( segmentCenter - start ).Magnitude();
|
|
|
|
rmt::Vector midPoint;
|
|
midPoint = ( end + start ) * 0.5f;
|
|
|
|
float length;
|
|
rmt::Vector direction = end - start;
|
|
length = direction.Length();
|
|
direction.Normalize();
|
|
float halfLen = length * 0.5f;
|
|
|
|
ReserveArray< StaticPhysDSG* > staticsList( 200 );
|
|
|
|
bool lineOfSight = true;
|
|
// Test static objects
|
|
FindStaticPhysElems( segmentCenter, radius, staticsList );
|
|
for ( int i = 0 ; i < staticsList.mUseSize ; i++ )
|
|
{
|
|
rmt::Box3D box;
|
|
staticsList[i]->GetBoundingBox( &box );
|
|
if ( Intersects( direction, midPoint, halfLen, box ) )
|
|
{
|
|
lineOfSight = false;
|
|
break;
|
|
}
|
|
}
|
|
// Test fence pieces
|
|
if ( lineOfSight )
|
|
{
|
|
ReserveArray< FenceEntityDSG* > fenceList(400);
|
|
FindFenceElems( segmentCenter, radius, fenceList );
|
|
for ( int i = 0 ; i < fenceList.mUseSize ; i++ )
|
|
{
|
|
rmt::Box3D box;
|
|
fenceList[i]->GetBoundingBox( &box );
|
|
if ( Intersects( direction, midPoint, halfLen, box ) )
|
|
{
|
|
lineOfSight = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Test dynamic objects
|
|
if ( lineOfSight )
|
|
{
|
|
ReserveArray< DynaPhysDSG* > dynaList(200);
|
|
FindDynaPhysElems( segmentCenter, radius, dynaList );
|
|
for ( int i = 0 ; i < dynaList.mUseSize ; i++ )
|
|
{
|
|
// Avoid testing line of sight with the actor's DSG object
|
|
if ( dynaList[i] == avoidObject )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
rmt::Box3D box;
|
|
dynaList[i]->GetBoundingBox( &box );
|
|
if ( Intersects( direction, midPoint, halfLen, box ) )
|
|
{
|
|
lineOfSight = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return lineOfSight;
|
|
|
|
}
|
|
|
|
//************************************************************************
|
|
//
|
|
// Protected Member Functions : IntersectManager
|
|
//
|
|
//************************************************************************
|
|
|
|
//************************************************************************
|
|
//
|
|
// Private Member Functions : IntersectManager
|
|
//
|
|
//************************************************************************
|
|
|
|
|
|
//========================================================================
|
|
// IntersectManager::IntersectManager
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
// Determines if a line segment intersects a bounding box
|
|
// line segment is broken into a direction vector, the midway point of the segment
|
|
// and the length / 2. height values are ignored when calculating
|
|
// for a minor performance boost
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
|
|
bool IntersectManager::IntersectsXZ( const rmt::Vector2& direction,
|
|
const rmt::Vector2& midPoint,
|
|
float halfLen,
|
|
const rmt::Box3D& box )
|
|
{
|
|
rmt::Vector boxMid = box.Mid();
|
|
|
|
rmt::Vector2 boxExtents;
|
|
boxExtents.x = box.high.x - boxMid.x;
|
|
boxExtents.y = box.high.z - boxMid.z;
|
|
|
|
rmt::Vector2 t;
|
|
t.x = boxMid.x - midPoint.x;
|
|
t.y = boxMid.z - midPoint.y;
|
|
|
|
if ( fabsf( t.x ) > boxExtents.x + halfLen * fabsf( direction.x ) )
|
|
{
|
|
return false;
|
|
}
|
|
if ( fabsf( t.y ) > boxExtents.y + halfLen * fabsf( direction.y ) )
|
|
{
|
|
return false;
|
|
}
|
|
float r = boxExtents.x * fabsf( direction.y ) +
|
|
boxExtents.y * fabsf( direction.x );
|
|
|
|
if ( fabsf( t.x * direction.y - t.y * direction.x ) > r )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool IntersectManager::Intersects( const rmt::Vector& direction,
|
|
const rmt::Vector& midPoint,
|
|
float halfLen,
|
|
const rmt::Box3D& box )
|
|
{
|
|
rmt::Vector boxMid = box.Mid();
|
|
|
|
rmt::Vector boxExtents;
|
|
boxExtents.x = box.high.x - boxMid.x;
|
|
boxExtents.y = box.high.y - boxMid.y;
|
|
boxExtents.z = box.high.z - boxMid.z;
|
|
|
|
rmt::Vector t;
|
|
t.x = boxMid.x - midPoint.x;
|
|
t.y = boxMid.y - midPoint.y;
|
|
t.z = boxMid.z - midPoint.z;
|
|
|
|
if ( fabsf( t.x ) > boxExtents.x + halfLen * fabsf( direction.x ) )
|
|
{
|
|
return false;
|
|
}
|
|
if ( fabsf( t.y ) > boxExtents.y + halfLen * fabsf( direction.y ) )
|
|
{
|
|
return false;
|
|
}
|
|
if ( fabsf( t.z ) > boxExtents.z + halfLen * fabsf( direction.z ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
float r = boxExtents.y * fabsf( direction.z ) +
|
|
boxExtents.z * fabsf( direction.y );
|
|
|
|
if ( fabsf( t.y * direction.z - t.z * direction.y ) > r )
|
|
return false;
|
|
|
|
/////////////////////////////////////////////
|
|
r = boxExtents.x * fabsf( direction.z ) +
|
|
boxExtents.z * fabsf( direction.x );
|
|
|
|
if ( fabsf( t.z * direction.x - t.x * direction.z ) > r )
|
|
return false;
|
|
/////////////////////////////////////////////
|
|
r = boxExtents.x * fabsf( direction.y ) +
|
|
boxExtents.y * fabsf( direction.x );
|
|
|
|
if ( fabsf( t.x * direction.y - t.y * direction.x ) > r )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
// IntersectManager::IntersectManager
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
|
|
IntersectManager::IntersectManager()
|
|
: mbSameFrame(false)
|
|
{
|
|
}
|
|
|
|
//========================================================================
|
|
// IntersectManager::~IntersectManager
|
|
//========================================================================
|
|
//
|
|
// Description:
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Constraints: None.
|
|
//
|
|
//========================================================================
|
|
IntersectManager::~IntersectManager()
|
|
{
|
|
}
|