2019-03-07 22:23:41 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Verve
|
|
|
|
|
// Copyright (C) 2014 - Violent Tulip
|
|
|
|
|
//
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to
|
|
|
|
|
// deal in the Software without restriction, including without limitation the
|
|
|
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
//
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
//
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
// IN THE SOFTWARE.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
#include "VActorPhysicsController.h"
|
|
|
|
|
|
|
|
|
|
#include "VActor.h"
|
|
|
|
|
#include "VActorData.h"
|
|
|
|
|
#include "VActorPhysicsStates.h"
|
|
|
|
|
|
|
|
|
|
#include "Verve/VPath/VPath.h"
|
|
|
|
|
|
|
|
|
|
#include "collision/clippedPolyList.h"
|
|
|
|
|
#include "collision/earlyOutPolyList.h"
|
|
|
|
|
#include "collision/extrudedPolyList.h"
|
|
|
|
|
#include "core/stream/bitStream.h"
|
|
|
|
|
#include "environment/waterObject.h"
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static const U32 sGroundCollisionMask = ( StaticObjectType | StaticShapeObjectType | TerrainObjectType );
|
|
|
|
|
static const U32 sMoveCollisionMask = ( PlayerObjectType | VehicleObjectType );
|
|
|
|
|
static const U32 sCollisionMask = ( sGroundCollisionMask | sMoveCollisionMask );
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
VActorPhysicsController::VActorPhysicsController( void ) :
|
|
|
|
|
mObject( NULL ),
|
|
|
|
|
mMountedPath( NULL ),
|
|
|
|
|
mPhysicsState( 0 ),
|
|
|
|
|
mControlState( k_NullControlState ),
|
|
|
|
|
mMoveState( k_NullMove ),
|
|
|
|
|
mVelocity( VectorF::Zero ),
|
2020-05-11 20:53:14 +00:00
|
|
|
mGravity( 0.f, 0.f, -9.8f ),
|
|
|
|
|
mOnGround(false)
|
2019-03-07 22:23:41 +00:00
|
|
|
{
|
|
|
|
|
// Void.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VActorPhysicsController::~VActorPhysicsController( void )
|
|
|
|
|
{
|
|
|
|
|
// Clear Object.
|
|
|
|
|
clearObject();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Initialisation Methods.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::initPhysicsController();
|
|
|
|
|
//
|
|
|
|
|
// Initialise the physics table and setup the interface between the Controller
|
|
|
|
|
// and the reference object.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool VActorPhysicsController::initPhysicsController( VActor *pObject )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !pObject )
|
|
|
|
|
{
|
|
|
|
|
// Assert & Quit.
|
|
|
|
|
AssertFatal( false, "VActorPhysicsController::initPhysicsController() - Invalid Object Specified." );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set Object.
|
|
|
|
|
mObject = pObject;
|
|
|
|
|
// Register for Actor Events.
|
|
|
|
|
mObject->getEventSignal().notify( this, &VActorPhysicsController::onActorEvent );
|
|
|
|
|
|
|
|
|
|
// Set Table's Reference.
|
|
|
|
|
mPhysicsStateTable.setObject( pObject );
|
|
|
|
|
|
|
|
|
|
// Init the Convex Box.
|
|
|
|
|
mConvex.init( pObject );
|
|
|
|
|
|
|
|
|
|
// Reset Interp.
|
|
|
|
|
mInterpController.resetDelta( pObject->getTransform() );
|
|
|
|
|
|
|
|
|
|
// Validate.
|
|
|
|
|
return initPhysicsTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::initPhysicsTable();
|
|
|
|
|
//
|
|
|
|
|
// Register the available physics states which this controller may utilize.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool VActorPhysicsController::initPhysicsTable( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No, Quit Now.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear the Table.
|
|
|
|
|
mPhysicsStateTable.clear();
|
|
|
|
|
|
|
|
|
|
// Fetch Sequence List.
|
|
|
|
|
VActorData::tPhysicsStateVector *stateList = getObjectDataBlock()->getPhysicsStateList();
|
|
|
|
|
|
|
|
|
|
// Initialise the Physics States.
|
|
|
|
|
for ( VActorData::tPhysicsStateVector::iterator itr = stateList->begin();
|
|
|
|
|
itr != stateList->end();
|
|
|
|
|
itr++ )
|
|
|
|
|
{
|
|
|
|
|
// Fetch Sequence Definition.
|
|
|
|
|
const VActorData::sPhysicsState &physState = ( *itr );
|
|
|
|
|
|
|
|
|
|
// Valid State?
|
|
|
|
|
if ( physState.State )
|
|
|
|
|
{
|
|
|
|
|
// Register State.
|
|
|
|
|
mPhysicsStateTable.registerState( physState.State, physState.Priority );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort the Table.
|
|
|
|
|
mPhysicsStateTable.sort();
|
|
|
|
|
|
|
|
|
|
// Valid.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Accessor Methods
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isValidObject();
|
|
|
|
|
//
|
|
|
|
|
// Do we have a valid reference object?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool VActorPhysicsController::isValidObject( void )
|
|
|
|
|
{
|
|
|
|
|
return ( mObject && mObject->getDataBlock() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getObject();
|
|
|
|
|
//
|
|
|
|
|
// Return the reference object.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
VActor *VActorPhysicsController::getObject( void )
|
|
|
|
|
{
|
|
|
|
|
return mObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getObjectDataBlock();
|
|
|
|
|
//
|
|
|
|
|
// Get the Actor Data for the reference object.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
VActorData *VActorPhysicsController::getObjectDataBlock( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !mObject )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return DataBlock.
|
|
|
|
|
return mObject->getDataBlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::clearObject();
|
|
|
|
|
//
|
|
|
|
|
// Clear the reference object. Note that this should *never* be called outside
|
|
|
|
|
// of the controller's destructor!
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::clearObject( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !mObject )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear Notify.
|
|
|
|
|
mObject->getEventSignal().remove( this, &VActorPhysicsController::onActorEvent );
|
|
|
|
|
|
|
|
|
|
// Clear Object.
|
|
|
|
|
mObject = NULL;
|
|
|
|
|
|
|
|
|
|
// Clear Table.
|
|
|
|
|
mPhysicsStateTable.setObject( NULL );
|
|
|
|
|
mPhysicsStateTable.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getControlState();
|
|
|
|
|
//
|
|
|
|
|
// Get the current Control State.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const U32 VActorPhysicsController::getControlState( void )
|
|
|
|
|
{
|
|
|
|
|
return mControlState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::clearControlState( pControlState );
|
|
|
|
|
//
|
|
|
|
|
// Clear the Control State of a particular mask.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::clearControlState( const U32 &pControlState )
|
|
|
|
|
{
|
|
|
|
|
mControlState &= ( ~pControlState );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::setControlState( pControlState );
|
|
|
|
|
//
|
|
|
|
|
// Set the Control State.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::setControlState( const U32 &pControlState )
|
|
|
|
|
{
|
|
|
|
|
mControlState = pControlState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isMoving();
|
|
|
|
|
//
|
|
|
|
|
// Is the Actor currently Moving?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const bool VActorPhysicsController::isMoving( void )
|
|
|
|
|
{
|
|
|
|
|
return ( !mIsZero( getVelocity().lenSquared() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isMoving( pMoveState );
|
|
|
|
|
//
|
|
|
|
|
// Is the Actor currently moving with the desired state?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const bool VActorPhysicsController::isMoving( const U32 &pMoveState )
|
|
|
|
|
{
|
|
|
|
|
// Moving?
|
|
|
|
|
return ( ( getMoveState() & pMoveState ) && isMoving() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getMoveState();
|
|
|
|
|
//
|
|
|
|
|
// Get the current Move State.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const U32 VActorPhysicsController::getMoveState( void )
|
|
|
|
|
{
|
|
|
|
|
// Return Move State.
|
|
|
|
|
return mMoveState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::clearMoveState( pMoveState );
|
|
|
|
|
//
|
|
|
|
|
// Clear the Move State of a particular mask.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::clearMoveState( const U32 &pMoveState )
|
|
|
|
|
{
|
|
|
|
|
// Set Move State.
|
|
|
|
|
mMoveState &= ( ~pMoveState );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::setMoveState( pMoveState );
|
|
|
|
|
//
|
|
|
|
|
// Set the Move State.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::setMoveState( const U32 &pMoveState )
|
|
|
|
|
{
|
|
|
|
|
// Set Move State.
|
|
|
|
|
mMoveState = pMoveState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isPathing();
|
|
|
|
|
//
|
|
|
|
|
// Is the Actor Pathing?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const bool VActorPhysicsController::isPathing( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ( mMountedPath != NULL );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getPathObject();
|
|
|
|
|
//
|
|
|
|
|
// Get the Path Object the Actor is mounted to.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
VPath *VActorPhysicsController::getPathObject( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mMountedPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isOnGround();
|
|
|
|
|
//
|
|
|
|
|
// Is the Actor On the Ground?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const bool VActorPhysicsController::isOnGround( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Objects?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// On Ground?
|
|
|
|
|
return ( mOnGround && mGroundObject && !isInWater() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isInAir();
|
|
|
|
|
//
|
|
|
|
|
// Is the Actor in the Air?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const bool VActorPhysicsController::isInAir( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Objects?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// In Air?
|
|
|
|
|
return ( !isOnGround() && !isInWater() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::isInWater();
|
|
|
|
|
//
|
|
|
|
|
// Is the Actor in the Water?
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
const bool VActorPhysicsController::isInWater( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Objects?
|
|
|
|
|
if ( !isValidObject() || !getWaterObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Submerged?
|
|
|
|
|
return ( ( mObject->getWaterCoverage() + POINT_EPSILON ) >= mObject->getDataBlock()->getSumbergeCoverage() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getWaterObject();
|
|
|
|
|
//
|
|
|
|
|
// Get the current Water Object the Actor is in.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
WaterObject *VActorPhysicsController::getWaterObject( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mObject->getCurrentWaterObject();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getTransform();
|
|
|
|
|
//
|
|
|
|
|
// Get the Actor's Transform.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
MatrixF VActorPhysicsController::getTransform( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return MatrixF::Identity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return Transform.
|
|
|
|
|
return mObject->getTransform();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::setTransform( pTransform );
|
|
|
|
|
//
|
|
|
|
|
// Set the Actor's Transform.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::setTransform( const MatrixF &pTransform )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply Transform.
|
|
|
|
|
mObject->setTransform( pTransform );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getPosition();
|
|
|
|
|
//
|
|
|
|
|
// Get the Actor's Position.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
Point3F VActorPhysicsController::getPosition( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return Point3F::Zero;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return Position.
|
|
|
|
|
return mObject->getPosition();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::setPosition( pPosition );
|
|
|
|
|
//
|
|
|
|
|
// Set the Actor's Position.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::setPosition( const Point3F &pPosition )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply Position.
|
|
|
|
|
mObject->setPosition( pPosition );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::applyGravity( pElapsedTime );
|
|
|
|
|
//
|
|
|
|
|
// Apply gravity for the elapsed period.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::applyGravity( const F32 &pElapsedTime )
|
|
|
|
|
{
|
|
|
|
|
// Get Velocity.
|
|
|
|
|
VectorF velocity = getVelocity();
|
|
|
|
|
// Add Tick Gravity.
|
|
|
|
|
velocity += getGravity() * pElapsedTime;
|
|
|
|
|
// Apply.
|
|
|
|
|
setVelocity( velocity );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::getVelocity();
|
|
|
|
|
//
|
|
|
|
|
// Get the Actor's Velocity.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
VectorF VActorPhysicsController::getVelocity( void )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No.
|
|
|
|
|
return VectorF::Zero;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return Velocity.
|
|
|
|
|
return mVelocity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::setVelocity( pVelocity );
|
|
|
|
|
//
|
|
|
|
|
// Set the Actor's Velocity.
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::setVelocity( const VectorF &pVelocity )
|
|
|
|
|
{
|
|
|
|
|
// Set Velocity.
|
|
|
|
|
mVelocity = pVelocity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Physics Methods
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::update( pDelta, pMove );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::update( const F32 &pDelta, const Move *pMove )
|
|
|
|
|
{
|
|
|
|
|
// Valid Objects?
|
|
|
|
|
if ( !isValidObject() )
|
|
|
|
|
{
|
|
|
|
|
// No, Quit Now.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pre-tick Update.
|
|
|
|
|
preTickUpdate( pDelta );
|
|
|
|
|
|
|
|
|
|
// Integrate Tick Update.
|
|
|
|
|
integrateTickUpdate( pDelta, pMove );
|
|
|
|
|
|
|
|
|
|
// Post-tick Update.
|
|
|
|
|
postTickUpdate( pDelta );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::preTickUpdate( pDelta );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::preTickUpdate( const F32 &pDelta )
|
|
|
|
|
{
|
|
|
|
|
// Pop Delta.
|
|
|
|
|
mInterpController.popDelta();
|
|
|
|
|
|
|
|
|
|
switch( mControlState )
|
|
|
|
|
{
|
|
|
|
|
case k_PathControlState :
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( isPathing(), "VActorPhysicsController::preTickUpdate() - Invalid Path State." );
|
|
|
|
|
|
|
|
|
|
// Fetch Mount Velocity.
|
|
|
|
|
const VectorF &mountVelocity = mMountedPath->getMountVelocity( mObject->getMountNode() );
|
|
|
|
|
|
|
|
|
|
// Use X & Y Velocity.
|
|
|
|
|
VectorF velocity = getVelocity();
|
|
|
|
|
velocity.x = mountVelocity.x;
|
|
|
|
|
velocity.y = mountVelocity.y;
|
|
|
|
|
|
|
|
|
|
// Apply Updates.
|
|
|
|
|
setVelocity( velocity );
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update Move State.
|
|
|
|
|
updateMoveState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::integrateTickUpdate( pDelta, pMove );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::integrateTickUpdate( const F32 &pDelta, const Move *pMove )
|
|
|
|
|
{
|
|
|
|
|
// Update Collision Set.
|
|
|
|
|
updateWorkingCollisionSet();
|
|
|
|
|
// Ground Ground Status.
|
|
|
|
|
updateGroundStatus();
|
|
|
|
|
|
|
|
|
|
// Execute Physics Table.
|
|
|
|
|
VActorPhysicsState *physState = dynamic_cast<VActorPhysicsState*>( mPhysicsStateTable.execute() );
|
|
|
|
|
// Assert.
|
|
|
|
|
AssertFatal( physState, "VActorPhysicsController::update() - Invalid Physics State in the Table." );
|
|
|
|
|
|
|
|
|
|
// Process the State.
|
|
|
|
|
physState->processTick( mObject, pDelta, pMove );
|
|
|
|
|
|
|
|
|
|
// Process Collisions.
|
|
|
|
|
processCollisions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::postTickUpdate( pDelta );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::postTickUpdate( const F32 &pDelta )
|
|
|
|
|
{
|
|
|
|
|
switch( mControlState )
|
|
|
|
|
{
|
|
|
|
|
case k_PathControlState :
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( isPathing(), "VActorPhysicsController::postTickUpdate() - Invalid Path State." );
|
|
|
|
|
|
|
|
|
|
// Fetch Mount Transform.
|
|
|
|
|
MatrixF transform;
|
|
|
|
|
mMountedPath->getMountTransform( mObject->getMountNode(), getTransform(), &transform );
|
|
|
|
|
// Fetch Mount Position.
|
|
|
|
|
const Point3F &mountPosition = transform.getPosition();
|
|
|
|
|
|
|
|
|
|
// Update X & Y Position.
|
|
|
|
|
Point3F position = getPosition();
|
|
|
|
|
position.x = mountPosition.x;
|
|
|
|
|
position.y = mountPosition.y;
|
|
|
|
|
|
|
|
|
|
// In Water?
|
|
|
|
|
bool underWater = false;
|
|
|
|
|
if ( isInWater() )
|
|
|
|
|
{
|
|
|
|
|
// Fetch Body of Water.
|
|
|
|
|
WaterObject *waterBody = getWaterObject();
|
|
|
|
|
|
|
|
|
|
// Fetch Surface Position.
|
|
|
|
|
const F32 &waterSurfacePosition = waterBody->getSurfaceHeight( Point2F( position.x, position.y ) );
|
|
|
|
|
// Fetch Submersion Position.
|
|
|
|
|
const F32 sumbersionPosition = waterSurfacePosition - ( mObject->getWorldBox().len_z() * mObject->getDataBlock()->getSumbergeCoverage() );
|
|
|
|
|
|
|
|
|
|
// Choose a Z Value.
|
|
|
|
|
// Note: This is done so that the Actor will either path under the
|
|
|
|
|
// water, or it will swim along the water's surface.
|
|
|
|
|
position.z = getMin( mountPosition.z, sumbersionPosition );
|
|
|
|
|
|
|
|
|
|
// Under Water?
|
|
|
|
|
underWater = ( position.z < sumbersionPosition );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Under Water?
|
|
|
|
|
if ( !underWater )
|
|
|
|
|
{
|
|
|
|
|
// Fetch Y Column.
|
|
|
|
|
VectorF forwardVector;
|
|
|
|
|
transform.getColumn( 1, &forwardVector );
|
|
|
|
|
|
|
|
|
|
// Determine Angle.
|
|
|
|
|
const F32 &angle = -mAtan2( -forwardVector.x, forwardVector.y );
|
|
|
|
|
|
|
|
|
|
// Reset Transform.
|
|
|
|
|
transform.set( EulerF( 0.f, 0.f, angle ) );
|
|
|
|
|
|
|
|
|
|
// In the air?
|
|
|
|
|
if ( !isOnGround() )
|
|
|
|
|
{
|
|
|
|
|
// Apply z-axis force.
|
|
|
|
|
position.z += ( getVelocity().z * pDelta );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update Transform.
|
|
|
|
|
transform.setPosition( position );
|
|
|
|
|
|
|
|
|
|
// Apply Update.
|
|
|
|
|
setTransform( transform );
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
default :
|
|
|
|
|
{
|
|
|
|
|
// Fetch Transform.
|
|
|
|
|
MatrixF transform = getTransform();
|
|
|
|
|
|
|
|
|
|
// Determine the Post-Tick Position.
|
|
|
|
|
Point3F postTickPosition = getPosition() + ( getVelocity() * pDelta );
|
|
|
|
|
// Set the Post Tick Position.
|
|
|
|
|
transform.setPosition( postTickPosition );
|
|
|
|
|
|
|
|
|
|
// Apply the Transform.
|
|
|
|
|
setTransform( transform );
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Push Delta.
|
|
|
|
|
mInterpController.pushDelta( getTransform() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::interpolateTick( pDelta );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::interpolateTick( const F32 &pDelta )
|
|
|
|
|
{
|
|
|
|
|
// Fetch Interpolated Transform.
|
|
|
|
|
const MatrixF transform = mInterpController.getTransform( pDelta );
|
|
|
|
|
// Apply Render Transform.
|
|
|
|
|
mObject->setRenderTransform( transform );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::updateWorkingCollisionSet();
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::updateWorkingCollisionSet()
|
|
|
|
|
{
|
|
|
|
|
// Contstruct Bounding Box.
|
|
|
|
|
const Box3F boundingBox = mConvex.getBoundingBox( getTransform(), mObject->getScale() );
|
|
|
|
|
|
|
|
|
|
// Determine Sweep Vector.
|
|
|
|
|
const VectorF sweepVector = ( getVelocity() * TickSec );
|
|
|
|
|
|
|
|
|
|
// Construct Swept Box.
|
|
|
|
|
Box3F sweptBox = boundingBox;
|
|
|
|
|
sweptBox.minExtents.setMin( boundingBox.minExtents + sweepVector );
|
|
|
|
|
sweptBox.maxExtents.setMax( boundingBox.maxExtents + sweepVector );
|
|
|
|
|
|
|
|
|
|
// Update Collision List.
|
|
|
|
|
mObject->disableCollision();
|
|
|
|
|
mConvex.updateWorkingList( sweptBox, sCollisionMask );
|
|
|
|
|
mObject->enableCollision();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::updateMoveState();
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::updateMoveState( void )
|
|
|
|
|
{
|
|
|
|
|
switch( mControlState )
|
|
|
|
|
{
|
|
|
|
|
case k_PathControlState :
|
|
|
|
|
{
|
|
|
|
|
AssertFatal( isPathing(), "VActorPhysicsController::updateMoveState() - Invalid Path State." );
|
|
|
|
|
|
|
|
|
|
// Update Move State.
|
|
|
|
|
VPathObject *pathObject = mMountedPath->getPathObject( mObject );
|
|
|
|
|
if ( !pathObject->isActive() )
|
|
|
|
|
{
|
|
|
|
|
// Idle.
|
|
|
|
|
setMoveState( k_NullMove );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Set Movement Direction.
|
|
|
|
|
setMoveState( ( pathObject->isForward() ) ? k_ForwardMove : k_BackwardMove );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
default :
|
|
|
|
|
{
|
|
|
|
|
// Set Idle.
|
|
|
|
|
setMoveState( k_NullMove );
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::clearGroundStatus();
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::clearGroundStatus( void )
|
|
|
|
|
{
|
|
|
|
|
// Clear Grounding.
|
|
|
|
|
mOnGround = false;
|
|
|
|
|
mGroundObject = NULL;
|
|
|
|
|
mGroundNormal.zero();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::updateGroundStatus();
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::updateGroundStatus( void )
|
|
|
|
|
{
|
|
|
|
|
// Submerged?
|
|
|
|
|
if ( isInWater() )
|
|
|
|
|
{
|
|
|
|
|
// Clear Ground Status.
|
|
|
|
|
clearGroundStatus();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for Grounding.
|
|
|
|
|
SceneObject *groundObject;
|
|
|
|
|
Point3F groundPoint;
|
|
|
|
|
VectorF groundNormal;
|
|
|
|
|
if ( !findGroundContact( groundObject, groundPoint, groundNormal ) )
|
|
|
|
|
{
|
|
|
|
|
// Clear Ground Status.
|
|
|
|
|
clearGroundStatus();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tidy up the Contact Position.
|
|
|
|
|
// Note: This basically "clamps" the Actor to the surface of the ground
|
|
|
|
|
// object.
|
|
|
|
|
const Point3F objPosition = getPosition();
|
|
|
|
|
setPosition( objPosition - Point3F( 0.f, 0.f, ( objPosition.z - groundPoint.z ) ) );
|
|
|
|
|
|
|
|
|
|
// Clear Z-Axis Velocity.
|
|
|
|
|
mVelocity.z = 0.f;
|
|
|
|
|
|
|
|
|
|
// Store Details.
|
|
|
|
|
mOnGround = true;
|
|
|
|
|
mGroundObject = groundObject;
|
|
|
|
|
mGroundNormal = groundNormal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::findGroundContact( pContactObject, pContactPoint, pContactNormal );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool VActorPhysicsController::findGroundContact( SceneObject *&pContactObject, Point3F &pContactPoint, VectorF &pContactNormal )
|
|
|
|
|
{
|
|
|
|
|
// Setup Collision List.
|
|
|
|
|
static CollisionList sCollisionList;
|
|
|
|
|
sCollisionList.clear();
|
|
|
|
|
|
|
|
|
|
static Polyhedron sBoxPolyhedron;
|
|
|
|
|
static ExtrudedPolyList sExtrudedPolyList;
|
|
|
|
|
|
|
|
|
|
// Fetch Max Step Height.
|
|
|
|
|
const F32 stepHeight = mObject->getDataBlock()->getMaxStepHeight();
|
|
|
|
|
|
|
|
|
|
// Determine Positions.
|
|
|
|
|
const Point3F preTickPosition = getPosition() + Point3F( 0.f, 0.f, stepHeight );
|
|
|
|
|
const VectorF preTickVelocity = getVelocity() + mGravity - VectorF( 0.f, 0.f, stepHeight / TickSec );
|
|
|
|
|
const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec );
|
|
|
|
|
const VectorF postTickVector = postTickPosition - preTickPosition;
|
|
|
|
|
|
|
|
|
|
// Construct Scaled Box.
|
|
|
|
|
Box3F scaledBox = mObject->getObjBox();
|
|
|
|
|
scaledBox.minExtents.convolve( mObject->getScale() );
|
|
|
|
|
scaledBox.maxExtents.convolve( mObject->getScale() );
|
|
|
|
|
|
|
|
|
|
// Setup Polyherdron.
|
|
|
|
|
MatrixF collisionMatrix( true );
|
|
|
|
|
collisionMatrix.setPosition( preTickPosition );
|
|
|
|
|
sBoxPolyhedron.buildBox( collisionMatrix, scaledBox );
|
|
|
|
|
|
|
|
|
|
// Setup Extruded Poly List.
|
|
|
|
|
sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector );
|
|
|
|
|
sExtrudedPolyList.setVelocity( preTickVelocity );
|
|
|
|
|
sExtrudedPolyList.setCollisionList( &sCollisionList );
|
|
|
|
|
|
|
|
|
|
// Construct World Convex Box & Adjust for Sweep.
|
|
|
|
|
Box3F convexBox = scaledBox;
|
|
|
|
|
getTransform().mul( convexBox );
|
|
|
|
|
convexBox.minExtents += postTickVector;
|
|
|
|
|
convexBox.maxExtents += postTickVector;
|
|
|
|
|
|
|
|
|
|
// Build List of Contacts.
|
|
|
|
|
CollisionWorkingList &rList = mConvex.getWorkingList();
|
|
|
|
|
for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext )
|
|
|
|
|
{
|
|
|
|
|
Convex *convexShape = pList->mConvex;
|
|
|
|
|
|
|
|
|
|
// Ground Object?
|
|
|
|
|
if ( !( convexShape->getObject()->getTypeMask() & sGroundCollisionMask ) )
|
|
|
|
|
{
|
|
|
|
|
// No, Continue.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Overlap?
|
|
|
|
|
const Box3F &collisionConvexBox = convexShape->getBoundingBox();
|
|
|
|
|
if ( convexBox.isOverlapped( collisionConvexBox ) )
|
|
|
|
|
{
|
|
|
|
|
// Build Contact Information.
|
|
|
|
|
convexShape->getPolyList( &sExtrudedPolyList );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Valid Collision?
|
|
|
|
|
if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() < 0.f || sCollisionList.getTime() > 1.f )
|
|
|
|
|
{
|
|
|
|
|
// No, Quit Now.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use First Collision.
|
|
|
|
|
Collision *collision = &sCollisionList[0];
|
|
|
|
|
|
|
|
|
|
// More Collisions?
|
|
|
|
|
if ( sCollisionList.getCount() > 1 )
|
|
|
|
|
{
|
|
|
|
|
// Check for Better Contacts.
|
|
|
|
|
for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ )
|
|
|
|
|
{
|
|
|
|
|
if ( cp->faceDot > collision->faceDot )
|
|
|
|
|
{
|
|
|
|
|
// Use this One.
|
|
|
|
|
collision = cp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set Properties.
|
|
|
|
|
pContactObject = collision->object;
|
|
|
|
|
//pContactPoint = collision->point;
|
|
|
|
|
pContactPoint = ( preTickPosition + ( preTickVelocity * TickSec * sCollisionList.getTime() ) );
|
|
|
|
|
pContactNormal = collision->normal;
|
|
|
|
|
|
|
|
|
|
// Valid Contact.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::processCollisions();
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::processCollisions( void )
|
|
|
|
|
{
|
|
|
|
|
// Find & Resolve Collisions.
|
|
|
|
|
Collision *collision;
|
|
|
|
|
if ( findCollision( collision ) )
|
|
|
|
|
{
|
|
|
|
|
// Solve the Collision.
|
|
|
|
|
solveCollision( collision );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::findCollision( pCollision );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool VActorPhysicsController::findCollision( Collision *&pCollision )
|
|
|
|
|
{
|
|
|
|
|
// Setup Collision List.
|
|
|
|
|
static CollisionList sCollisionList;
|
|
|
|
|
sCollisionList.clear();
|
|
|
|
|
|
|
|
|
|
static Polyhedron sBoxPolyhedron;
|
|
|
|
|
static ExtrudedPolyList sExtrudedPolyList;
|
|
|
|
|
|
|
|
|
|
// Determine Positions.
|
|
|
|
|
const Point3F preTickPosition = getPosition();
|
|
|
|
|
const VectorF preTickVelocity = getVelocity();
|
|
|
|
|
const Point3F postTickPosition = preTickPosition + ( preTickVelocity * TickSec );
|
|
|
|
|
const VectorF postTickVector = postTickPosition - preTickPosition;
|
|
|
|
|
|
|
|
|
|
// Construct Scaled Box.
|
|
|
|
|
Box3F scaledBox = mObject->getObjBox();
|
|
|
|
|
scaledBox.minExtents.convolve( mObject->getScale() );
|
|
|
|
|
scaledBox.maxExtents.convolve( mObject->getScale() );
|
|
|
|
|
|
|
|
|
|
// Setup Polyherdron.
|
|
|
|
|
MatrixF collisionMatrix( true );
|
|
|
|
|
collisionMatrix.setPosition( preTickPosition );
|
|
|
|
|
sBoxPolyhedron.buildBox( collisionMatrix, scaledBox );
|
|
|
|
|
|
|
|
|
|
// Setup Extruded Poly List.
|
|
|
|
|
sExtrudedPolyList.extrude( sBoxPolyhedron, postTickVector );
|
|
|
|
|
sExtrudedPolyList.setVelocity( preTickVelocity );
|
|
|
|
|
sExtrudedPolyList.setCollisionList( &sCollisionList );
|
|
|
|
|
|
|
|
|
|
// Construct World Convex Box & Adjust for Sweep.
|
|
|
|
|
Box3F convexBox = scaledBox;
|
|
|
|
|
getTransform().mul( convexBox );
|
|
|
|
|
convexBox.minExtents += postTickVector;
|
|
|
|
|
convexBox.maxExtents += postTickVector;
|
|
|
|
|
|
|
|
|
|
// Determine the Collision Mask.
|
|
|
|
|
const U32 collisionMask = ( isInWater() ) ? ( sGroundCollisionMask | sMoveCollisionMask ) : sMoveCollisionMask;
|
|
|
|
|
|
|
|
|
|
// Build List of Contacts.
|
|
|
|
|
CollisionWorkingList &rList = mConvex.getWorkingList();
|
|
|
|
|
for ( CollisionWorkingList *pList = rList.wLink.mNext; pList != &rList; pList = pList->wLink.mNext )
|
|
|
|
|
{
|
|
|
|
|
Convex *convexShape = pList->mConvex;
|
|
|
|
|
|
|
|
|
|
// Valid Collision Target?
|
|
|
|
|
if ( !( convexShape->getObject()->getTypeMask() & collisionMask ) )
|
|
|
|
|
{
|
|
|
|
|
// No, Continue.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Overlap?
|
|
|
|
|
const Box3F &collisionConvexBox = convexShape->getBoundingBox();
|
|
|
|
|
if ( convexBox.isOverlapped( collisionConvexBox ) )
|
|
|
|
|
{
|
|
|
|
|
// Build Contact Information.
|
|
|
|
|
convexShape->getPolyList( &sExtrudedPolyList );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Valid Collision?
|
|
|
|
|
if ( sCollisionList.getCount() == 0 || sCollisionList.getTime() > 1.f )
|
|
|
|
|
{
|
|
|
|
|
// No, Quit Now.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use First Collision.
|
|
|
|
|
Collision *collision = &sCollisionList[0];
|
|
|
|
|
|
|
|
|
|
// More Collisions?
|
|
|
|
|
if ( sCollisionList.getCount() > 1 )
|
|
|
|
|
{
|
|
|
|
|
// Check for Better Contacts.
|
|
|
|
|
for ( Collision *cp = ( collision + 1 ); cp != ( collision + sCollisionList.getCount() ); cp++ )
|
|
|
|
|
{
|
|
|
|
|
if ( cp->faceDot > collision->faceDot )
|
|
|
|
|
{
|
|
|
|
|
// Use this One.
|
|
|
|
|
collision = cp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Store Reference.
|
|
|
|
|
pCollision = collision;
|
|
|
|
|
|
|
|
|
|
// Valid Collision.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::solveCollision( pCollision );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::solveCollision( Collision *pCollision )
|
|
|
|
|
{
|
|
|
|
|
// Fetch Velocity.
|
|
|
|
|
VectorF velocity = getVelocity();
|
|
|
|
|
// Resolve Collision.
|
|
|
|
|
velocity -= ( pCollision->normal * mDot( getVelocity(), pCollision->normal ) );
|
|
|
|
|
|
|
|
|
|
// Pathing?
|
|
|
|
|
if ( isPathing() )
|
|
|
|
|
{
|
|
|
|
|
// Clear X & Y Velocity Adjustments.
|
|
|
|
|
// Note: This means that any collisions made during pathing will not
|
|
|
|
|
// be solved, unless they only affect Z position. It is up to the
|
|
|
|
|
// user to construct Paths which avoid obsticles!
|
|
|
|
|
velocity.x = velocity.y = 0.f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set Velocity.
|
|
|
|
|
setVelocity( velocity );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Update Methods
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::onActorEvent( pEvent );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::onActorEvent( const VActor::eEventType &pEvent )
|
|
|
|
|
{
|
|
|
|
|
switch( pEvent )
|
|
|
|
|
{
|
|
|
|
|
case VActor::k_MountEvent :
|
|
|
|
|
{
|
|
|
|
|
// Set Control State.
|
|
|
|
|
setControlState( k_PathControlState );
|
|
|
|
|
|
|
|
|
|
// Store Path.
|
|
|
|
|
mMountedPath = dynamic_cast<VPath*>( mObject->getObjectMount() );
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case VActor::k_UnmountEvent :
|
|
|
|
|
{
|
|
|
|
|
// Clear Control State.
|
|
|
|
|
clearControlState( k_PathControlState );
|
|
|
|
|
|
|
|
|
|
// Clear Path.
|
|
|
|
|
mMountedPath = NULL;
|
|
|
|
|
// Clear X & Y Velocity.
|
|
|
|
|
setVelocity( VectorF( 0.f, 0.f, mVelocity.z ) );
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::packUpdate( pConnection, pMask, pStream );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
U32 VActorPhysicsController::packUpdate( NetConnection *pConnection, U32 pMask, BitStream *pStream )
|
|
|
|
|
{
|
|
|
|
|
// Return Mask.
|
|
|
|
|
U32 retMask = 0;
|
|
|
|
|
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !pStream->writeFlag( isValidObject() ) )
|
|
|
|
|
{
|
|
|
|
|
return retMask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write Move?
|
|
|
|
|
const bool writeMove = ( pMask & VActor::MoveMask ) && !isPathing();
|
|
|
|
|
if ( pStream->writeFlag( writeMove ) )
|
|
|
|
|
{
|
|
|
|
|
// Write Position.
|
|
|
|
|
const Point3F &position = getPosition();
|
|
|
|
|
pStream->write( position.x );
|
|
|
|
|
pStream->write( position.y );
|
|
|
|
|
pStream->write( position.z );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retMask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// VActorPhysicsController::unpackUpdate( pConnection, pStream );
|
|
|
|
|
//
|
|
|
|
|
// ...
|
|
|
|
|
//
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void VActorPhysicsController::unpackUpdate( NetConnection *pConnection, BitStream *pStream )
|
|
|
|
|
{
|
|
|
|
|
// Valid Object?
|
|
|
|
|
if ( !pStream->readFlag() )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read Move?
|
|
|
|
|
if ( pStream->readFlag() )
|
|
|
|
|
{
|
|
|
|
|
// Read Position.
|
|
|
|
|
Point3F position;
|
|
|
|
|
pStream->read( &position.x );
|
|
|
|
|
pStream->read( &position.y );
|
|
|
|
|
pStream->read( &position.z );
|
|
|
|
|
|
|
|
|
|
// Apply.
|
|
|
|
|
setPosition( position );
|
|
|
|
|
}
|
2020-05-11 20:53:14 +00:00
|
|
|
}
|