diff options
Diffstat (limited to 'tools/worldbuilder/code/gameengine/gameengine.cpp')
-rw-r--r-- | tools/worldbuilder/code/gameengine/gameengine.cpp | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/tools/worldbuilder/code/gameengine/gameengine.cpp b/tools/worldbuilder/code/gameengine/gameengine.cpp new file mode 100644 index 0000000..6aedada --- /dev/null +++ b/tools/worldbuilder/code/gameengine/gameengine.cpp @@ -0,0 +1,749 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: GameEngine.cpp +// +// Description: Implement GameEngine +// +// History: 19/07/2002 + Created -- Cary Brisebois +// +//============================================================================= + +//======================================== +// System Includes +//======================================== + +#ifdef WORLD_BUILDER +#include "main/toolhack.h" +#endif + +#include <assert.h> +#include <tlmatrix.hpp> +#include <tlpoint.hpp> +#include <p3d/pointcamera.hpp> + +//======================================== +// Project Includes +//======================================== +#include "GameEngine.h" +#include "nodes/railcamlocatornode.h" +#include "nodes/staticcameralocatornode.h" +#include "nodes/fovlocatornode.h" +#include "nodes/splinelocatornode.h" +#include "nodes/triggervolumenode.h" +#include "nodes/staticcameralocatornode.h" +#include "..\..\..\game\code\meta\recttriggervolume.h" +#include "..\..\..\game\code\meta\spheretriggervolume.h" +#include "..\..\..\game\code\meta\triggervolume.h" +#include "utility\mext.h" +#include "utility\glext.h" +#include "main\constants.h" +#include "wbcamtarget.h" + +#include "..\..\..\game\code\camera\railcam.h" +#include "..\..\..\game\code\camera\staticcam.h" +#include "utility/transformmatrix.h" + +#include <radtime.hpp> + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** +GameEngine* GameEngine::mInstance = NULL; + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================= +// GameEngine::CreateInstance +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GameEngine::CreateInstance() +{ + assert( mInstance == NULL ); + + mInstance = new GameEngine(); +} + +//============================================================================= +// GameEngine::DestroyInstance +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: void +// +//============================================================================= +void GameEngine::DestroyInstance() +{ + assert( mInstance ); + + delete mInstance; + mInstance = NULL; +} + +//============================================================================= +// GameEngine::GetInstance +//============================================================================= +// Description: Comment +// +// Parameters: () +// +// Return: GameEngine +// +//============================================================================= +GameEngine* GameEngine::GetInstance() +{ + return mInstance; +} + +//============================================================================= +// GameEngine::UpdateRailCam +//============================================================================= +// Description: Comment +// +// Parameters: ( MObject& railCam ) +// +// Return: void +// +//============================================================================= +void GameEngine::UpdateRailCam( MObject& railCamObj ) +{ + MStatus status; + + MFnDependencyNode fnDepNode ( railCamObj ); + + MPlug activePlug = fnDepNode.findPlug( RailCamLocatorNode::sActive, &status ); + assert( status ); + + bool active = false; + activePlug.getValue( active ); + + //Test to see if this is active. + if ( active ) + { + MString targetName; + fnDepNode.findPlug( RailCamLocatorNode::sTarget, &status ).getValue( targetName ); + assert( status ); + + //Test to see if this has a target... + if ( targetName.length() != 0 ) + { + MDagPath targetPath; + MObject targetObj; + if ( !MExt::FindDagNodeByName( &targetPath, targetName ) ) + { + //The target does not exist... + return; + } + + targetObj = targetPath.node(); + + RailCam* railCam = dynamic_cast<RailCamLocatorNode*>(fnDepNode.userNode())->GetRailCam(); + assert( railCam ); + + WBCamTarget* target = dynamic_cast<RailCamLocatorNode*>(fnDepNode.userNode())->GetTarget(); + assert( target ); + + target->SetTarget( targetObj ); + + rmt::Vector position; + target->GetPosition( &position ); + + //Get the spline locator (it has the triggers) + MPlug railPlug = fnDepNode.findPlug( MString( "message" ), &status ); + assert( status ); + + MPlugArray targets; + railPlug.connectedTo( targets, false, true, &status ); + assert( status ); + + assert( targets.length() == 1 ); + if ( targets.length() != 1 ) + { + return; + } + + MObject splineLoc = targets[0].node(); + + MFnDependencyNode splineFNDepNode( splineLoc ); + MPlug triggersPlug = splineFNDepNode.findPlug( SplineLocatorNode::sTriggers, &status ); + assert( status ); + + MPlugArray sources; + MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false ); + + unsigned int i; + for ( i = 0; i < sources.length(); ++i ) + { + //Test to see if the target is in a trigger volume for this + //Test against all triggers... + MFnDependencyNode triggerFNDepNode( sources[i].node() ); + int type = 0; + triggerFNDepNode.findPlug( TriggerVolumeNode::sType, &status ).getValue( type ); + assert( status ); + + bool inside = false; + + tlMatrix mat; + tlPoint scale; + TriggerVolumeNode::GetScaleAndMatrix( sources[i].node(), mat, scale ); + + switch ( type ) + { + case TriggerVolumeNode::RECTANGLE: + { + RectTriggerVolume* trigVol = new RectTriggerVolume( mat.GetRow( 3 ), + mat.GetRow( 0 ), + mat.GetRow( 1 ), + mat.GetRow( 2 ), + scale.x, + scale.y, + scale.z ); + + inside = trigVol->Contains( position ); + + trigVol->Release(); + } + break; + case TriggerVolumeNode::SPHERE: + { + SphereTriggerVolume* trigVol = new SphereTriggerVolume( mat.GetRow( 3 ), scale.x ); + + inside = trigVol->Contains( position ); + + trigVol->Release(); + } + break; + default: + assert( false ); + } + + if ( inside ) + { + //If the object is in a trigger volume update the camera and set + //the new position of the railCam + + //We need to give it the splinecurve. + MPlug splineCurvePlug = fnDepNode.findPlug( RailCamLocatorNode::sRail, &status ); + assert( status ); + + MPlugArray splines; + splineCurvePlug.connectedTo( splines, true, false, &status ); + assert( status ); + + assert( splines.length() == 1 ); + if ( splines.length() != 1 ) + { + //Something has deleted the spline. + return; + } + + MFnDependencyNode splineCurveFNDepNode( splines[0].node() ); + + MDagPath splineCurvePath; + bool found = MExt::FindDagNodeByName( &splineCurvePath, splineCurveFNDepNode.name() ); + assert( found ); + + MFnNurbsCurve fnNurbsCurve( splineCurvePath, &status ); + assert( status ); + + MPointArray cvs; + fnNurbsCurve.getCVs( cvs, MSpace::kWorld ); + + railCam->SetNumCVs( cvs.length() ); + + unsigned int cvCount; + for ( cvCount = 0; cvCount < cvs.length(); ++cvCount ) + { + float x, y, z; + + x = cvs[cvCount].x / WBConstants::Scale; + y = cvs[cvCount].y / WBConstants::Scale; + z = -cvs[cvCount].z / WBConstants::Scale; + + rmt::Vector point( x, y, z ); + + railCam->SetVertex( cvCount, point ); + } + + railCam->SetTarget( target ); + + + //Test for FOV changes. + UpdateFOV( railCam, position ); + + UpdateRailSettings( railCam, railCamObj ); + + railCam->Update( 16 ); + + rmt::Vector newPos; + railCam->GetCamera()->GetPosition( &newPos ); + rmt::Vector newTarg; + railCam->GetCamera()->GetTarget( &newTarg ); + rmt::Vector newVUp; + railCam->GetCamera()->GetVUp( &newVUp ); + float fov, aspect; + railCam->GetCamera()->GetFOV( &fov, &aspect ); + + mMayaCam->Set( newPos, newTarg, newVUp, rmt::RadianToDeg(fov) ); + + MPoint newPoint; + newPoint.x = newPos.x * WBConstants::Scale; + newPoint.y = newPos.y * WBConstants::Scale; + newPoint.z = -newPos.z * WBConstants::Scale; + + MExt::SetWorldPosition( newPoint, railCamObj ); + + //Get out of the loop. + break; + } + } + } + } +} + + +//============================================================================= +// GameEngine::UpdateStaticCam +//============================================================================= +// Description: Comment +// +// Parameters: ( MObject& staticCam ) +// +// Return: void +// +//============================================================================= +void GameEngine::UpdateStaticCam( MObject& staticCamObj ) +{ + MStatus status; + + MFnDependencyNode fnDepNode ( staticCamObj ); + + MPlug activePlug = fnDepNode.findPlug( StaticCameraLocatorNode::sActive, &status ); + assert( status ); + + bool active = false; + activePlug.getValue( active ); + + //Test to see if this is active. + if ( active ) + { + bool tracking = false; + fnDepNode.findPlug( StaticCameraLocatorNode::sTracking, &status ).getValue( tracking ); + assert( status ); + + MString targetName; + fnDepNode.findPlug( StaticCameraLocatorNode::sTarget, &status ).getValue( targetName ); + assert( status ); + + //Test to see if this has a target... + if ( targetName.length() != 0 ) + { + MDagPath targetPath; + MObject targetObj; + if ( !MExt::FindDagNodeByName( &targetPath, targetName ) ) + { + //The target does not exist... + return; + } + + //Now we have a target to test for being in the cameras trigger volume + targetObj = targetPath.node(); + + StaticCam* staticCam = reinterpret_cast<StaticCameraLocatorNode*>(fnDepNode.userNode())->GetStaticCam(); + assert( staticCam ); + + WBCamTarget* target = reinterpret_cast<StaticCameraLocatorNode*>(fnDepNode.userNode())->GetTarget(); + assert( target ); + + target->SetTarget( targetObj ); + + rmt::Vector position; + target->GetPosition( &position ); + + //Test the trigger volumes + MPlug triggersPlug = fnDepNode.findPlug( StaticCameraLocatorNode::sTriggers, &status ); + assert( status ); + + MPlugArray sources, targets; + MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false ); + + unsigned int i; + for ( i = 0; i < sources.length(); ++i ) + { + //Test to see if the target is in a trigger volume for this + //Test against all triggers... + MFnDependencyNode triggerFNDepNode( sources[i].node() ); + int type = 0; + triggerFNDepNode.findPlug( TriggerVolumeNode::sType, &status ).getValue( type ); + assert( status ); + + bool inside = false; + + tlMatrix mat; + tlPoint scale; + TriggerVolumeNode::GetScaleAndMatrix( sources[i].node(), mat, scale ); + + switch ( type ) + { + case TriggerVolumeNode::RECTANGLE: + { + RectTriggerVolume* trigVol = new RectTriggerVolume( mat.GetRow( 3 ), + mat.GetRow( 0 ), + mat.GetRow( 1 ), + mat.GetRow( 2 ), + scale.x, + scale.y, + scale.z ); + + inside = trigVol->Contains( position ); + + trigVol->Release(); + } + break; + case TriggerVolumeNode::SPHERE: + { + SphereTriggerVolume* trigVol = new SphereTriggerVolume( mat.GetRow( 3 ), scale.x ); + + inside = trigVol->Contains( position ); + + trigVol->Release(); + } + break; + default: + assert( false ); + } + + if ( inside ) + { + //If the object is in a trigger volume update the camera and set + //the new position of the static cam + + staticCam->SetTarget( target ); + + + //Test for FOV changes. + UpdateFOV( staticCam, position ); + + UpdateStaticCamSettings( staticCam, staticCamObj ); + + staticCam->Update( 16 ); + + rmt::Vector newPos; + staticCam->GetCamera()->GetPosition( &newPos ); + rmt::Vector newTarg; + staticCam->GetCamera()->GetTarget( &newTarg ); + rmt::Vector newVUp; + staticCam->GetCamera()->GetVUp( &newVUp ); + float fov, aspect; + staticCam->GetCamera()->GetFOV( &fov, &aspect ); + + mMayaCam->Set( newPos, newTarg, newVUp, rmt::RadianToDeg(fov) ); + + MPoint newPoint; + newPoint.x = newPos.x * WBConstants::Scale; + newPoint.y = newPos.y * WBConstants::Scale; + newPoint.z = -newPos.z * WBConstants::Scale; + + MExt::SetWorldPosition( newPoint, staticCamObj ); + + //Get out of the loop. + break; + } + } + } + } +} + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================== +// GameEngine::GameEngine +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +GameEngine::GameEngine() : + mTimeStart(0) +{ + mMayaCam = new MayaCamera(); +} + +//============================================================================== +// GameEngine::~GameEngine +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +GameEngine::~GameEngine() +{ + Init(); + + delete mMayaCam; +} + +void GameEngine::Init() +{ +} + +//============================================================================= +// GameEngine::UpdateRailSettings +//============================================================================= +// Description: Comment +// +// Parameters: ( RailCam* railCam, MObject obj ) +// +// Return: void +// +//============================================================================= +void GameEngine::UpdateRailSettings( RailCam* railCam, MObject obj ) +{ + MFnDependencyNode fnDepNode( obj ); + + int behav; + fnDepNode.findPlug( RailCamLocatorNode::sBehaviour).getValue( behav ); + railCam->SetBehaviour( (RailCam::Behaviour)(behav) ); + + float minRad; + fnDepNode.findPlug( RailCamLocatorNode::sMinRadius ).getValue( minRad ); + railCam->SetMinRadius( minRad ); + + float maxRad; + fnDepNode.findPlug( RailCamLocatorNode::sMaxRadius ).getValue( maxRad ); + railCam->SetMaxRadius( maxRad ); + + bool trackRail; + fnDepNode.findPlug( RailCamLocatorNode::sTrackRail ).getValue( trackRail ); + railCam->SetTrackRail( trackRail ); + + float trackDist; + fnDepNode.findPlug( RailCamLocatorNode::sTrackDist ).getValue( trackDist ); + railCam->SetTrackDist( trackDist ); + + bool reverse; + fnDepNode.findPlug( RailCamLocatorNode::sReverseSense ).getValue( reverse ); + railCam->SetReverseSense( reverse ); + + float fov; + fnDepNode.findPlug( RailCamLocatorNode::sFOV ).getValue( fov ); + railCam->SetFOV( rmt::DegToRadian(fov) ); + + float x, y, z; + fnDepNode.findPlug( RailCamLocatorNode::sFacingOffset ).child(0).getValue( x ); + fnDepNode.findPlug( RailCamLocatorNode::sFacingOffset ).child(1).getValue( y ); + fnDepNode.findPlug( RailCamLocatorNode::sFacingOffset ).child(2).getValue( z ); + railCam->SetTargetOffset( rmt::Vector( x, y, z ) ); + + //Same with axis play... TODO + + float posLag; + fnDepNode.findPlug( RailCamLocatorNode::sPositionLag ).getValue( posLag ); + railCam->SetPositionLag( posLag ); + + float targLag; + fnDepNode.findPlug( RailCamLocatorNode::sTargetLag ).getValue( targLag ); + railCam->SetTargetLag( targLag ); +} + +//============================================================================= +// GameEngine::UpdateStaticCamSettings +//============================================================================= +// Description: Comment +// +// Parameters: ( StaticCam* staticCam, MObject obj ) +// +// Return: void +// +//============================================================================= +void GameEngine::UpdateStaticCamSettings( StaticCam* staticCam, MObject obj ) +{ + MFnDependencyNode fnDepNode( obj ); + + float fov; + fnDepNode.findPlug( StaticCameraLocatorNode::sFOV ).getValue( fov ); + staticCam->SetFOV( rmt::DegToRadian(fov) ); + + float targLag; + fnDepNode.findPlug( StaticCameraLocatorNode::sTargetLag ).getValue( targLag ); + staticCam->SetTargetLag( targLag ); + + MPoint worldPos; + MExt::GetWorldPosition( &worldPos, obj ); + + rmt::Vector pos; + pos.x = worldPos.x / WBConstants::Scale; + pos.y = worldPos.y / WBConstants::Scale; + pos.z = -worldPos.z / WBConstants::Scale; + + staticCam->SetPosition( pos ); + + bool tracking = false; + fnDepNode.findPlug( StaticCameraLocatorNode::sTracking ).getValue( tracking ); + staticCam->SetTracking( tracking ); + + float x, y, z; + fnDepNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(0).getValue( x ); + fnDepNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(1).getValue( y ); + fnDepNode.findPlug( StaticCameraLocatorNode::sFacingOffset ).child(2).getValue( z ); + + if ( tracking ) + { + staticCam->SetTargetOffset( rmt::Vector( x, y, z ) ); + } + else + { + //Figure out the transformation on the locator node and apply it to the offset. + MObject transform; + MFnDagNode fnDAGNode( obj ); + transform = fnDAGNode.parent( 0 ); + MFnTransform fnTransform( transform ); + + MDagPath dagPath; + MExt::FindDagNodeByName( &dagPath, fnTransform.name() ); + TransformMatrix tm( dagPath ); + + tlMatrix hmatrix; + tm.GetHierarchyMatrixLHS( hmatrix ); + //Make this p3d friendly... + hmatrix.element[3][0]; + hmatrix.element[3][1]; + hmatrix.element[3][2]; + + if ( x == 0 && y == 0 && z == 0 ) + { + z = 1.0f; + } + + tlPoint offset( x, y, z ); + offset = VectorTransform( hmatrix, offset ); + + rmt::Vector targPos = pos; + targPos.Add( offset ); + staticCam->SetTargetOffset( targPos ); + } +} + +//============================================================================= +// GameEngine::UpdateFOV +//============================================================================= +// Description: Comment +// +// Parameters: ( SuperCam* cam, const rmt::Vector position ) +// +// Return: void +// +//============================================================================= +void GameEngine::UpdateFOV( SuperCam* cam, const rmt::Vector position ) +{ + MStatus status; + MItDag dagIt( MItDag::kDepthFirst, MFn::kLocator ); + + bool inside = false; + + while ( !dagIt.isDone() ) + { + MFnDependencyNode fnNode( dagIt.item() ); + if ( fnNode.typeId() == FOVLocatorNode::id ) + { + //This is a FOV locator, let's see if we're in it's trigger volume. + + MPlug triggersPlug = fnNode.findPlug( FOVLocatorNode::sTriggers, &status ); + assert( status ); + + MPlugArray sources, targets; + MExt::ResolveConnections( &sources, &targets, triggersPlug, true, false ); + + unsigned int i; + for ( i = 0; i < sources.length(); ++i ) + { + //Test to see if the target is in a trigger volume for this + //Test against all triggers... + MFnDependencyNode triggerFNDepNode( sources[i].node() ); + int type = 0; + triggerFNDepNode.findPlug( TriggerVolumeNode::sType, &status ).getValue( type ); + assert( status ); + + tlMatrix mat; + tlPoint scale; + TriggerVolumeNode::GetScaleAndMatrix( sources[i].node(), mat, scale ); + + switch ( type ) + { + case TriggerVolumeNode::RECTANGLE: + { + RectTriggerVolume* trigVol = new RectTriggerVolume( mat.GetRow( 3 ), + mat.GetRow( 0 ), + mat.GetRow( 1 ), + mat.GetRow( 2 ), + scale.x, + scale.y, + scale.z ); + + inside = trigVol->Contains( position ); + + trigVol->Release(); + } + break; + case TriggerVolumeNode::SPHERE: + { + SphereTriggerVolume* trigVol = new SphereTriggerVolume( mat.GetRow( 3 ), scale.x ); + + inside = trigVol->Contains( position ); + + trigVol->Release(); + } + break; + default: + assert( false ); + } + + if ( inside ) + { + float fov; + float time; + float rate; + fnNode.findPlug( FOVLocatorNode::sFOV ).getValue( fov ); + fnNode.findPlug( FOVLocatorNode::sTime ).getValue( time ); + fnNode.findPlug( FOVLocatorNode::sRate ).getValue( rate ); + + cam->SetFOVOverride( rmt::DegToRadian( fov ) ); + cam->OverrideFOV( true, time, rate ); + + break; + } + } + } + + dagIt.next(); + } + + if ( !inside ) + { + cam->OverrideFOV( false, 2000, 0.04f ); + } +} |