123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278 |
- //-----------------------------------------------------------------------------
- // 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 ),
- mGravity( 0.f, 0.f, -9.8f ),
- mOnGround(false)
- {
- // 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 );
- }
- }
|