Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6726 lines
218 KiB
C++
6726 lines
218 KiB
C++
//===========================================================================//
|
|
// File: l4vidrnd.cpp //
|
|
// Project: MUNGA Brick: Video Renderer Manager //
|
|
// Contents: Interface specification Video Renderer Manager //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 07/08/95 GAC Took renderables out of l4video and moved them here //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <mungal4.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(L4VIDRND_HPP)
|
|
# include <l4vidrnd.hpp>
|
|
#endif
|
|
|
|
#if !defined(VECTOR2D_HPP)
|
|
# include <vector2d.hpp>
|
|
#endif
|
|
|
|
#if !defined(MATRIX_HPP)
|
|
# include <matrix.hpp>
|
|
#endif
|
|
|
|
#if !defined(MOVER_HPP)
|
|
# include <mover.hpp>
|
|
#endif
|
|
|
|
#if !defined(PLAYER_HPP)
|
|
# include <player.hpp>
|
|
#endif
|
|
|
|
#if !defined(L4VIDEO_HPP)
|
|
# include <l4video.hpp>
|
|
#endif
|
|
|
|
#if !defined(NTTMGR_HPP)
|
|
# include <nttmgr.hpp>
|
|
#endif
|
|
|
|
#if !defined(l4APP_HPP)
|
|
# include <l4app.hpp>
|
|
#endif
|
|
|
|
#include <dpl.h>
|
|
#include <dpl_2d.h>
|
|
#include <dpl_vpx.h>
|
|
#include <dplutils.h>
|
|
#include <matrix.h>
|
|
|
|
#if defined(TRACE_VIDEO_MECH_CULL_RENDERABLE)
|
|
static BitTrace Video_Mech_Cull_Renderable("Video Mech Cull Renderable");
|
|
#define SET_VIDEO_MECH_CULL_RENDERABLE() Video_Mech_Cull_Renderable.Set()
|
|
#define CLEAR_VIDEO_MECH_CULL_RENDERABLE() Video_Mech_Cull_Renderable.Clear()
|
|
#else
|
|
#define SET_VIDEO_MECH_CULL_RENDERABLE()
|
|
#define CLEAR_VIDEO_MECH_CULL_RENDERABLE()
|
|
#endif
|
|
|
|
//
|
|
// Below allows the use of DPLDelayDCSFlush to be on or off
|
|
//
|
|
#if 1
|
|
# define HACK_DPL_FLUSH_DCS(a)\
|
|
{L4Application *l4_application = Cast_Object(L4Application*, application);\
|
|
Check(l4_application);\
|
|
l4_application->GetVideoRenderer()->DPLDelayDCSFlush(a);}
|
|
# define DPL_FLUSH_DCS(a)\
|
|
{myRenderer->DPLDelayDCSFlush(a);}
|
|
#else
|
|
# define DPL_FLUSH_DCS(a)\
|
|
dpl_FlushDCS(a)
|
|
# define HACK_DPL_FLUSH_DCS(a)\
|
|
dpl_FlushDCS(a)
|
|
#endif
|
|
|
|
//
|
|
// All renderables that need to use "Now()" should use renderer frame time
|
|
// as it should be much quicker (it returns the time at the start of the
|
|
// frame execution. All the renderables should know which renderer they belong
|
|
// to, but since many don't, this macro will supply the time from the default one
|
|
//
|
|
#define GET_CURRENT_FRAME_TIME() \
|
|
{L4Application *l4_application = Cast_Object(L4Application*, application);\
|
|
Check(l4_application);\
|
|
l4_application->GetVideoRenderer()->GetCurrentFrameTime();}
|
|
|
|
//===========================================================================//
|
|
//===========================================================================//
|
|
//===========================================================================//
|
|
//===========================================================================//
|
|
// All the stuff between these big ugly bars is the new video component stuff//
|
|
//===========================================================================//
|
|
//===========================================================================//
|
|
//===========================================================================//
|
|
//===========================================================================//
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~This is a special class to speed up projectiles~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for InnerProjectileRenderable
|
|
//
|
|
InnerProjectileRenderable::InnerProjectileRenderable(
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone // DPL Zone this stuff will live in (for culling)
|
|
):
|
|
Component(TrivialNodeClassID) // Inherited constructor
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
Check_Pointer(this_zone);
|
|
Check_Pointer(graphical_object);
|
|
//
|
|
// Construct the hiearchy the projectile needs to be renderable
|
|
//
|
|
myDCS = dpl_NewDCS ();
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer (myDCS);
|
|
Check_Pointer (myInstance);
|
|
dpl_SetDCSZone (myDCS, this_zone);
|
|
dpl_SetInstanceObject (myInstance, graphical_object);
|
|
dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj );
|
|
dpl_SetInstanceSectMask (myInstance, NULL );
|
|
dpl_SetInstanceVisibility (myInstance, 1 );
|
|
dpl_AddInstanceToDCS (myDCS, myInstance );
|
|
dpl_AddDCSToScene (myDCS );
|
|
dpl_FlushInstance (myInstance);
|
|
dpl_FlushDCS (myDCS);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for InnerProjectileRenderable
|
|
//
|
|
InnerProjectileRenderable::~InnerProjectileRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Delete the instance(s) hanging on the DCS (if any)
|
|
// NOTE: we may want to iterate through all the instances here using DPL routines
|
|
//
|
|
dpl_RemoveInstanceFromDCS(myDCS, myInstance);
|
|
dpl_RemoveDCSFromScene(myDCS);
|
|
dpl_DeleteInstance(myInstance);
|
|
//
|
|
// Delete the DCS
|
|
//
|
|
dpl_DeleteDCS(myDCS);
|
|
myDCS = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the InnerProjectileRenderable
|
|
//
|
|
Logical
|
|
InnerProjectileRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
Component::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check_Pointer(myInstance);
|
|
Check_Pointer(myDCS);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for ProjectileRootRenderable
|
|
//
|
|
ProjectileRootRenderable::ProjectileRootRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone // DPL Zone this stuff will live in (for culling)
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the incoming pointers
|
|
//
|
|
Check_Pointer(graphical_object);
|
|
Check_Pointer(this_zone);
|
|
//
|
|
// Get a projectile renderable we can use
|
|
//
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
myInnerProjectile = l4_application->GetVideoRenderer()->GetProjectile(
|
|
graphical_object,
|
|
this_zone);
|
|
Check(myInnerProjectile);
|
|
//
|
|
// Set the DCS matrix and flush it
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myInnerProjectile->GetDCS());
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = myEntity->localToWorld;
|
|
DPL_FLUSH_DCS ( myInnerProjectile->GetDCS());
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ProjectileRootRenderable
|
|
//
|
|
ProjectileRootRenderable::~ProjectileRootRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// return our inner renderable to the pool
|
|
//
|
|
Point3D infinity(0.0f, 10000.0f, 0.0f);
|
|
float32* tempMatrix = dpl_GetDCSMatrix(myInnerProjectile->GetDCS());
|
|
Check_Pointer (tempMatrix);
|
|
*(Matrix4x4*)tempMatrix = infinity;
|
|
DPL_FLUSH_DCS ( myInnerProjectile->GetDCS() );
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->ReleaseProjectile(myInnerProjectile);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ProjectileRootRenderable
|
|
//
|
|
Logical
|
|
ProjectileRootRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
VideoRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(&oldLocalToWorld);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ProjectileRootRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
ProjectileRootRenderable::Execute()
|
|
{
|
|
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// If our entity has changed it's localToWorld matrix, update DPL
|
|
//
|
|
if(oldLocalToWorld != myEntity->localToWorld)
|
|
{
|
|
oldLocalToWorld = myEntity->localToWorld;
|
|
float32* tempMatrix = dpl_GetDCSMatrix(myInnerProjectile->GetDCS());
|
|
Check_Pointer (tempMatrix);
|
|
*(Matrix4x4*)tempMatrix = oldLocalToWorld;
|
|
DPL_FLUSH_DCS ( myInnerProjectile->GetDCS() );
|
|
}
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLObjectWrapper
|
|
//
|
|
DPLObjectWrapper::DPLObjectWrapper(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
const CString &name, // Name of the DPL object to load into the wrapper
|
|
dpl_LOAD_MODE cache_mode // DPL Zone this stuff will live in (for culling)
|
|
):
|
|
VideoRenderable(entity, DPLObjectWrapper::Static)
|
|
{
|
|
//
|
|
// Check the incoming pointers
|
|
//
|
|
Check(&name);
|
|
//
|
|
// Load the DPL object into the wrapper, try to get the object pointer from
|
|
// the cache, if it isn't there, do a regular load.
|
|
//
|
|
if(cache_mode == dpl_load_nocache)
|
|
{
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
myDPLObject = l4_application->GetVideoRenderer()->GetCachedObject(name);
|
|
if(!myDPLObject)
|
|
{
|
|
myDPLObject = dpl_LoadObject(name, cache_mode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
myDPLObject = dpl_LoadObject(name, cache_mode);
|
|
}
|
|
myCacheMode = cache_mode;
|
|
myDPLObjectName = name;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLObjectWrapper
|
|
//
|
|
DPLObjectWrapper::~DPLObjectWrapper()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Handle the unloading of DPL objects
|
|
//
|
|
if(myCacheMode == dpl_load_nocache)
|
|
{
|
|
//
|
|
// If this object was not cached, we will eventually return it to the video
|
|
// renderer's list of unused uncached objects for later use by someone else
|
|
//
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->PutCachedObject(myDPLObjectName, myDPLObject);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do nothing (should unload the object)
|
|
//
|
|
//dpl_UnloadObject(myDPLObject);
|
|
}
|
|
myDPLObject = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLObjectWrapper
|
|
//
|
|
Logical
|
|
DPLObjectWrapper::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
VideoRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check_Pointer(myDPLObject);
|
|
Check(&myDPLObjectName);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DPLObjectWrapper
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
DPLObjectWrapper::Execute()
|
|
{
|
|
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~New Class Hiearchy for Renderables~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for VideoRenderable
|
|
//
|
|
VideoRenderable::VideoRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type // How/when to execute the renderable
|
|
):
|
|
Component(TrivialNodeClassID) // Inherited constructor
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
Check(entity);
|
|
//
|
|
// Remember the entity and execution type
|
|
//
|
|
myEntity = entity;
|
|
myExecutionType = execution_type;
|
|
//
|
|
// HACK HACK HACK
|
|
// This initializes the video renderable's pointer back to the renderer that
|
|
// owns it so it can get information from that renderer. The renderer pointer
|
|
// really should be passed in as an argument, this is a concession to avoid
|
|
// spending the time to edit all references to the renderer so they support
|
|
// a new argument. This will be fixed later, for now we know there is only
|
|
// on renderer so we grab the application pointer and get the video renderer
|
|
// from it.
|
|
//
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
myRenderer = l4_application->GetVideoRenderer();
|
|
//
|
|
// Register us as static or dynamic
|
|
//
|
|
switch(myExecutionType)
|
|
{
|
|
case Static:
|
|
myEntity->AddStaticVideoComponent(this);
|
|
break;
|
|
case Dynamic:
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
myEntity->AddStaticVideoComponent(this);
|
|
myRenderer->AddDynamicRenderable(this);
|
|
break;
|
|
case Watcher:
|
|
myEntity->AddStaticVideoComponent(this);
|
|
break;
|
|
case Dependant:
|
|
myEntity->AddStaticVideoComponent(this);
|
|
break;
|
|
default:
|
|
Fail("VideoRenderable--Illegal execution type\n");
|
|
break;
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for VideoRenderable
|
|
//
|
|
VideoRenderable::~VideoRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Nothing else to do here
|
|
//
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the VideoRenderable
|
|
//
|
|
Logical
|
|
VideoRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
Component::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(myEntity);
|
|
Check(myRenderer);
|
|
Verify(myExecutionType >= Static && myExecutionType <= Dependant);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the VideoRenderable
|
|
// This method just checks to be sure we are not trying to execute a static
|
|
// renderable, then returns.
|
|
//
|
|
void
|
|
VideoRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Make sure we are not trying to execute a static renderable
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
if(myExecutionType == Static)
|
|
{
|
|
Fail("VideoRenderable--someone executed a STATIC renderable\n");
|
|
}
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the ChildLightRenderable
|
|
//
|
|
// This renderable is used to connect a light as a child of an existing DCS
|
|
// the light isn't setup to move on it's own and creates a DCS only for the
|
|
// purpose of offsetting it from it's parent.
|
|
//
|
|
ChildLightRenderable::ChildLightRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
Scalar red, // light color
|
|
Scalar green,
|
|
Scalar blue,
|
|
Scalar inner_radius,
|
|
Scalar outer_radius,
|
|
dpl_LIGHT_TYPE light_type,
|
|
int light_mask
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check_Pointer(this_zone);
|
|
Check_Pointer(parent_DCS);
|
|
Check(offset_matrix);
|
|
//
|
|
// Remember the interesting parameters
|
|
//
|
|
myZone = this_zone;
|
|
myParentDCS = parent_DCS;
|
|
myOffsetMatrix = *offset_matrix;
|
|
//
|
|
// Create the dpl DCS and the light that we will be using
|
|
//
|
|
myDCS = dpl_NewDCS ();
|
|
myLight = dpl_NewLight();
|
|
Check_Pointer(myDCS);
|
|
Check_Pointer(myLight);
|
|
//
|
|
// Setup light type and color
|
|
//
|
|
dpl_SetLightType (myLight, light_type );
|
|
dpl_SetLightColor (myLight, red, green, blue );
|
|
dpl_SetLightDCS (myLight, myDCS );
|
|
dpl_SetLightRadii (myLight, inner_radius, outer_radius );
|
|
dpl_SetLightLightingMask (myLight, light_mask);
|
|
//
|
|
// Connect the DCS just created to a parent
|
|
//
|
|
dpl_AddDCSToDCS ( myParentDCS, myDCS );
|
|
//
|
|
// Set the DCS into the requested zone for culling
|
|
//
|
|
dpl_SetDCSZone ( myDCS, this_zone );
|
|
//
|
|
// Load up the DCS matrix with the supplied matrix
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix(myDCS);
|
|
Check_Pointer(tempMatrix);
|
|
*(Matrix4x4*)tempMatrix = myOffsetMatrix;
|
|
//
|
|
// Flip the light around to point the correct direction
|
|
//
|
|
// dpl_RotateDCS ( myDCS, 180.0f, dpl_Y );
|
|
//
|
|
// Flush out the instance and DCS
|
|
//
|
|
dpl_FlushLight ( myLight);
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ChildLightRenderable
|
|
//
|
|
ChildLightRenderable::~ChildLightRenderable()
|
|
{
|
|
Check(this);
|
|
dpl_DeleteDCS(myDCS);
|
|
dpl_DeleteLight(myLight);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ChildLightRenderable
|
|
//
|
|
Logical
|
|
ChildLightRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check_Pointer(myDCS);
|
|
Check_Pointer(myParentDCS);
|
|
Check_Pointer(myLight);
|
|
Check(&myOffsetMatrix);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for ChildLightRenderable
|
|
//
|
|
void
|
|
ChildLightRenderable::Execute()
|
|
{
|
|
// This might eventually handle turning the light on and off
|
|
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DCSObjectRenderable
|
|
//
|
|
DCSObjectRenderable::DCSObjectRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask // intersection mask for the object
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
if(graphical_object)
|
|
Check_Pointer(graphical_object); // allowed to be null
|
|
#endif
|
|
Check_Pointer(this_zone);
|
|
//
|
|
// Remember my dpl object, intersect and offset data
|
|
//
|
|
myDPLObject = graphical_object;
|
|
myDPLZone = this_zone;
|
|
myIntersectMode = intersect_mode;
|
|
myIntersectMask = intersect_mask;
|
|
myDCS = NULL;
|
|
myInstance = NULL;
|
|
//
|
|
// We need to construct a DCS node here and remember it. The next class up is
|
|
// expected to handle the flushing and connecting of structure so we just setup
|
|
// the DCS and zone information here, leaving flushing to someone else.
|
|
//
|
|
myDCS = dpl_NewDCS ();
|
|
|
|
Check_Pointer ( myDCS );
|
|
dpl_SetDCSZone ( myDCS, myDPLZone );
|
|
//
|
|
// Construct the instance(s) and hang them on the DCS. Since we may be building
|
|
// more than one instance, we have to take care of flushing them here.
|
|
//
|
|
if(myDPLObject)
|
|
{
|
|
myInstance = dpl_NewInstance();
|
|
|
|
Check_Pointer ( myInstance);
|
|
dpl_SetInstanceObject ( myInstance, myDPLObject);
|
|
dpl_SetInstanceIntersect ( myInstance, myIntersectMode );
|
|
dpl_SetInstanceSectMask ( myInstance, myIntersectMask );
|
|
dpl_SetInstanceVisibility ( myInstance, 1 );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DCSObjectRenderable
|
|
//
|
|
DCSObjectRenderable::~DCSObjectRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Delete the instance(s) hanging on the DCS (if any)
|
|
// NOTE: we may want to iterate through all the instances here using DPL routines
|
|
//
|
|
if(myInstance)
|
|
{
|
|
dpl_RemoveInstanceFromDCS(myDCS, myInstance);
|
|
dpl_DeleteInstance(myInstance);
|
|
}
|
|
//
|
|
// Delete the DCS
|
|
//
|
|
dpl_DeleteDCS(myDCS);
|
|
myDCS = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DCSObjectRenderable
|
|
//
|
|
Logical
|
|
DCSObjectRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
VideoRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
if(myDPLObject)
|
|
Check_Pointer(myDPLObject);
|
|
if(myInstance)
|
|
Check_Pointer(myInstance);
|
|
#endif
|
|
Check_Pointer(myDPLZone);
|
|
Check_Pointer(myDCS);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DCSObjectRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
DCSObjectRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DCSInstanceRenderable
|
|
//
|
|
DCSInstanceRenderable::DCSInstanceRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to connect to the instance
|
|
dpl_DCS *parent_DCS, // the DCS to add the instance to
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
Logical visible // initial visibility setting
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
Check_Pointer(graphical_object);
|
|
Check_Pointer(parent_DCS);
|
|
//
|
|
// Remember my dpl object, intersect and offset data
|
|
//
|
|
myDPLObject = graphical_object;
|
|
myIntersectMode = intersect_mode;
|
|
myIntersectMask = intersect_mask;
|
|
myDCS = parent_DCS;
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer(myInstance);
|
|
//
|
|
// Construct the instance(s) and hang them on the parent DCS
|
|
//
|
|
dpl_SetInstanceObject ( myInstance, myDPLObject);
|
|
dpl_SetInstanceIntersect ( myInstance, myIntersectMode );
|
|
dpl_SetInstanceSectMask ( myInstance, myIntersectMask );
|
|
dpl_SetInstanceVisibility ( myInstance, visible );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DCSInstanceRenderable
|
|
//
|
|
DCSInstanceRenderable::~DCSInstanceRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Disconnect the instance from the DCS and delete the instance
|
|
//
|
|
dpl_RemoveInstanceFromDCS(myDCS, myInstance);
|
|
dpl_DeleteInstance(myInstance);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DCSInstanceRenderable
|
|
//
|
|
Logical
|
|
DCSInstanceRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
VideoRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check_Pointer(myDPLObject);
|
|
Check_Pointer(myInstance);
|
|
Check_Pointer(myDCS);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DCSInstanceRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
DCSInstanceRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for RootRenderable
|
|
//
|
|
RootRenderable::RootRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask // intersection mask for the object
|
|
):
|
|
DCSObjectRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask) // intersection mask for the object
|
|
{
|
|
//
|
|
// All the incoming data will have been checked by DCSObjectRenderable
|
|
// already, so we don't have to check anything locally.
|
|
//
|
|
//
|
|
// Initialize our variables
|
|
//
|
|
oldLocalToWorld = myEntity->localToWorld;
|
|
//
|
|
// Now we finish the work of hooking up and initializing the root renderable
|
|
// Add the DCS to the scene and initialize it's matrix with the localToWorld
|
|
// transformation from our entity
|
|
//
|
|
dpl_AddDCSToScene ( myDCS );
|
|
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = myEntity->localToWorld;
|
|
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for RootRenderable
|
|
//
|
|
RootRenderable::~RootRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Remove the DCS from the scene, deletion of the DCS and it's instances is
|
|
// handled by our parent class.
|
|
//
|
|
dpl_RemoveDCSFromScene(myDCS);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the RootRenderable
|
|
//
|
|
Logical
|
|
RootRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
DCSObjectRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(&oldLocalToWorld);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the RootRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
RootRenderable::Execute()
|
|
{
|
|
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// If our entity has changed it's localToWorld matrix, update DPL
|
|
//
|
|
if(oldLocalToWorld != myEntity->localToWorld)
|
|
{
|
|
oldLocalToWorld = myEntity->localToWorld;
|
|
float32* tempMatrix = dpl_GetDCSMatrix(myDCS);
|
|
Check_Pointer (tempMatrix);
|
|
*(Matrix4x4*)tempMatrix = oldLocalToWorld;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
DCSObjectRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for ChildOffsetRenderable
|
|
//
|
|
ChildOffsetRenderable::ChildOffsetRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix // offset matrix to be applied prior to joint DCS
|
|
):
|
|
DCSObjectRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask) // intersection mask for the object
|
|
{
|
|
//
|
|
// Check incoming data not handled by lower levels
|
|
//
|
|
Check(offset_matrix);
|
|
//
|
|
// Remember my offset matrix
|
|
//
|
|
myOffsetMatrix = *offset_matrix;
|
|
myOffsetDCS = NULL;
|
|
myParentDCS = parent_DCS;
|
|
//
|
|
// We construct the offset DCS node and link the DCS carrying our our
|
|
// graphical instances to it.
|
|
//
|
|
myOffsetDCS = dpl_NewDCS ();
|
|
Check_Pointer ( myOffsetDCS );
|
|
dpl_SetDCSZone ( myDCS, myDPLZone );
|
|
dpl_AddDCSToDCS ( myOffsetDCS, myDCS );
|
|
//
|
|
// Now we connect that DCS to our parent
|
|
//
|
|
dpl_AddDCSToDCS ( myParentDCS, myOffsetDCS);
|
|
//
|
|
// Then fill in the offset DCS and flush it
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myOffsetDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = myOffsetMatrix;
|
|
dpl_FlushDCS ( myOffsetDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ChildOffsetRenderable
|
|
//
|
|
ChildOffsetRenderable::~ChildOffsetRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Delete the connection to our parent DCS
|
|
//
|
|
dpl_RemoveDCSFromDCS(myParentDCS, myOffsetDCS);
|
|
//
|
|
// Delete the static DCS and it's connections to the dynamic one
|
|
//
|
|
dpl_RemoveDCSFromDCS(myOffsetDCS, myDCS);
|
|
dpl_DeleteDCS(myOffsetDCS);
|
|
myOffsetDCS = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ChildOffsetRenderable
|
|
//
|
|
Logical
|
|
ChildOffsetRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
DCSObjectRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check_Pointer(myParentDCS);
|
|
Check_Pointer(myOffsetDCS);
|
|
Check(&myOffsetMatrix);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ChildOffsetRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
ChildOffsetRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
DCSObjectRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for HingeRenderable
|
|
//
|
|
#define SINGLE_AXIS_HINGE True
|
|
|
|
HingeRenderable::HingeRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
const Hinge *my_hinge // Hinge attribute we will use to control the joint
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
//
|
|
// Check the incomming data
|
|
//
|
|
Check(my_hinge);
|
|
//
|
|
// Initialize our variables
|
|
//
|
|
myHinge = my_hinge;
|
|
oldHinge = *my_hinge;
|
|
//
|
|
// Dump the initial value of the hing into the DCS our instances are attached
|
|
// to, then flush it out. We have to copy the hinge to a quaternion because
|
|
// the math library doesn't support direct assignment of hing to matrix yet.
|
|
//
|
|
#if SINGLE_AXIS_HINGE
|
|
SinCosPair
|
|
temp_sin_cos_pair;
|
|
temp_sin_cos_pair = myHinge->rotationAmount;
|
|
switch(myHinge->axisNumber)
|
|
{
|
|
case X_Axis:
|
|
dpl_SetDCSXAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine);
|
|
break;
|
|
case Y_Axis:
|
|
dpl_SetDCSYAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine);
|
|
break;
|
|
case Z_Axis:
|
|
dpl_SetDCSZAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine);
|
|
break;
|
|
}
|
|
#else
|
|
Quaternion
|
|
temp_quaternion;
|
|
float32
|
|
*temp_matrix;
|
|
temp_matrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( temp_matrix );
|
|
temp_quaternion = oldHinge;
|
|
*(Matrix4x4*)temp_matrix = temp_quaternion;
|
|
#endif
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for HingeRenderable
|
|
//
|
|
HingeRenderable::~HingeRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the HingeRenderable
|
|
//
|
|
Logical
|
|
HingeRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
ChildOffsetRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(myHinge);
|
|
Check(&oldHinge);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the HingeRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
HingeRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// If the hinge we're watching has changed, update our matrix
|
|
//
|
|
if(oldHinge != *myHinge)
|
|
{
|
|
oldHinge = *myHinge;
|
|
#if SINGLE_AXIS_HINGE
|
|
SinCosPair
|
|
temp_sin_cos_pair;
|
|
temp_sin_cos_pair = myHinge->rotationAmount;
|
|
switch(myHinge->axisNumber)
|
|
{
|
|
case X_Axis:
|
|
dpl_SetDCSXAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine);
|
|
break;
|
|
case Y_Axis:
|
|
dpl_SetDCSYAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine);
|
|
break;
|
|
case Z_Axis:
|
|
dpl_SetDCSZAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine);
|
|
break;
|
|
}
|
|
#else
|
|
Quaternion
|
|
temp_quaternion;
|
|
float32
|
|
*temp_matrix;
|
|
temp_matrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( temp_matrix );
|
|
temp_quaternion = oldHinge;
|
|
*(Matrix4x4*)temp_matrix = temp_quaternion;
|
|
#endif
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for BallJointRenderable
|
|
//
|
|
BallJointRenderable::BallJointRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
const EulerAngles *my_euler // Euler angles to control rotation of the ball joint
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
float32
|
|
*temp_matrix;
|
|
//
|
|
// Check the incomming data
|
|
//
|
|
Check(my_euler);
|
|
//
|
|
// Initialize our variables
|
|
//
|
|
myEuler = my_euler;
|
|
oldEuler = *my_euler;
|
|
//
|
|
// Dump the initial value of the euler angles into the DCS our instances are attached
|
|
// to, then flush it out.
|
|
//
|
|
temp_matrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( temp_matrix );
|
|
*(Matrix4x4*)temp_matrix = oldEuler;
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for BallJointRenderable
|
|
//
|
|
BallJointRenderable::~BallJointRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the BallJointRenderable
|
|
//
|
|
Logical
|
|
BallJointRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
ChildOffsetRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(myEuler);
|
|
Check(&oldEuler);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the BallJointRenderable
|
|
//
|
|
void
|
|
BallJointRenderable::Execute()
|
|
{
|
|
float32
|
|
*temp_matrix;
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// If the hinge we're watching has changed, update our matrix
|
|
//
|
|
if(oldEuler != *myEuler)
|
|
{
|
|
oldEuler = *myEuler;
|
|
temp_matrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( temp_matrix );
|
|
*(Matrix4x4*)temp_matrix = oldEuler;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for BallTranslateJointRenderable
|
|
//
|
|
BallTranslateJointRenderable::BallTranslateJointRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
const EulerAngles *my_euler, // Euler angles to control rotation of the ball joint
|
|
const Point3D *my_translation // offset for the translation part of the joint
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
AffineMatrix
|
|
tempAffine(True);
|
|
|
|
float32
|
|
*temp_matrix;
|
|
//
|
|
// Check the incomming data
|
|
//
|
|
Check(my_euler);
|
|
Check(my_translation);
|
|
//
|
|
// Initialize our variables
|
|
//
|
|
myEuler = my_euler;
|
|
oldEuler = *my_euler;
|
|
myTranslation = my_translation;
|
|
oldTranslation = *my_translation;
|
|
//
|
|
// Dump the initial value of the euler angles into the DCS our instances are attached
|
|
// to, then flush it out.
|
|
//
|
|
temp_matrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( temp_matrix );
|
|
tempAffine = oldTranslation;
|
|
tempAffine = oldEuler;
|
|
*(Matrix4x4*)temp_matrix = tempAffine;
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for BallTranslateJointRenderable
|
|
//
|
|
BallTranslateJointRenderable::~BallTranslateJointRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the BallTranslateJointRenderable
|
|
//
|
|
Logical
|
|
BallTranslateJointRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
ChildOffsetRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(myEuler);
|
|
Check(&oldEuler);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the BallTranslateJointRenderable
|
|
//
|
|
void
|
|
BallTranslateJointRenderable::Execute()
|
|
{
|
|
float32
|
|
*temp_matrix;
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// If the hinge we're watching has changed, update our matrix
|
|
//
|
|
if(oldEuler != *myEuler || oldTranslation != *myTranslation)
|
|
{
|
|
oldEuler = *myEuler;
|
|
oldTranslation = *myTranslation;
|
|
temp_matrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( temp_matrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine = oldTranslation;
|
|
tempAffine = oldEuler;
|
|
*(Matrix4x4*)temp_matrix = tempAffine;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for SpinScaleQuatRenderable
|
|
//
|
|
SpinScaleQuatRenderable::SpinScaleQuatRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
Quaternion *rotation_quaternion,// rotates the object
|
|
Vector3D *scale_vector, // Scales the object
|
|
Logical *visible, // turns the object on and off
|
|
Scalar z_spin_rate // spins the object about z (radians/frame)
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(rotation_quaternion);
|
|
Check(scale_vector);
|
|
Check_Pointer(visible);
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that offsets it to the correct position.
|
|
//
|
|
myRotationQuaternion = rotation_quaternion;
|
|
myScaleVector = scale_vector;
|
|
myVisible = visible;
|
|
myZSpinRate = z_spin_rate;
|
|
OldVisible = *visible;
|
|
OldZSpin = 0;
|
|
//
|
|
// Setup the dcs matrix to it's initial state
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= (*myScaleVector);
|
|
tempAffine *= (*myRotationQuaternion);
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
dpl_FlushDCS ( myDCS );
|
|
//
|
|
// Set the instance visibility correctly
|
|
//
|
|
dpl_SetInstanceVisibility ( myInstance, OldVisible );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for SpinScaleQuatRenderable
|
|
//
|
|
SpinScaleQuatRenderable::~SpinScaleQuatRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the SpinScaleQuatRenderable
|
|
//
|
|
Logical
|
|
SpinScaleQuatRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
ChildOffsetRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the SpinScaleQuatRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
SpinScaleQuatRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Load up the DCS matrix with the localToWorld matrix from the entity
|
|
// then flush out the new DCS
|
|
//
|
|
if(OldVisible != *myVisible)
|
|
{
|
|
OldVisible = *myVisible;
|
|
dpl_SetInstanceVisibility ( myInstance, OldVisible );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
//
|
|
// If the beam is visible, we have to update it
|
|
//
|
|
if(OldVisible)
|
|
{
|
|
OldZSpin += myZSpinRate;
|
|
if(OldZSpin > TWO_PI)
|
|
OldZSpin -= TWO_PI;
|
|
Hinge temp_hinge(Z_Axis, OldZSpin);
|
|
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
|
|
AffineMatrix tempAffine(True);
|
|
Quaternion temp_quaternion;
|
|
temp_quaternion = temp_hinge;
|
|
tempAffine = temp_quaternion;
|
|
tempAffine *= (*myScaleVector);
|
|
temp_quaternion = *myRotationQuaternion;
|
|
tempAffine *= temp_quaternion;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for POVTranslocateRenderable
|
|
//
|
|
POVTranslocateRenderable::POVTranslocateRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_ZONE *this_zone, // DPL zone the world is in
|
|
dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
StateIndicator *effect_trigger, // State dial we use to control the translocation
|
|
unsigned effect_control_state // State that controls start/end of the effect
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
#define COLLAPSE_TIME 1.0f // Time in seconds for initial collapse
|
|
#define COLLAPSE_START_SCALE 30.0f // Scale factor of the sphere when we start collapse
|
|
#define EXPAND_TIME 1.0f // Time that expansion of the sphere should take
|
|
#define EXPAND_END_SCALE 100.0f // Scale factor of the sphere when expansion ends
|
|
#define ROTATE_RATE (0.5f * (0.01745329222222))
|
|
#define ROTATE_LIMIT (20.0f * (0.01745329222222))
|
|
#define TRANSLATE_RATE 0.2f
|
|
#define TRANSLATE_LIMIT 2.0f
|
|
// HACK HACK HACK this should be removed once red planet is checked out
|
|
if(execution_type != Watcher)
|
|
cout<<"POVTranslocateRenderable wants to be a watcher and isn't!\n";
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check_Pointer(this_zone);
|
|
Check_Pointer(death_zone);
|
|
Check_Pointer(parent_DCS);
|
|
Check(effect_trigger);
|
|
//
|
|
// Remember the entity and DCS this renderable is attached to
|
|
//
|
|
myZone = this_zone;
|
|
myDeathZone = death_zone;
|
|
myParentDCS = parent_DCS;
|
|
myEffectTrigger = effect_trigger;
|
|
myEffectControlState = effect_control_state;
|
|
myState = IdleState;
|
|
myRotateY = 0.0f;
|
|
myRotateYSpeed = TRANSLATE_RATE;
|
|
//
|
|
// Load up the object we're going to use for the translocation
|
|
//
|
|
dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere.bgf", dpl_load_normal );
|
|
Check_Pointer(myTranslocateSphere);
|
|
//
|
|
// Setup a DCS that we can put the sphere on so it can be rotated and scaled
|
|
// around the VTV. Attach the sphere to this DCS but make it invisible.
|
|
//
|
|
myInstance = dpl_NewInstance();
|
|
myDCS = dpl_NewDCS();
|
|
Check_Pointer (myInstance);
|
|
Check_Pointer (myDCS);
|
|
dpl_AddDCSToDCS (myParentDCS, myDCS);
|
|
dpl_SetDCSZone (myDCS, myDeathZone);
|
|
dpl_SetInstanceObject (myInstance, myTranslocateSphere);
|
|
dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj);
|
|
dpl_SetInstanceSectMask (myInstance, NULL);
|
|
dpl_SetInstanceVisibility (myInstance, False);
|
|
dpl_AddInstanceToDCS (myDCS, myInstance);
|
|
dpl_FlushInstance (myInstance);
|
|
dpl_FlushDCS (myDCS);
|
|
//
|
|
// Connect us to the state dial's watcher hook
|
|
//
|
|
myEffectTrigger->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for POVTranslocationRenderable
|
|
//
|
|
POVTranslocateRenderable::~POVTranslocateRenderable()
|
|
{
|
|
Check(this);
|
|
//
|
|
// Disconnect the structure we have setup
|
|
//
|
|
dpl_RemoveDCSFromDCS(myParentDCS, myDCS);
|
|
dpl_RemoveInstanceFromDCS(myDCS,myInstance);
|
|
//
|
|
// Delete the DPL elements we created
|
|
//
|
|
dpl_DeleteInstance(myInstance);
|
|
dpl_DeleteDCS(myDCS);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the POVTranslocateRenderable
|
|
//
|
|
Logical
|
|
POVTranslocateRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
|
|
Check_Pointer(myZone);
|
|
Check_Pointer(myDeathZone);
|
|
Check_Pointer(myParentDCS);
|
|
Check(myEffectTrigger);
|
|
Check_Pointer(myInstance);
|
|
Check_Pointer(myDCS);
|
|
Verify(myState >= IdleState && myState <= ExpandRevealState);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for POVTranslocateRenderable.
|
|
//
|
|
void
|
|
POVTranslocateRenderable::Execute()
|
|
{
|
|
|
|
float32
|
|
*tempMatrix;
|
|
Scalar
|
|
elapsed_time,
|
|
current_time,
|
|
percent_time_left,
|
|
percent_time_used,
|
|
scale_factor;
|
|
unsigned
|
|
current_trigger_state;
|
|
//
|
|
// Get the current state and the current time for later use
|
|
//
|
|
Check(myEffectTrigger);
|
|
current_trigger_state = myEffectTrigger->GetState();
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
//
|
|
// State engine (running off myState) to manage running of the death effect
|
|
//
|
|
// cout<<"POVTranslocateRenderable::Execute\n";
|
|
switch(myState)
|
|
{
|
|
//
|
|
// IdleState waits for a transition in the effect control state and starts
|
|
// the effect state machine when it detects one.
|
|
//
|
|
case IdleState:
|
|
{
|
|
if(current_trigger_state == myEffectControlState)
|
|
{
|
|
myState = InitialCollapseState;
|
|
myCollapseEnd = current_time + COLLAPSE_TIME;
|
|
dpl_SetInstanceVisibility (myInstance, True);
|
|
dpl_FlushInstance (myInstance);
|
|
myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"POVTranslocateRenderable::Going Dynamic\n";
|
|
}
|
|
break;
|
|
}
|
|
//
|
|
// This case handles ending the screen flash when we need to
|
|
//
|
|
case FlashScreenState:
|
|
{
|
|
myState = InitialCollapseState;
|
|
break;
|
|
}
|
|
//
|
|
// InitialCollapseState handles reducing the sphere from its max size down
|
|
// to one over a period of time. We figure the percentage of the time
|
|
// left then multiply it by the size the sphere started at to get the
|
|
// scale factor.
|
|
//
|
|
case InitialCollapseState:
|
|
{
|
|
percent_time_left = (myCollapseEnd - current_time)/COLLAPSE_TIME;
|
|
//
|
|
// See how much time is left in the effect.
|
|
//
|
|
if(percent_time_left <= 0.0f)
|
|
{
|
|
//
|
|
// Time's up! Go to WaitForReincarnate state, force scale factor to
|
|
// 1.0, and turn off the outside world
|
|
//
|
|
scale_factor = 1.0f;
|
|
dpl_SetZoneAllViewsOff (myZone);
|
|
dpl_FlushZone (myZone);
|
|
myCollapseEnd = current_time;
|
|
myState = WaitForReincarnateState;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Recalculate the scale factor based on time left
|
|
//
|
|
scale_factor = (percent_time_left * COLLAPSE_START_SCALE) + 1.0f;
|
|
}
|
|
//
|
|
// Build a scaling identity matrix based on our scale factor
|
|
//
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
//
|
|
// Put the scale matrix into the DCS and flush it.
|
|
//
|
|
tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
DPL_FLUSH_DCS (myDCS);
|
|
break;
|
|
}
|
|
//
|
|
// WaitForReincarnateState waits till we the trigger state switches off
|
|
// then does what we want to get us back into the world.
|
|
//
|
|
case WaitForReincarnateState:
|
|
{
|
|
if(current_trigger_state != myEffectControlState)
|
|
{
|
|
//
|
|
// Switch the world back on, then change states
|
|
//
|
|
dpl_SetZoneAllViewsOn (myZone);
|
|
dpl_FlushZone (myZone);
|
|
myState = ExpandRevealState;
|
|
myCollapseEnd = current_time + EXPAND_TIME;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Mess with the DCS to make the tunnel effect more pronounced
|
|
//
|
|
elapsed_time = current_time - myCollapseEnd;
|
|
Point3D temp_point(
|
|
(cos(elapsed_time * 3.33) * TRANSLATE_LIMIT),
|
|
(sin(elapsed_time * 2.5) * TRANSLATE_LIMIT),
|
|
0.0);
|
|
tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = temp_point;
|
|
DPL_FLUSH_DCS(myDCS);
|
|
}
|
|
break;
|
|
}
|
|
//
|
|
// ExpandRevealState expands the sphere rapidly in size to reveal the world
|
|
// getting rid of the sphere when it hits a maximum size.
|
|
//
|
|
case ExpandRevealState:
|
|
{
|
|
//
|
|
// In case we get killed again while in this state, I watch for
|
|
// a change back into the trigger state and retrigger the
|
|
// effect if it shows up
|
|
//
|
|
if(current_trigger_state == myEffectControlState)
|
|
{
|
|
myState = InitialCollapseState;
|
|
myCollapseEnd = current_time + COLLAPSE_TIME;
|
|
// dpl_SetInstanceVisibility (myInstance, True);
|
|
// dpl_FlushInstance (myInstance);
|
|
// myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"POVTranslocateRenderable::Going Dynamic\n";
|
|
}
|
|
percent_time_used = 1.0f - ((myCollapseEnd - current_time)/EXPAND_TIME);
|
|
if(percent_time_used >= 1.0f)
|
|
{
|
|
dpl_SetInstanceVisibility (myInstance, False);
|
|
dpl_FlushInstance (myInstance);
|
|
myState = IdleState;
|
|
scale_factor = 1.0f;
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
// cout<<"POVTranslocateRenderable::Going Static\n";
|
|
}
|
|
else
|
|
{
|
|
scale_factor = (percent_time_used * EXPAND_END_SCALE) + 1.0f;
|
|
}
|
|
//
|
|
// Build a scaling identity matrix based on our scale factor
|
|
//
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
//
|
|
// Put the scale matrix into the DCS and flush it.
|
|
//
|
|
tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
DPL_FLUSH_DCS (myDCS);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for POVStartEndRenderable This handles the effect we use when
|
|
// the mission begins and ends (different from death)
|
|
//
|
|
POVStartEndRenderable::POVStartEndRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_ZONE *this_zone, // DPL zone the world is in
|
|
dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in
|
|
dpl_VIEW *this_view, // The view containing our eye
|
|
StateIndicator *effect_trigger, // State dial we use to control the translocation
|
|
float red_fog, // Fog color
|
|
float green_fog,
|
|
float blue_fog,
|
|
float near_fog, // The near fog plane
|
|
float far_fog, // The far fog plane
|
|
unsigned start_mission_state, // State that signals start of mission
|
|
unsigned end_mission_state // State that signals end of mission
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
#define FLASH_TIME (0.1f) // Time the screen will stay stark white
|
|
#define FADE_IN_TIME (1.0f) // Time to fade from white to the world
|
|
#define FADE_OUT_TIME (1.0f) // Time to fade to black at the end of the game
|
|
// HACK HACK HACK this should be removed once red planet is checked out
|
|
if(execution_type != Watcher)
|
|
cout<<"POVStartEndRenderable wants to be a watcher and isn't!\n";
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check_Pointer(this_zone);
|
|
Check_Pointer(death_zone);
|
|
Check_Pointer(this_view);
|
|
Check(effect_trigger);
|
|
//
|
|
// Remember the entity and DCS this renderable is attached to
|
|
//
|
|
myZone = this_zone;
|
|
myDeathZone = death_zone;
|
|
myEffectTrigger = effect_trigger;
|
|
myView = this_view;
|
|
myState = WaitForStartState;
|
|
myFogRed = red_fog;
|
|
myFogGreen = green_fog;
|
|
myFogBlue = blue_fog;
|
|
myFogNear = near_fog;
|
|
myFogFar = far_fog;
|
|
myStartMissionState = start_mission_state;
|
|
myEndMissionState = end_mission_state;
|
|
myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting);
|
|
//
|
|
// Connect us to the state dial's watcher hook
|
|
//
|
|
myEffectTrigger->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for POVStartEndRenderable
|
|
//
|
|
POVStartEndRenderable::~POVStartEndRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the POVStartEndRenderable
|
|
//
|
|
Logical
|
|
POVStartEndRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
|
|
Check_Pointer(myZone);
|
|
Check_Pointer(myDeathZone);
|
|
Check(myEffectTrigger);
|
|
Verify(myState >= WaitForStartState && myState <= FadeOutState);
|
|
Verify(myFogRed >= 0.0f && myFogRed <= 1.0f);
|
|
Verify(myFogGreen >= 0.0f && myFogGreen <= 1.0f);
|
|
Verify(myFogBlue >= 0.0f && myFogBlue <= 1.0f);
|
|
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for POVStartEndRenderable.
|
|
//
|
|
void
|
|
POVStartEndRenderable::Execute()
|
|
{
|
|
Scalar
|
|
current_time,
|
|
percent_time_left,
|
|
percent_time_used;
|
|
unsigned
|
|
current_trigger_state;
|
|
//
|
|
// Get the current state and the current time for later use
|
|
//
|
|
Check(myEffectTrigger);
|
|
current_trigger_state = myEffectTrigger->GetState();
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
//
|
|
// State engine (running off myState) to manage running of the death effect
|
|
//
|
|
// cout<<"POVStartEndRenderable::Executing\n";
|
|
switch(myState)
|
|
{
|
|
//
|
|
// WaitForStartState waits for the state that signals the start of the mission
|
|
// then sends the screen to full white by manipulating the fog color and limits.
|
|
//
|
|
case WaitForStartState:
|
|
{
|
|
myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting);
|
|
if(current_trigger_state == myStartMissionState)
|
|
{
|
|
myState = FlashScreenState;
|
|
myStateTimer = current_time + FLASH_TIME;
|
|
dpl_SetViewFog(
|
|
myView,
|
|
dpl_fog_type_pixel_lin,
|
|
1.0,
|
|
1.0,
|
|
1.0,
|
|
0.01,
|
|
0.05 );
|
|
dpl_FlushView(myView);
|
|
myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"POVStartEndRenderable::Going Dynamic\n";
|
|
}
|
|
break;
|
|
}
|
|
//
|
|
// FlashScreenState is a state we park in for a short time so the screen will
|
|
// stay white for more than one frame.
|
|
//
|
|
case FlashScreenState:
|
|
{
|
|
if(myStateTimer <= current_time)
|
|
{
|
|
myStateTimer = current_time + FADE_IN_TIME;
|
|
myState = FadeInState;
|
|
}
|
|
break;
|
|
}
|
|
//
|
|
// FadeInState fades the fog color down from white to what it's supposed to
|
|
// be, while sweeping the fog ranges out to their proper ranges.
|
|
//
|
|
case FadeInState:
|
|
{
|
|
percent_time_left = (myStateTimer - current_time)/FADE_IN_TIME;
|
|
if(percent_time_left <= 0.0f)
|
|
{
|
|
percent_time_left = 0.0f;
|
|
myState = MissionRunningState;
|
|
myRenderer->SetFogStyle(DPLRenderer::updateFogSetting);
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
// cout<<"POVStartEndRenderable::Going Static\n";
|
|
|
|
}
|
|
percent_time_used = 1.0f - percent_time_left;
|
|
myRenderer->GetCurrentFogSettings(
|
|
&myFogRed,
|
|
&myFogGreen,
|
|
&myFogBlue,
|
|
&myFogNear,
|
|
&myFogFar);
|
|
dpl_SetViewFog(
|
|
myView,
|
|
dpl_fog_type_pixel_lin,
|
|
myFogRed + ((1.0f - myFogRed) * percent_time_left),
|
|
myFogGreen + ((1.0f - myFogGreen) * percent_time_left),
|
|
myFogBlue + ((1.0f - myFogBlue) * percent_time_left),
|
|
(myFogNear * percent_time_used) + 0.01f,
|
|
(myFogFar * percent_time_used) + 0.05f);
|
|
dpl_FlushView(myView);
|
|
break;
|
|
}
|
|
//
|
|
// MissionRunningState is where we park while the mission is going on, waiting
|
|
// for the state that signals the end of the game
|
|
//
|
|
case MissionRunningState:
|
|
{
|
|
if(current_trigger_state == myEndMissionState)
|
|
{
|
|
myState = FadeOutState;
|
|
myStateTimer = current_time + FADE_OUT_TIME;
|
|
myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting);
|
|
myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"POVStartEndRenderable::Going Dynamic\n";
|
|
}
|
|
break;
|
|
}
|
|
//
|
|
// FadeOutState handles doing a fade-to-black at the end of the game
|
|
//
|
|
case FadeOutState:
|
|
{
|
|
percent_time_left = (myStateTimer - current_time)/FADE_OUT_TIME;
|
|
if(percent_time_left <= 0.0f)
|
|
{
|
|
myState = WaitForStartState;
|
|
percent_time_left = 0.0f;
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
// cout<<"POVStartEndRenderable::Going Static\n";
|
|
}
|
|
myRenderer->GetCurrentFogSettings(
|
|
&myFogRed,
|
|
&myFogGreen,
|
|
&myFogBlue,
|
|
&myFogNear,
|
|
&myFogFar);
|
|
dpl_SetViewFog(
|
|
myView,
|
|
dpl_fog_type_pixel_lin,
|
|
myFogRed * percent_time_left,
|
|
myFogGreen * percent_time_left,
|
|
myFogBlue * percent_time_left,
|
|
(myFogNear * percent_time_left) + 0.01f,
|
|
(myFogFar * percent_time_left) + 0.05f);
|
|
dpl_FlushView(myView);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the ReticleRenderable
|
|
// This produces a movable crosshair reticle that can be either static or
|
|
// dynamic. If static, it will position the graphic at wherever the reticle
|
|
// points when we construct this.
|
|
//
|
|
ReticleRenderable::ReticleRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Reticle **my_reticle, // points to renderable reticle pointer that points to entity's reticle
|
|
dpl_VIEW *this_view // the view associated with our eye
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
dpl2d_MATRIX
|
|
my_2d_matrix;
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check_Pointer(my_reticle);
|
|
Check_Pointer(*my_reticle);
|
|
Check_Pointer(this_view);
|
|
//
|
|
// Remember the entity that this renderable is attached to
|
|
//
|
|
rendererReticle = my_reticle;
|
|
myReticle = *my_reticle;
|
|
myView = this_view;
|
|
myOldReticlePosition = myReticle->reticlePosition;
|
|
myOldReticleState = myReticle->reticleState;
|
|
//
|
|
// Build a main 2d display list with the reticle graphic in it, this should call
|
|
// a second display list that contains just a position command so only a short
|
|
// display list needs to be remade to move the cursor.
|
|
//
|
|
myReticleDisplayList = dpl2d_NewDisplayList();
|
|
myPositionDisplayList = dpl2d_NewDisplayList();
|
|
dpl2d_OpenDisplayList (myReticleDisplayList, dpl2d_open_mode_clear);
|
|
dpl2d_AddCallDisplayList(myReticleDisplayList, myPositionDisplayList );
|
|
dpl2d_AddFullScreenClipRegion (myReticleDisplayList);
|
|
dpl2d_AddSetColor (myReticleDisplayList, 0.0f, 0.5f, 0.0f);
|
|
dpl2d_AddOpenLines (myReticleDisplayList);
|
|
dpl2d_AddPoint (myReticleDisplayList, -0.08f, 0.0f);
|
|
dpl2d_AddPoint (myReticleDisplayList, -0.02f, 0.0f);
|
|
dpl2d_AddPoint (myReticleDisplayList, 0.02f, 0.0f);
|
|
dpl2d_AddPoint (myReticleDisplayList, 0.08f, 0.0f);
|
|
dpl2d_AddPoint (myReticleDisplayList, 0.0f, -0.08f);
|
|
dpl2d_AddPoint (myReticleDisplayList, 0.0f, -0.02f);
|
|
dpl2d_AddPoint (myReticleDisplayList, 0.0f, 0.02f);
|
|
dpl2d_AddPoint (myReticleDisplayList, 0.0f, 0.08f);
|
|
dpl2d_AddCloseLines (myReticleDisplayList);
|
|
dpl2d_CloseDisplayList (myReticleDisplayList);
|
|
|
|
dpl2d_OpenDisplayList (myPositionDisplayList, dpl2d_open_mode_clear);
|
|
dpl2d_IdMatrix (my_2d_matrix);
|
|
dpl2d_TranslateMatrix (my_2d_matrix, myReticle->reticlePosition.x, myReticle->reticlePosition.y );
|
|
dpl2d_AddSetMatrix (myPositionDisplayList,my_2d_matrix );
|
|
dpl2d_CloseDisplayList (myPositionDisplayList);
|
|
|
|
dpl2d_FlushDisplayList (myReticleDisplayList);
|
|
dpl2d_FlushDisplayList (myPositionDisplayList);
|
|
//
|
|
// If the reticle is turned on bind the display list to our eyepoint
|
|
//
|
|
if(myOldReticleState == Reticle::ReticleOn)
|
|
{
|
|
dpl2d_SetViewDisplayList ( myView, myReticleDisplayList );
|
|
dpl_FlushView ( myView );
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the ReticleRenderable
|
|
//
|
|
ReticleRenderable::~ReticleRenderable()
|
|
{
|
|
//
|
|
// Make sure our structure is still in one piece
|
|
//
|
|
Check(this);
|
|
//
|
|
// Unhook the display list from the view, then delete both lists
|
|
//
|
|
dpl2d_SetViewDisplayList ( myView, NULL );
|
|
dpl_FlushView ( myView );
|
|
dpl2d_DeleteDisplayList(myReticleDisplayList);
|
|
dpl2d_DeleteDisplayList(myPositionDisplayList);
|
|
//
|
|
// Unhook the renderer's pickpoint stuff from this renderable
|
|
//
|
|
*rendererReticle = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLDrawReticleRenderable
|
|
// Not much to check here, the entity and DCS pointers must be valid while
|
|
// the instance is allowed to be NULL
|
|
//
|
|
Logical
|
|
ReticleRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myReticle);
|
|
Check_Pointer(rendererReticle);
|
|
Check_Pointer(myView);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ReticleRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
ReticleRenderable::Execute()
|
|
{
|
|
dpl2d_MATRIX
|
|
my_2d_matrix;
|
|
//
|
|
// See if the reticle state has changed
|
|
//
|
|
if(myOldReticleState != myReticle->reticleState)
|
|
{
|
|
//
|
|
// Send the reticle into the appropriate state
|
|
//
|
|
myOldReticleState = myReticle->reticleState;
|
|
switch(myOldReticleState)
|
|
{
|
|
case Reticle::ReticleOff:
|
|
dpl2d_SetViewDisplayList ( myView, NULL );
|
|
dpl_FlushView ( myView );
|
|
break;
|
|
case Reticle::ReticleOn:
|
|
dpl2d_SetViewDisplayList ( myView, myReticleDisplayList );
|
|
dpl_FlushView ( myView );
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// See if the reticle has moved
|
|
//
|
|
if(myOldReticlePosition != myReticle->reticlePosition)
|
|
{
|
|
myOldReticlePosition = myReticle->reticlePosition;
|
|
//
|
|
// Re-create the display list that positions the reticle
|
|
//
|
|
dpl2d_OpenDisplayList(
|
|
myPositionDisplayList,
|
|
dpl2d_open_mode_clear);
|
|
dpl2d_IdMatrix(my_2d_matrix);
|
|
dpl2d_TranslateMatrix(
|
|
my_2d_matrix,
|
|
myOldReticlePosition.x,
|
|
myOldReticlePosition.y );
|
|
dpl2d_AddSetMatrix(
|
|
myPositionDisplayList,
|
|
my_2d_matrix );
|
|
dpl2d_CloseDisplayList(myPositionDisplayList);
|
|
dpl2d_FlushDisplayList(myPositionDisplayList);
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the CameraShipHUDRenderable
|
|
//
|
|
CameraShipHUDRenderable::CameraShipHUDRenderable(
|
|
Entity *entity,
|
|
ExecutionType execution_type,
|
|
int *player_index,
|
|
Logical *display_ranking_window
|
|
) :
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
Check_Pointer(player_index);
|
|
Check_Pointer(display_ranking_window);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in PlayerName Geometry
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
playerNameObject[0] = dpl_LoadObject("PNAME1.bgf", dpl_load_normal);
|
|
playerNameObject[1] = dpl_LoadObject("PNAME2.bgf", dpl_load_normal);
|
|
playerNameObject[2] = dpl_LoadObject("PNAME3.bgf", dpl_load_normal);
|
|
playerNameObject[3] = dpl_LoadObject("PNAME4.bgf", dpl_load_normal);
|
|
playerNameObject[4] = dpl_LoadObject("PNAME5.bgf", dpl_load_normal);
|
|
playerNameObject[5] = dpl_LoadObject("PNAME6.bgf", dpl_load_normal);
|
|
playerNameObject[6] = dpl_LoadObject("PNAME7.bgf", dpl_load_normal);
|
|
playerNameObject[7] = dpl_LoadObject("PNAME8.bgf", dpl_load_normal);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in Ordinal Rankings Geometry
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ordinalObject[0] = dpl_LoadObject("PLACE1.bgf", dpl_load_normal);
|
|
ordinalObject[1] = dpl_LoadObject("PLACE2.bgf", dpl_load_normal);
|
|
ordinalObject[2] = dpl_LoadObject("PLACE3.bgf", dpl_load_normal);
|
|
ordinalObject[3] = dpl_LoadObject("PLACE4.bgf", dpl_load_normal);
|
|
ordinalObject[4] = dpl_LoadObject("PLACE5.bgf", dpl_load_normal);
|
|
ordinalObject[5] = dpl_LoadObject("PLACE6.bgf", dpl_load_normal);
|
|
ordinalObject[6] = dpl_LoadObject("PLACE7.bgf", dpl_load_normal);
|
|
ordinalObject[7] = dpl_LoadObject("PLACE8.bgf", dpl_load_normal);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize CameraFollowing
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
followedPlayerIndex = player_index;
|
|
oldFollowedPlayerIndex = -1;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create One DCS for a Camera Following Name Bitmap
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
followedNameDCS = dpl_NewDCS();
|
|
followedNameInstance = dpl_NewInstance();
|
|
dpl_ScaleDCS ( followedNameDCS, 0.20f, 0.20f, 1.0f );
|
|
dpl_TranslateDCS ( followedNameDCS, 0.0f, -0.15f, -0.5f );
|
|
dpl_SetDCSIgnoreGeo ( followedNameDCS, 1 );
|
|
dpl_SetDCSTraversal ( followedNameDCS, 0x7 );
|
|
dpl_AddDCSToScene ( followedNameDCS );
|
|
dpl_SetInstanceObject ( followedNameInstance, playerNameObject[0] );
|
|
dpl_AddInstanceToDCS ( followedNameDCS, followedNameInstance );
|
|
dpl_SetInstanceVisibility ( followedNameInstance, 1 );
|
|
dpl_FlushInstance ( followedNameInstance );
|
|
dpl_FlushDCS ( followedNameDCS );
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create One DCS for Camera Following Ordinal Ranking Bitmap
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
followedOrdinalDCS = dpl_NewDCS();
|
|
followedOrdinalInstance = dpl_NewInstance();
|
|
dpl_AddDCSToDCS ( followedNameDCS, followedOrdinalDCS );
|
|
dpl_SetInstanceObject ( followedOrdinalInstance, ordinalObject[0] );
|
|
dpl_AddInstanceToDCS ( followedOrdinalDCS, followedOrdinalInstance );
|
|
dpl_SetDCSIgnoreGeo ( followedOrdinalDCS, 1 );
|
|
dpl_SetDCSTraversal ( followedOrdinalDCS, 0x7 );
|
|
dpl_TranslateDCS ( followedOrdinalDCS, -0.75f, 0.0f, 0.0f );
|
|
dpl_SetInstanceVisibility ( followedOrdinalInstance, 0 );
|
|
dpl_FlushInstance ( followedOrdinalInstance );
|
|
dpl_FlushDCS ( followedOrdinalDCS );
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the Ranking Window
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
displayRankingWindow = display_ranking_window;
|
|
oldDisplayRankingWindow = False;
|
|
|
|
Scalar rank_window_y;
|
|
rank_window_y = 0.16f;
|
|
|
|
rankingWindowDCS = dpl_NewDCS();
|
|
dpl_ScaleDCS ( rankingWindowDCS, 0.12f, 0.12f, 1.0f );
|
|
dpl_TranslateDCS ( rankingWindowDCS, 0.22f, rank_window_y, -0.5f );
|
|
dpl_SetDCSIgnoreGeo ( rankingWindowDCS, 1 );
|
|
dpl_SetDCSTraversal ( rankingWindowDCS, 0x7 );
|
|
dpl_AddDCSToScene ( rankingWindowDCS );
|
|
dpl_FlushDCS ( rankingWindowDCS );
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize the pointer's to the player Ranks
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
playerRank = NULL;
|
|
oldPlayerRank = NULL;
|
|
nameDCS = NULL;
|
|
rankDCS = NULL;
|
|
nameInstance = NULL;
|
|
rankInstance = NULL;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// See How Many Regular Players and CameraShip Players!
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
playerCount = 0;
|
|
Check(application);
|
|
EntityManager *entity_mgr = application->GetEntityManager();
|
|
Check(entity_mgr);
|
|
EntityGroup *player_group = entity_mgr->FindGroup("Players");
|
|
if (player_group)
|
|
{
|
|
Check(player_group);
|
|
ChainIteratorOf<Node*> player_iterator(player_group->groupMembers);
|
|
playerCount = player_iterator.GetSize();
|
|
}
|
|
|
|
EntityGroup *camera_player_group = entity_mgr->FindGroup("CameraPlayers");
|
|
int camera_player_count=0;
|
|
if (camera_player_group)
|
|
{
|
|
Check(player_group);
|
|
ChainIteratorOf<Node*> camera_iterator(camera_player_group->groupMembers);
|
|
camera_player_count = camera_iterator.GetSize();
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Make the Arrays for Ranking the size of regular and cameras players
|
|
// summed up. This is necessary since GameMachineHost type of Camera
|
|
// Ships also have a bitmapIndex!
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (playerCount)
|
|
{
|
|
camera_player_count += playerCount;
|
|
Verify(camera_player_count <= MAX_PLAYER_NAMES);
|
|
playerRank = new (int (*[camera_player_count]));
|
|
Register_Pointer(playerRank);
|
|
Player *active_player;
|
|
if(player_group)
|
|
{
|
|
Check(player_group);
|
|
ChainIteratorOf<Node*> player_iterator(player_group->groupMembers);
|
|
while ((active_player = (Player*) player_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// PlayerRank Array indexed by bitmapIndex
|
|
// holds that player's ranking
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(active_player);
|
|
Verify(
|
|
active_player->playerBitmapIndex > 0
|
|
&& active_player->playerBitmapIndex <= MAX_PLAYER_NAMES
|
|
);
|
|
playerRank[active_player->playerBitmapIndex - 1] =
|
|
&active_player->playerRanking ;
|
|
}
|
|
}
|
|
if (camera_player_group)
|
|
{
|
|
ChainIteratorOf<Node*> camera_iterator(camera_player_group->groupMembers);
|
|
while ((active_player = (Player*) camera_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// PlayerRank Array indexed by bitmapIndex
|
|
// holds that player's ranking
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(active_player);
|
|
Verify(
|
|
active_player->playerBitmapIndex > 0
|
|
&& active_player->playerBitmapIndex <= MAX_PLAYER_NAMES
|
|
);
|
|
playerRank[active_player->playerBitmapIndex - 1] =
|
|
&active_player->playerRanking ;
|
|
}
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize OldPlayerRank
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
oldPlayerRank = new int[camera_player_count];
|
|
Register_Pointer(oldPlayerRank);
|
|
|
|
int ii;
|
|
for(ii=0; ii<camera_player_count; ++ii)
|
|
{
|
|
oldPlayerRank[ii] = -1;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Only Create Name and Rank DCS's for Regular players
|
|
// CameraShip Players do not have a score and thus are not
|
|
// displayed
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Allocate memory for all the DCS's
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
nameDCS = new (dpl_DCS (*[playerCount]));
|
|
Register_Pointer(nameDCS);
|
|
rankDCS = new (dpl_DCS (*[playerCount]));
|
|
Register_Pointer(rankDCS);
|
|
nameInstance = new (dpl_INSTANCE (*[playerCount]));
|
|
Register_Pointer(nameInstance);
|
|
rankInstance = new (dpl_INSTANCE (*[playerCount]));
|
|
Register_Pointer(rankInstance);
|
|
|
|
Scalar delta_y;
|
|
|
|
for( ii = 0; ii < playerCount ; ++ii)
|
|
{
|
|
delta_y = -(ii * 0.24);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create one DCS for a Name Bitmap
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
nameDCS[ii] = dpl_NewDCS();
|
|
nameInstance[ii] = dpl_NewInstance();
|
|
dpl_AddDCSToDCS ( rankingWindowDCS, nameDCS[ii] );
|
|
dpl_SetInstanceObject ( nameInstance[ii], playerNameObject[ii] );
|
|
dpl_SetDCSIgnoreGeo ( nameDCS[ii], 1 );
|
|
dpl_SetDCSTraversal ( nameDCS[ii], 0x7 );
|
|
dpl_TranslateDCS ( nameDCS[ii], 0.0f, delta_y, 0.0f );
|
|
dpl_AddInstanceToDCS ( nameDCS[ii], nameInstance[ii] );
|
|
dpl_SetInstanceVisibility ( nameInstance[ii], 0 );
|
|
dpl_FlushInstance ( nameInstance[ii] );
|
|
dpl_FlushDCS ( nameDCS[ii] );
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create One DCS for Ordinal Ranking Bitmap
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
rankDCS[ii] = dpl_NewDCS();
|
|
rankInstance[ii] = dpl_NewInstance();
|
|
dpl_AddDCSToDCS ( nameDCS[ii], rankDCS[ii] );
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Ordinal Object will remain Static on the Ranking Window
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_SetInstanceObject ( rankInstance[ii], ordinalObject[ii] );
|
|
dpl_AddInstanceToDCS ( rankDCS[ii], rankInstance[ii] );
|
|
dpl_SetDCSIgnoreGeo ( rankDCS[ii], 1 );
|
|
dpl_SetDCSTraversal ( rankDCS[ii], 0x7 );
|
|
dpl_TranslateDCS ( rankDCS[ii], -0.75f, 0.0f, 0.0f );
|
|
dpl_SetInstanceVisibility ( rankInstance[ii], 0 );
|
|
dpl_FlushInstance ( rankInstance[ii] );
|
|
dpl_FlushDCS ( rankDCS[ii] );
|
|
}
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the CameraShipHUDRenderable
|
|
//
|
|
CameraShipHUDRenderable::~CameraShipHUDRenderable()
|
|
{
|
|
Check(this);
|
|
|
|
dpl_RemoveInstanceFromDCS(followedNameDCS, followedNameInstance);
|
|
dpl_RemoveDCSFromScene(followedNameDCS);
|
|
dpl_DeleteInstance(followedNameInstance);
|
|
dpl_DeleteDCS(followedNameDCS);
|
|
|
|
dpl_RemoveInstanceFromDCS(followedOrdinalDCS, followedOrdinalInstance);
|
|
dpl_RemoveDCSFromScene(followedOrdinalDCS);
|
|
dpl_DeleteInstance(followedOrdinalInstance);
|
|
dpl_DeleteDCS(followedOrdinalDCS);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Delete the Ranking Window
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(application);
|
|
for(int ii=0;ii<playerCount;++ii)
|
|
{
|
|
dpl_RemoveInstanceFromDCS(rankDCS[ii], rankInstance[ii]);
|
|
dpl_RemoveDCSFromDCS(nameDCS[ii], rankDCS[ii]);
|
|
dpl_DeleteInstance(rankInstance[ii]);
|
|
dpl_DeleteDCS(rankDCS[ii]);
|
|
|
|
dpl_RemoveInstanceFromDCS(nameDCS[ii], nameInstance[ii]);
|
|
dpl_RemoveDCSFromDCS(rankingWindowDCS,nameDCS[ii]);
|
|
dpl_DeleteInstance(nameInstance[ii]);
|
|
dpl_DeleteDCS(nameDCS[ii]);
|
|
}
|
|
if (rankDCS)
|
|
{
|
|
Unregister_Pointer(rankDCS);
|
|
delete[] rankDCS;
|
|
}
|
|
if (nameDCS)
|
|
{
|
|
Unregister_Pointer(nameDCS);
|
|
delete[] nameDCS;
|
|
}
|
|
if(rankInstance)
|
|
{
|
|
Unregister_Pointer(rankInstance);
|
|
delete[] rankInstance;
|
|
}
|
|
if (nameInstance)
|
|
{
|
|
Unregister_Pointer(nameInstance);
|
|
delete[] nameInstance;
|
|
}
|
|
if (rankingWindowDCS)
|
|
{
|
|
dpl_RemoveDCSFromScene(rankingWindowDCS);
|
|
dpl_DeleteDCS(rankingWindowDCS);
|
|
}
|
|
if (oldPlayerRank)
|
|
{
|
|
Unregister_Pointer(oldPlayerRank);
|
|
delete[] oldPlayerRank;
|
|
}
|
|
if (playerRank)
|
|
{
|
|
Unregister_Pointer(playerRank);
|
|
delete[] playerRank;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the CameraShipHUDRenderable
|
|
//
|
|
void
|
|
CameraShipHUDRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
|
|
if (!playerCount || *followedPlayerIndex <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Update the Followed Player NameBitmap
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Verify(*followedPlayerIndex <= MAX_PLAYER_NAMES);
|
|
if (oldFollowedPlayerIndex != *followedPlayerIndex -1)
|
|
{
|
|
oldFollowedPlayerIndex = *followedPlayerIndex -1;
|
|
|
|
if (oldFollowedPlayerIndex < 8)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Change the bitmap shown
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_SetInstanceObject (
|
|
followedNameInstance,
|
|
playerNameObject[oldFollowedPlayerIndex]
|
|
);
|
|
dpl_FlushInstance ( followedNameInstance );
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Change the bitmap shown
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_SetInstanceObject (
|
|
followedOrdinalInstance,
|
|
ordinalObject[*playerRank[oldFollowedPlayerIndex]]
|
|
);
|
|
dpl_FlushInstance ( followedOrdinalInstance );
|
|
}
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Update the Followed Ordinal NameBitmap
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Verify(oldFollowedPlayerIndex < playerCount && oldFollowedPlayerIndex >= 0);
|
|
#if 0
|
|
if (
|
|
oldPlayerRank[oldFollowedPlayerIndex]
|
|
!= *playerRank[oldFollowedPlayerIndex]
|
|
)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Change the bitmap shown
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Verify(
|
|
oldPlayerRank[oldFollowedPlayerIndex] >= 0
|
|
&& oldPlayerRank[oldFollowedPlayerIndex] < playerCount
|
|
);
|
|
dpl_SetInstanceObject (
|
|
followedOrdinalInstance,
|
|
ordinalObject[*playerRank[oldFollowedPlayerIndex]]
|
|
);
|
|
dpl_FlushInstance ( followedOrdinalInstance );
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Update the Rankings for All Players
|
|
// whenever they change!
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
for(int ii=0;ii<playerCount;++ii)
|
|
{
|
|
if (oldPlayerRank[ii] != (*playerRank[ii]))
|
|
{
|
|
oldPlayerRank[ii] = *playerRank[ii];
|
|
Verify(oldPlayerRank[ii] >= 0 && oldPlayerRank[ii] < playerCount);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Name instance corresponds to rank
|
|
// playerNameobject corresponds to playerBitmapIndex
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_SetInstanceObject(
|
|
nameInstance[oldPlayerRank[ii]],
|
|
playerNameObject[ii]
|
|
);
|
|
dpl_FlushInstance ( nameInstance[oldPlayerRank[ii]] );
|
|
}
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Toggle Ranking Window Visibility
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (oldDisplayRankingWindow != *displayRankingWindow)
|
|
{
|
|
oldDisplayRankingWindow = *displayRankingWindow;
|
|
for(int ii=0;ii<playerCount;++ii)
|
|
{
|
|
if (oldDisplayRankingWindow)
|
|
{
|
|
dpl_SetInstanceVisibility ( nameInstance[ii], 1 );
|
|
dpl_SetInstanceVisibility ( rankInstance[ii], 1 );
|
|
}
|
|
else
|
|
{
|
|
dpl_SetInstanceVisibility ( nameInstance[ii], 0 );
|
|
dpl_SetInstanceVisibility ( rankInstance[ii], 0 );
|
|
}
|
|
dpl_FlushInstance ( nameInstance[ii] );
|
|
dpl_FlushInstance ( rankInstance[ii] );
|
|
}
|
|
}
|
|
|
|
if (application->GetApplicationState() == Application::StoppingMission ||
|
|
application->GetApplicationState() == Application::EndingMission)
|
|
{
|
|
dpl_SetInstanceVisibility ( followedOrdinalInstance, 0 );
|
|
dpl_SetInstanceVisibility ( followedNameInstance, 0 );
|
|
dpl_FlushInstance ( followedOrdinalInstance );
|
|
dpl_FlushInstance ( followedNameInstance );
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
CameraShipHUDRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DCSMorphObjectRenderable
|
|
//
|
|
DCSMorphObjectRenderable::DCSMorphObjectRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *destination_object, // destination
|
|
dpl_OBJECT *start_object, // start object
|
|
dpl_OBJECT *end_object, // end object
|
|
Scalar *morph_control, // pointer to control variable
|
|
int32 morph_mode, // Defines type of morph to do
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask // intersection mask for the object
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
Check_Pointer(destination_object);
|
|
Check_Pointer(start_object);
|
|
Check_Pointer(end_object);
|
|
Check_Pointer(morph_control);
|
|
Check_Pointer(this_zone);
|
|
//
|
|
// Remember my dpl object, intersect and offset data
|
|
//
|
|
myDPLObject = destination_object;
|
|
myStartObject = start_object;
|
|
myEndObject = end_object;
|
|
myMorphControl = morph_control;
|
|
oldMorphControl = *myMorphControl;
|
|
myMorphMode = morph_mode;
|
|
myDPLZone = this_zone;
|
|
myIntersectMode = intersect_mode;
|
|
myIntersectMask = intersect_mask;
|
|
myDCS = NULL;
|
|
myInstance = NULL;
|
|
//
|
|
// We need to construct a DCS node here and remember it. The next class up is
|
|
// expected to handle the flushing and connecting of structure so we just setup
|
|
// the DCS and zone information here, leaving flushing to someone else.
|
|
//
|
|
myDCS = dpl_NewDCS ();
|
|
Check_Pointer ( myDCS );
|
|
dpl_SetDCSZone ( myDCS, myDPLZone );
|
|
//
|
|
// Construct the instance(s) and hang them on the DCS. Since we may be building
|
|
// more than one instance, we have to take care of flushing them here.
|
|
//
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer ( myInstance);
|
|
dpl_SetInstanceObject ( myInstance, myDPLObject);
|
|
dpl_SetInstanceIntersect ( myInstance, myIntersectMode );
|
|
dpl_SetInstanceSectMask ( myInstance, myIntersectMask );
|
|
dpl_SetInstanceVisibility ( myInstance, 1 );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
dpl_FlushInstance ( myInstance );
|
|
//
|
|
// Setup the morph and do the initial morph to get the destination object
|
|
//--------------------------------------------------------------------------
|
|
// NOTE: dpl_MorphObject seems to have Start and End objects reversed
|
|
// so they are reversed here as well...(two negatives make positive)
|
|
//--------------------------------------------------------------------------
|
|
dpl_MorphObject(myDPLObject,myStartObject,myEndObject,oldMorphControl,myMorphMode);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DCSMorphObjectRenderable
|
|
//
|
|
DCSMorphObjectRenderable::~DCSMorphObjectRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Delete the instance(s) hanging on the DCS (if any)
|
|
// NOTE: we may want to iterate through all the instances here using DPL routines
|
|
//
|
|
dpl_RemoveInstanceFromDCS(myDCS, myInstance);
|
|
dpl_DeleteInstance(myInstance);
|
|
//
|
|
// Delete the DCS
|
|
//
|
|
dpl_DeleteDCS(myDCS);
|
|
myDCS = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DCSMorphObjectRenderable
|
|
//
|
|
Logical
|
|
DCSMorphObjectRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
VideoRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check_Pointer(myDPLObject);
|
|
Check_Pointer(myStartObject);
|
|
Check_Pointer(myEndObject);
|
|
Check_Pointer(myMorphControl);
|
|
Check_Pointer(myDPLZone);
|
|
Check_Pointer(myDCS);
|
|
Check_Pointer(myInstance);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DCSMorphObjectRenderable
|
|
// If the morph control variable has changed, we re-do the morph
|
|
//
|
|
void
|
|
DCSMorphObjectRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// See if the morph control varaible has changed
|
|
//
|
|
if(oldMorphControl != *myMorphControl)
|
|
{
|
|
oldMorphControl = *myMorphControl;
|
|
//--------------------------------------------------------------------------
|
|
// NOTE: dpl_MorphObject seems to have Start and End objects reversed
|
|
// so they are reversed here as well...(two negatives make positive)
|
|
//--------------------------------------------------------------------------
|
|
|
|
dpl_MorphObject(myDPLObject,myStartObject,myEndObject,oldMorphControl,myMorphMode);
|
|
}
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for RootMorphRenderable
|
|
//
|
|
RootMorphRenderable::RootMorphRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *destination_object, // destination
|
|
dpl_OBJECT *start_object, // start object
|
|
dpl_OBJECT *end_object, // end object
|
|
Scalar *morph_control, // pointer to control variable
|
|
int32 morph_mode, // Defines type of morph to do
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask // intersection mask for the object
|
|
):
|
|
DCSMorphObjectRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
destination_object, // destination
|
|
start_object, // start object
|
|
end_object, // end object
|
|
morph_control, // pointer to control variable
|
|
morph_mode, // Defines type of morph to do
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask) // intersection mask for the object
|
|
{
|
|
//
|
|
// All the incoming data will have been checked by DCSObjectRenderable
|
|
// already, so we don't have to check anything locally.
|
|
//
|
|
//
|
|
// Initialize our variables
|
|
//
|
|
oldLocalToWorld = myEntity->localToWorld;
|
|
//
|
|
// Now we finish the work of hooking up and initializing the root renderable
|
|
// Add the DCS to the scene and initialize it's matrix with the localToWorld
|
|
// transformation from our entity
|
|
//
|
|
dpl_AddDCSToScene ( myDCS );
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = myEntity->localToWorld;
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for RootMorphRenderable
|
|
//
|
|
RootMorphRenderable::~RootMorphRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
//
|
|
// Remove the DCS from the scene, deletion of the DCS and it's instances is
|
|
// handled by our parent class.
|
|
//
|
|
dpl_RemoveDCSFromScene(myDCS);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the RootMorphRenderable
|
|
//
|
|
Logical
|
|
RootMorphRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
DCSMorphObjectRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(&oldLocalToWorld);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the RootMorphRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
RootMorphRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// If our entity has changed it's localToWorld matrix, update DPL
|
|
//
|
|
if(oldLocalToWorld != myEntity->localToWorld)
|
|
{
|
|
oldLocalToWorld = myEntity->localToWorld;
|
|
float32* tempMatrix = dpl_GetDCSMatrix(myDCS);
|
|
Check_Pointer (tempMatrix);
|
|
*(Matrix4x4*)tempMatrix = oldLocalToWorld;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
DCSMorphObjectRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for ChildMorphRenderable
|
|
//
|
|
ChildMorphRenderable::ChildMorphRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *destination_object, // destination
|
|
dpl_OBJECT *start_object, // start object
|
|
dpl_OBJECT *end_object, // end object
|
|
Scalar *morph_control, // pointer to control variable
|
|
int32 morph_mode, // Defines type of morph to do
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS // the parent DCS we will be offsetting from
|
|
):
|
|
DCSMorphObjectRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
destination_object, // destination
|
|
start_object, // start object
|
|
end_object, // end object
|
|
morph_control, // pointer to control variable
|
|
morph_mode, // Defines type of morph to do
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask) // intersection mask for the object
|
|
{
|
|
//
|
|
// All the incoming data will have been checked by DCSObjectRenderable
|
|
// already, so we don't have to check anything locally.
|
|
//
|
|
Check_Pointer(parent_DCS);
|
|
//
|
|
// Now we finish the work of hooking up and initializing the root renderable
|
|
// Add the DCS to the scene and initialize it's matrix with the localToWorld
|
|
// transformation from our entity
|
|
//
|
|
dpl_AddDCSToDCS ( parent_DCS, myDCS );
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ChildMorphRenderable
|
|
//
|
|
ChildMorphRenderable::~ChildMorphRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ChildMorphRenderable
|
|
//
|
|
Logical
|
|
ChildMorphRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
DCSMorphObjectRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ChildMorphRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
ChildMorphRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
DCSMorphObjectRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for ScalingExplosionRenderable
|
|
//
|
|
ScalingExplosionRenderable::ScalingExplosionRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // This will be the scaling explosion object
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
Vector3D *control_vector, // Effect control velocity vector
|
|
Vector3D *accel_vector, // rate of change of control vector
|
|
Scalar gravity,
|
|
int *trigger // doesn't run till the trigger comes up
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
//
|
|
// Check the incoming data
|
|
//
|
|
Check(control_vector);
|
|
#if DEBUG_LEVEL > 0
|
|
if(trigger)
|
|
Check_Pointer(trigger);
|
|
#endif
|
|
//
|
|
// Initialize our variables
|
|
//
|
|
myScalingVector.x = 0.01;
|
|
myScalingVector.y = 0.01;
|
|
myScalingVector.z = 0.01;
|
|
myVelocityVector = *control_vector;
|
|
myVelocityChange = *accel_vector;
|
|
myGravity = gravity;
|
|
myVelocity = 0.0f;
|
|
myTranslation.x = 0.0;
|
|
myTranslation.y = 0.0;
|
|
myTranslation.z = 0.0;
|
|
myTrigger = trigger;
|
|
//
|
|
// Initialize the matrix in this dcs
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= myScalingVector;
|
|
tempAffine *= myTranslation;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
dpl_FlushDCS ( myDCS );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ScalingExplosionRenderable
|
|
//
|
|
ScalingExplosionRenderable::~ScalingExplosionRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ScalingExplosionRenderable
|
|
//
|
|
Logical
|
|
ScalingExplosionRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
DCSObjectRenderable::TestInstance();
|
|
//
|
|
// Test our own variables
|
|
//
|
|
Check(&myScalingVector);
|
|
Check(&myVelocityVector);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ScalingExplosionRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
ScalingExplosionRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
if(!myTrigger || *myTrigger != 0)
|
|
{
|
|
//
|
|
// Apply the scaling factor to the object
|
|
//
|
|
myVelocityVector += myVelocityChange;
|
|
myScalingVector += myVelocityVector;
|
|
myVelocity += myGravity;
|
|
myTranslation.y += myVelocity;
|
|
//
|
|
// Initialize the matrix in this dcs
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= myScalingVector;
|
|
tempAffine *= myTranslation;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Micro Renderables
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
// From here to the row of === is pretty kludgy stuff to allow dave to prototype
|
|
// some explosion stuff.
|
|
// I expect to replace most of it within a week with the all-new micro
|
|
// renderable system.
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DependantRenderable
|
|
// This is a class of renderable that has other dependant renderables which it
|
|
// will execute on command. This is a base for this type of renderable and is
|
|
// not ment to be used by itself.
|
|
//
|
|
DependantRenderable::DependantRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type // How/when to execute the renderable
|
|
):
|
|
VideoRenderable(entity, execution_type),
|
|
dependantRenderableSocket(NULL)
|
|
{
|
|
// Check incoming data
|
|
// Initialize variables
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DependantRenderable
|
|
DependantRenderable::~DependantRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DependantRenderable
|
|
Logical
|
|
DependantRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
// Now do our checking
|
|
Check(&dependantRenderableSocket);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// AddDependantRenderable for the DependantRenderable
|
|
// This adds an existing renderable as a dependant on this renderable so it
|
|
// will be run when this renderable is executed.
|
|
void
|
|
DependantRenderable::AddDependantRenderable(Component *dependant)
|
|
{
|
|
Check(dependant);
|
|
dependantRenderableSocket.Add(dependant);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DependantRenderable
|
|
void
|
|
DependantRenderable::Execute()
|
|
{
|
|
Component
|
|
*dependant;
|
|
//
|
|
// Make an iterator for our components then execute them all
|
|
//
|
|
// cout<<"DependantRenderable::Execute()\n";
|
|
SChainIteratorOf<Component*> dependant_iterator(&dependantRenderableSocket);
|
|
while ((dependant = dependant_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
dependant->Execute();
|
|
// cout<<"dependant->Execute();\n";
|
|
}
|
|
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for ScalarTriggerRenderable
|
|
// Whenever "watched_value" changes by "watched_precision" the dependants of this
|
|
// renderable will be called.
|
|
//
|
|
ScalarTriggerRenderable::ScalarTriggerRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar *watched_value, // we run dependants when this changes
|
|
Scalar watched_precision // watched_value must change by this much
|
|
):
|
|
DependantRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
Check_Pointer(watched_value);
|
|
//
|
|
// Initialize variables
|
|
//
|
|
myWatchedValue = watched_value;
|
|
myOldWatchedValue = *myWatchedValue;
|
|
myPrecision = watched_precision;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ScalarTriggerRenderable
|
|
ScalarTriggerRenderable::~ScalarTriggerRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ScalarTriggerRenderable
|
|
Logical
|
|
ScalarTriggerRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
DependantRenderable::TestInstance();
|
|
// Now do our checking
|
|
Check_Pointer(myWatchedValue);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ScalarTriggerRenderable
|
|
void
|
|
ScalarTriggerRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
//
|
|
// If there hasn't been a significant enough change, return right now
|
|
//
|
|
if(Abs((*myWatchedValue - myOldWatchedValue)) < myPrecision)
|
|
return;
|
|
//
|
|
// Update my watcher data, then call my parent to execute the dependants
|
|
//
|
|
myOldWatchedValue = *myWatchedValue;
|
|
DependantRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for TimeCullRenderable
|
|
// This renderable will run all it's dependants at a set frequency based on
|
|
// a clock value supplied by the culling system.
|
|
//
|
|
TimeCullRenderable::TimeCullRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar delay_between_runs // Time delay between executions of dependants
|
|
):
|
|
DependantRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check incoming data
|
|
//
|
|
//
|
|
// Initialize the renderable, set clock so this will execute the first time
|
|
// it's called.
|
|
//
|
|
delayBetweenRuns = delay_between_runs;
|
|
nextRunTime = myRenderer->GetCurrentFrameTime();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for TimeCullRenderable
|
|
TimeCullRenderable::~TimeCullRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the TimeCullRenderable
|
|
Logical
|
|
TimeCullRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
DependantRenderable::TestInstance();
|
|
// Now do our checking
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the TimeCullRenderable
|
|
void
|
|
TimeCullRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
//
|
|
// If it's time, call my parent to execute the dependants
|
|
//
|
|
if(nextRunTime <= myRenderer->GetCurrentFrameTime())
|
|
{
|
|
nextRunTime = myRenderer->GetCurrentFrameTime() + delayBetweenRuns;
|
|
DependantRenderable::Execute();
|
|
// cout<<"Time Cull ran dependants\n";
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MechCullRenderable::MechCullRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Logical always_run_all, // If true, disable culling and run everything
|
|
dpl_ZONE *my_zone // Switch off this zone when the mech goes off screen
|
|
):
|
|
DependantRenderable(entity, execution_type),
|
|
legRenderableSocket(NULL)
|
|
{
|
|
Check_Pointer(my_zone);
|
|
myAlwaysRunAll = always_run_all;
|
|
myZone = my_zone;
|
|
myMechWasVisible = True;
|
|
myNextRootUpdate = myRenderer->GetCurrentFrameTime();
|
|
myNextLegUpdate = myRenderer->GetCurrentFrameTime();
|
|
myRootUpdateRate = 0.0;
|
|
myLegUpdateRate = 0.0;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for MechCullRenderable
|
|
MechCullRenderable::~MechCullRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// AddDependantLegRenderable for the MechCullRenderable
|
|
// This adds an existing renderable as a dependant of the leg chain.
|
|
void
|
|
MechCullRenderable::AddDependantLegRenderable(Component *dependant)
|
|
{
|
|
Check(dependant);
|
|
legRenderableSocket.Add(dependant);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the MechCullRenderable
|
|
Logical
|
|
MechCullRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
DependantRenderable::TestInstance();
|
|
// Now do our checking
|
|
Check_Pointer(myZone);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the MechCullRenderable
|
|
void
|
|
MechCullRenderable::Execute()
|
|
{
|
|
#define CULL_VOLUME_SIZE 11.0 // Assume mech (or other object) fills 10 meter bubble
|
|
Scalar
|
|
current_time;
|
|
Point3D
|
|
target_point;
|
|
Component
|
|
*dependant;
|
|
|
|
Check(this);
|
|
//
|
|
// If we've been told to always run everything, do so. I don't flip the
|
|
// profile bit here because I only want to time the actual cull algorithim.
|
|
//
|
|
if(myAlwaysRunAll)
|
|
{
|
|
DependantRenderable::Execute();
|
|
SChainIteratorOf<Component*> dependant_iterator(&legRenderableSocket);
|
|
while ((dependant = dependant_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
dependant->Execute();
|
|
}
|
|
myMechWasVisible = True;
|
|
return;
|
|
}
|
|
SET_VIDEO_MECH_CULL_RENDERABLE();
|
|
//
|
|
// Continue on to do the full culling process
|
|
//
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
//
|
|
// Transform this entities position into eye space
|
|
//
|
|
target_point = myEntity->localOrigin.linearPosition;
|
|
target_point *= (*myRenderer->GetWorldToEyeMatrix());
|
|
Check(this);
|
|
//
|
|
// See if this is inside the viewing volume
|
|
// HACK, viewing volume is hard coded here for now
|
|
// negative z goes into the screen
|
|
//
|
|
// See if it's behind me
|
|
//
|
|
if((target_point.z - CULL_VOLUME_SIZE) >= 0.0f)
|
|
{
|
|
if(myMechWasVisible)
|
|
{
|
|
myMechWasVisible = False;
|
|
dpl_SetZoneAllViewsOff (myZone);
|
|
dpl_FlushZone (myZone);
|
|
//
|
|
// Set the root rate to slow and the leg rate to stopped
|
|
//
|
|
myRootUpdateRate = 1.0f;
|
|
myLegUpdateRate = 60.0f;
|
|
myNextRootUpdate = current_time + myRootUpdateRate;
|
|
myNextLegUpdate = current_time + myLegUpdateRate;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fix up the Z so objects very close behind us (close enough they might
|
|
// stick into our view) will be properly culled.
|
|
//
|
|
if(target_point.z >= 0)
|
|
target_point.z = 0.1;
|
|
else
|
|
target_point.z = Abs(target_point.z);
|
|
Check(this);
|
|
//
|
|
// See if the object's volume is to the left or right of the culling
|
|
// volume.
|
|
//
|
|
if(((Abs(target_point.x)-CULL_VOLUME_SIZE)/target_point.z) > myRenderer->GetViewRatio())
|
|
{
|
|
//
|
|
// If we were visible before, we're not any more
|
|
//
|
|
Check(this);
|
|
if(myMechWasVisible)
|
|
{
|
|
myMechWasVisible = False;
|
|
dpl_SetZoneAllViewsOff (myZone);
|
|
dpl_FlushZone (myZone);
|
|
//
|
|
// Set the root rate to slow and the leg rate to stopped
|
|
//
|
|
myRootUpdateRate = 1.0f;
|
|
myLegUpdateRate = 60.0f;
|
|
myNextRootUpdate = current_time + myRootUpdateRate;
|
|
myNextLegUpdate = current_time + myLegUpdateRate;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If we were invisible before, we're visible now
|
|
//
|
|
Check(this);
|
|
if(!myMechWasVisible)
|
|
{
|
|
myMechWasVisible = True;
|
|
dpl_SetZoneAllViewsOn (myZone);
|
|
dpl_FlushZone (myZone);
|
|
//
|
|
// Set the various update rates appropriately and force an update
|
|
//
|
|
myRootUpdateRate = 0.0;
|
|
myNextRootUpdate = current_time;
|
|
myNextLegUpdate = current_time;
|
|
}
|
|
//
|
|
// Set the leg update rate based on range (really should be a formulia)
|
|
//
|
|
if(target_point.z < 500.0f)
|
|
myLegUpdateRate = 0.0;
|
|
else
|
|
myLegUpdateRate = 0.25;
|
|
}
|
|
}
|
|
//
|
|
// Flip the trace bit here because I don't want to include the cost of the
|
|
// dependant renderables.
|
|
//
|
|
CLEAR_VIDEO_MECH_CULL_RENDERABLE();
|
|
//
|
|
// Use the data already calculated to determine which of the dependant
|
|
// renderable groups we should execute.
|
|
//
|
|
if(myNextLegUpdate <= current_time)
|
|
{
|
|
myNextLegUpdate = current_time + myLegUpdateRate;
|
|
//
|
|
// Execute all the leg renderables
|
|
//
|
|
SChainIteratorOf<Component*> dependant_iterator(&legRenderableSocket);
|
|
while ((dependant = dependant_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
dependant->Execute();
|
|
}
|
|
}
|
|
if(myNextRootUpdate <= current_time)
|
|
{
|
|
myNextRootUpdate = current_time + myRootUpdateRate;
|
|
DependantRenderable::Execute();
|
|
}
|
|
return;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for InstanceSwitchRenderable
|
|
InstanceSwitchRenderable::InstanceSwitchRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_INSTANCE *this_instance, // the instance to control
|
|
Logical sense, // instance on when trigger is....
|
|
int *trigger // true if the instance is on, false if off
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
// Check incoming data
|
|
Check_Pointer(this_instance);
|
|
Check_Pointer(trigger);
|
|
// Initialize variables
|
|
mySense = sense;
|
|
myInstance = this_instance;
|
|
myTriggerAttribute = trigger;
|
|
oldTriggerAttribute = *myTriggerAttribute;
|
|
if(mySense == oldTriggerAttribute)
|
|
{
|
|
dpl_SetInstanceVisibility ( myInstance, 1 );
|
|
}
|
|
else
|
|
{
|
|
dpl_SetInstanceVisibility ( myInstance, 0 );
|
|
}
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for InstanceSwitchRenderable
|
|
InstanceSwitchRenderable::~InstanceSwitchRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the InstanceSwitchRenderable
|
|
Logical
|
|
InstanceSwitchRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myInstance);
|
|
Check_Pointer(myTriggerAttribute);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the InstanceSwitchRenderable
|
|
void
|
|
InstanceSwitchRenderable::Execute()
|
|
{
|
|
// Check our variables
|
|
Check(this);
|
|
if(*myTriggerAttribute != oldTriggerAttribute)
|
|
{
|
|
oldTriggerAttribute = *myTriggerAttribute;
|
|
if(mySense == oldTriggerAttribute)
|
|
{
|
|
dpl_SetInstanceVisibility ( myInstance, 1 );
|
|
}
|
|
else
|
|
{
|
|
dpl_SetInstanceVisibility ( myInstance, 0 );
|
|
}
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// StateInstanceSwitchRenderable is designed to be a watcher that connects to
|
|
// a state dial. Whenever the state dial changes we are called and check to
|
|
// see if the trigger state has been entered. If we are in the trigger state
|
|
// we will change the instance visibility based on the sense variable passed
|
|
// into the constructor. This lets you have an instance on while in a
|
|
// certain state or off while in that state and on in others.
|
|
// Messages Sent: None
|
|
// Messages Received: None
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for StateInstanceSwitchRenderable
|
|
//
|
|
StateInstanceSwitchRenderable::StateInstanceSwitchRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_INSTANCE *this_instance, // the instance to control
|
|
Logical sense, // true to turn on in this state, false for off
|
|
StateIndicator *state_dial, // State dial we use to control the on/off
|
|
unsigned trigger_state // State that we look for
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check incoming data for correctness
|
|
//
|
|
Check_Pointer(this_instance);
|
|
Check(state_dial);
|
|
//
|
|
// Initialize variables
|
|
//
|
|
myInstance = this_instance;
|
|
mySense = sense;
|
|
myStateDial = state_dial;
|
|
myTriggerState = trigger_state;
|
|
//
|
|
// Put the instance in the proper state and flush it
|
|
//
|
|
if(myStateDial->GetState() == myTriggerState)
|
|
{
|
|
if(mySense == True)
|
|
myLastInstanceState = True;
|
|
else
|
|
myLastInstanceState = False;
|
|
}
|
|
else
|
|
{
|
|
if(mySense == True)
|
|
myLastInstanceState = False;
|
|
else
|
|
myLastInstanceState = True;
|
|
}
|
|
dpl_SetInstanceVisibility ( myInstance, myLastInstanceState );
|
|
dpl_FlushInstance ( myInstance );
|
|
//
|
|
// Connect us to the state dial's watcher hook
|
|
//
|
|
state_dial->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for StateInstanceSwitchRenderable
|
|
StateInstanceSwitchRenderable::~StateInstanceSwitchRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the StateInstanceSwitchRenderable
|
|
Logical
|
|
StateInstanceSwitchRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myInstance);
|
|
Check(myStateDial);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the StateInstanceSwitchRenderable --- called by the state dial
|
|
// watcher hook when the state changes. The state dial won't call us if unless
|
|
// the state actually changes so there is no need to filter transitions between
|
|
// two identical states.
|
|
//
|
|
void
|
|
StateInstanceSwitchRenderable::Execute()
|
|
{
|
|
unsigned
|
|
new_state;
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// See what state we should go into
|
|
//
|
|
if(myStateDial->GetState() == myTriggerState)
|
|
{
|
|
if(mySense == True)
|
|
new_state = True;
|
|
else
|
|
new_state = False;
|
|
}
|
|
else
|
|
{
|
|
if(mySense == True)
|
|
new_state = False;
|
|
else
|
|
new_state = True;
|
|
}
|
|
if(new_state != myLastInstanceState)
|
|
{
|
|
myLastInstanceState = new_state;
|
|
dpl_SetInstanceVisibility ( myInstance, myLastInstanceState );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for MakeDCSFall
|
|
MakeDCSFall::MakeDCSFall(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_DCS *this_DCS, // the DCS to control
|
|
Scalar gravity, // Gravity in meters/sec squared
|
|
int *trigger // true if the instance is on, false if off
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
// Check incoming data
|
|
Check_Pointer(this_DCS);
|
|
Check_Pointer(trigger);
|
|
//
|
|
// Was an input trigger provided?
|
|
//
|
|
if(trigger)
|
|
{
|
|
// Yes, remember a pointer to it and it's state
|
|
myTrigger = trigger;
|
|
oldMyTrigger = *myTrigger;
|
|
}
|
|
else
|
|
{
|
|
// No, point it at a fake trigger that is turned on
|
|
fakeTrigger = 1;
|
|
myTrigger = &fakeTrigger;
|
|
oldMyTrigger = 0;
|
|
}
|
|
//
|
|
// Initialize other variables
|
|
//
|
|
myDCS = this_DCS;
|
|
myDisplacement = Point3D::Identity;
|
|
myHalfAcceleration = gravity/2.0f;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for MakeDCSFall
|
|
MakeDCSFall::~MakeDCSFall()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the MakeDCSFall
|
|
Logical
|
|
MakeDCSFall::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the MakeDCSFall
|
|
void
|
|
MakeDCSFall::Execute()
|
|
{
|
|
// Check our variables
|
|
Check(this);
|
|
//
|
|
// Look for an edge in the trigger input
|
|
//
|
|
if(*myTrigger != oldMyTrigger)
|
|
{
|
|
//
|
|
// A transition from zero to nonzero resets the DCS position and
|
|
// starts us falling again.
|
|
//
|
|
if(oldMyTrigger == 0)
|
|
{
|
|
myFallStart = myRenderer->GetCurrentFrameTime();
|
|
myDisplacement = Point3D::Identity;
|
|
}
|
|
oldMyTrigger = *myTrigger;
|
|
}
|
|
//
|
|
// If the trigger is nonzero and the sweep isn't at 1 yet, update
|
|
// the sweep values.
|
|
//
|
|
if(oldMyTrigger != 0)
|
|
{
|
|
Scalar
|
|
elapsed_time,
|
|
current_time;
|
|
// Figure displacement do to gravity... 0.5 * a * t^2
|
|
// note that we've already taken a * 0.5 in the constructor
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
elapsed_time = current_time - myFallStart;
|
|
myDisplacement.y = myHalfAcceleration * (elapsed_time * elapsed_time);
|
|
float32* tempMatrix = dpl_GetDCSMatrix(myDCS);
|
|
Check_Pointer (tempMatrix);
|
|
*(Matrix4x4*)tempMatrix = myDisplacement;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//=============================================================================
|
|
#if 0
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for SquareWaveRenderable
|
|
SquareWaveRenderable::SquareWaveRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar time_false, // time to spend in zero state
|
|
Scalar time_true, // time to spend in one state
|
|
int *trigger // starts square wave when it goes to 1
|
|
int start_state // state we start in
|
|
int cycles // number of transitions before we stop
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
if(trigger)
|
|
{
|
|
// Yes, remember a pointer to it and it's state
|
|
myTriggerInput = trigger;
|
|
oldTriggerInput = *myTrigger;
|
|
}
|
|
else
|
|
{
|
|
// No, point it at a fake trigger that is turned on
|
|
fakeTrigger = 1;
|
|
myTriggerInput = &fakeTrigger;
|
|
oldTriggerInput = 0;
|
|
}
|
|
// Initialize variables
|
|
myTriggerInput = trigger;
|
|
oldTriggerInput = 0;
|
|
myNextStateChange = 0;
|
|
myTimeFalse = time_false;
|
|
myTimeTrue = time_true;
|
|
myTriggerAttribute = start_state;
|
|
myCyclesLeft = cycles;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for SquareWaveRenderable
|
|
SquareWaveRenderable::~SquareWaveRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the SquareWaveRenderable
|
|
Logical
|
|
SquareWaveRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Verify(myTriggerTime > 0.0f);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the SquareWaveRenderable
|
|
void
|
|
SquareWaveRenderable::Execute()
|
|
{
|
|
Scalar
|
|
current_time;
|
|
// Check our variables
|
|
Check(this);
|
|
|
|
if(*myTriggerInput != oldTriggerInput && oldTriggerInput == 0)
|
|
{
|
|
if(myStartState)
|
|
{
|
|
myNextStateChange = myRenderer->GetCurrentFrameTime();
|
|
myNextStateChange += myTimeTrue;
|
|
myTriggerAttribute = True;
|
|
}
|
|
else
|
|
{
|
|
myNextStateChange = myRenderer->GetCurrentFrameTime();
|
|
myNextStateChange += myTimeFalse;
|
|
myTriggerAttribute = False;
|
|
}
|
|
myCyclesLeft = myCycles;
|
|
}
|
|
|
|
if(*myTriggerInput == 1 && myCyclesLeft > 0)
|
|
{
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
if(current_time >= myNextStateChange)
|
|
{
|
|
myCyclesLeft--;
|
|
myTriggerAttribute = (!myTriggerAttribute);
|
|
if(myTriggerAttribute)
|
|
{
|
|
myNextStateChange = myRenderer->GetCurrentFrameTime();
|
|
myNextStateChange += myTimeTrue;
|
|
}
|
|
else
|
|
{
|
|
myNextStateChange = myRenderer->GetCurrentFrameTime();
|
|
myNextStateChange += myTimeFalse;
|
|
}
|
|
}
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
#endif
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for OneShotDelayRenderable
|
|
// This renderable delays for a fixed amount after it's creation, then turns on
|
|
// a trigger attribute. It is used for the triggering of other renderables a
|
|
// fixed time after an object is created.
|
|
OneShotDelayRenderable::OneShotDelayRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar delay_time, // How long to wait before raising the trigger
|
|
Scalar duration_time // How long trigger is up (0.0 == stay up)
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
// Check incoming data
|
|
Verify(delay_time >= 0.0f);
|
|
Verify(duration_time >= 0.0f);
|
|
// Initialize variables
|
|
myState = WaitingForTriggerTime;
|
|
myEndTimeFlag = !Small_Enough(duration_time);
|
|
myTriggerTime = myRenderer->GetCurrentFrameTime();
|
|
myTriggerTime += delay_time;
|
|
myTriggerEndTime = myTriggerTime + duration_time;
|
|
myTriggerAttribute = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for OneShotDelayRenderable
|
|
OneShotDelayRenderable::~OneShotDelayRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the OneShotDelayRenderable
|
|
Logical
|
|
OneShotDelayRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Verify(myTriggerTime > 0.0f);
|
|
Verify(myTriggerEndTime >= myTriggerTime);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the OneShotDelayRenderable
|
|
void
|
|
OneShotDelayRenderable::Execute()
|
|
{
|
|
Scalar
|
|
current_time;
|
|
// Check our variables
|
|
Check(this);
|
|
if (myState != WaitingForEternity)
|
|
{
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
// putting this here insures that the one-time will always spend
|
|
// at least one frame at True before resetting.
|
|
if (myState == WaitingForTriggerTime)
|
|
{
|
|
if (current_time > myTriggerTime)
|
|
{
|
|
myTriggerAttribute = 1;
|
|
if (myEndTimeFlag)
|
|
{
|
|
myState = WaitingForTriggerEndTime;
|
|
}
|
|
else
|
|
{
|
|
myState = WaitingForEternity;
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
}
|
|
}
|
|
}
|
|
else if (myState == WaitingForTriggerEndTime)
|
|
{
|
|
if (current_time > myTriggerEndTime)
|
|
{
|
|
myTriggerAttribute = NULL;
|
|
myState = WaitingForEternity;
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Dump(myState);
|
|
Fail("invalid myState");
|
|
}
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for SweepRenderable
|
|
// When triggered this renderable sweeps it's output attribute from 0.0 to 1.0
|
|
// over a preset time interval. Used for controling morphs.
|
|
SweepRenderable::SweepRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar delay_time, // How long to take to sweep from 0 to 1
|
|
int cycles, // number of times to cycle before stopping
|
|
int *trigger, // When it goes from 0 to 1 it resets the sweep generator
|
|
Scalar start_value, // Initial value of sweep (default = 0.0f)
|
|
Scalar end_value, // Final value of sweep (default = 1.0f)
|
|
SweepFunction sweep_function // Function applied to sweep
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Verify incoming data
|
|
//
|
|
Verify(delay_time >= 0.0f);
|
|
Verify(start_value <= end_value);
|
|
if (sweep_function == Y_SQR_X)
|
|
{ Verify(start_value >= 0.0f); }
|
|
//
|
|
// Was an input trigger provided?
|
|
//
|
|
if(trigger)
|
|
{
|
|
// Yes, remember a pointer to it and it's state
|
|
myTrigger = trigger;
|
|
oldMyTrigger = *myTrigger;
|
|
}
|
|
else
|
|
{
|
|
// No, point it at a fake trigger that is turned on
|
|
fakeTrigger = 1;
|
|
myTrigger = &fakeTrigger;
|
|
oldMyTrigger = 0;
|
|
}
|
|
//
|
|
// Initialize other variables
|
|
//
|
|
mySweepFunction = sweep_function;
|
|
myStartValue = start_value;
|
|
myEndValue = end_value;
|
|
myCycleCount = cycles;
|
|
mySweepTime = delay_time;
|
|
mySweepAttribute = myStartValue;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for SweepRenderable
|
|
SweepRenderable::~SweepRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the SweepRenderable
|
|
Logical
|
|
SweepRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Verify(mySweepTime >= 0.0f)
|
|
Verify((mySweepAttribute >= myStartValue) && (mySweepAttribute <= myEndValue));
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the SweepRenderable
|
|
void
|
|
SweepRenderable::Execute()
|
|
{
|
|
// Check our variables
|
|
Check(this);
|
|
//
|
|
// Look for an edge in the trigger input
|
|
//
|
|
if(*myTrigger != oldMyTrigger)
|
|
{
|
|
//
|
|
// A transition from zero to nonzero resets all the sweep parameters
|
|
// and starts the process over again.
|
|
//
|
|
if(oldMyTrigger == 0)
|
|
{
|
|
// A transition from zero to nonzero causes a reset of sweep timers
|
|
// and starts the sweep running.
|
|
mySweepStart = myRenderer->GetCurrentFrameTime();
|
|
mySweepAttribute = myStartValue;
|
|
myCyclesLeft = myCycleCount;
|
|
}
|
|
oldMyTrigger = *myTrigger;
|
|
}
|
|
//
|
|
// If the trigger is nonzero and the sweep isn't at 1 yet, update
|
|
// the sweep values.
|
|
//
|
|
if(oldMyTrigger != 0 && myCyclesLeft > 0)
|
|
{
|
|
Scalar
|
|
current_time;
|
|
// putting this here insures that the sweep will always spend one frame at
|
|
// {EndValue} before resetting.
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
if(mySweepAttribute >= myEndValue)
|
|
{
|
|
myCyclesLeft--;
|
|
if(myCyclesLeft > 0)
|
|
{ mySweepStart = current_time; }
|
|
}
|
|
mySweepAttribute = myStartValue + (myEndValue - myStartValue) *
|
|
(current_time - mySweepStart) / mySweepTime;
|
|
if (mySweepFunction == Y_SQR_X)
|
|
{
|
|
mySweepAttribute = Sqrt(mySweepAttribute);
|
|
}
|
|
// else if (mySweepFunction == Y_ )
|
|
// {
|
|
// }
|
|
if(mySweepAttribute > myEndValue)
|
|
{ mySweepAttribute = myEndValue; }
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for PullFogRenderable
|
|
// This routine handles swapping the fog settings in and out when you
|
|
// turn headlight systems on and off.
|
|
//
|
|
PullFogRenderable::PullFogRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Logical *light_1,
|
|
Logical *light_2 // address containing the trigger
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check_Pointer(light_1);
|
|
myLight1 = light_1;
|
|
myOldLight1 = !(*myLight1);
|
|
if(light_2 == NULL)
|
|
{
|
|
myLight2 = myLight1;
|
|
}
|
|
else
|
|
{
|
|
Check_Pointer(light_2);
|
|
myLight2 = light_2;
|
|
}
|
|
myOldLight2 = !(*myLight2);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for PullFogRenderable
|
|
//
|
|
PullFogRenderable::~PullFogRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the PullFogRenderable
|
|
//
|
|
Logical
|
|
PullFogRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myLight1);
|
|
Check_Pointer(myLight2);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for PullFogRenderable.
|
|
//
|
|
void
|
|
PullFogRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
if(*myLight1 != myOldLight1 || *myLight2 != myOldLight2)
|
|
{
|
|
myOldLight1 = *myLight1;
|
|
myOldLight2 = *myLight2;
|
|
if(myOldLight1 || myOldLight2)
|
|
{
|
|
myRenderer->SetFogStyle(DPLRenderer::searchLightOnFogStyle);
|
|
}
|
|
else
|
|
{
|
|
myRenderer->SetFogStyle(DPLRenderer::searchLightOffFogStyle);
|
|
}
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLEffectRenderable
|
|
// This routine handles the creation of a DPL special effect whenever the
|
|
// trigger attribute changes. This is an edge triggered renderable and will
|
|
// generate an effect on ANY form of state change. The only way to effect the
|
|
// size and speed of the effect is by way of the DPL effect tables.
|
|
//
|
|
DPLEffectRenderable::DPLEffectRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
int *trigger, // address containing the trigger
|
|
int effect_type, // DPL effect number to trigger
|
|
dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL)
|
|
Point3D *offset_point // Offset (or world coordinants if DCS is NULL)
|
|
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check_Pointer(trigger);
|
|
Verify(effect_type >= 0);
|
|
#if DEBUG_LEVEL > 0
|
|
if(effect_DCS != NULL)
|
|
Check_Pointer(effect_DCS);
|
|
#endif
|
|
Check(offset_point);
|
|
//
|
|
// Initialze the local variables
|
|
//
|
|
myTrigger = trigger;
|
|
oldMyTrigger = *myTrigger;
|
|
myEffectType = effect_type;
|
|
myEffectDCS = effect_DCS;
|
|
myEffectOffset = *offset_point;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLEffectRenderable
|
|
//
|
|
DPLEffectRenderable::~DPLEffectRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLEffectRenderable
|
|
//
|
|
Logical
|
|
DPLEffectRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myTrigger);
|
|
Verify(myEffectType >= 0);
|
|
#if DEBUG_LEVEL > 0
|
|
if(myEffectDCS != NULL)
|
|
Check_Pointer(myEffectDCS);
|
|
#endif
|
|
Check(&myEffectOffset);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLEffectRenderable.
|
|
//
|
|
void
|
|
DPLEffectRenderable::Execute()
|
|
{
|
|
Check_Pointer(myTrigger);
|
|
if(*myTrigger != oldMyTrigger)
|
|
{
|
|
dpl_EXPLOSION_EFFECT_INFO my_explosion;
|
|
oldMyTrigger = *myTrigger;
|
|
my_explosion.type = myEffectType;
|
|
my_explosion.x = myEffectOffset.x;
|
|
my_explosion.y = myEffectOffset.y;
|
|
my_explosion.z = myEffectOffset.z;
|
|
dpl_Effect ( dpl_effect_type_explosion, myEffectDCS, &my_explosion );
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLPSFXRenderable
|
|
// This routine triggers a pfx whenever the trigger attribute goes true.
|
|
// since pfx effects have built-in durations we don't attempt to do any repeats
|
|
// or other controls here, we just start one and kill it if the entity dies.
|
|
//
|
|
DPLPSFXRenderable::DPLPSFXRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
int *trigger, // address containing the trigger
|
|
dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it
|
|
dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL)
|
|
Point3D *offset_point // Offset (or world coordinants if DCS is NULL)
|
|
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check_Pointer(trigger);
|
|
#if DEBUG_LEVEL > 0
|
|
if(effect_DCS != NULL)
|
|
Check_Pointer(effect_DCS);
|
|
#endif
|
|
Check(offset_point);
|
|
if(!psfx_definition)
|
|
{
|
|
Fail("A pfx was not defined in the .ini file\n");
|
|
}
|
|
//
|
|
// Initialze the local variables
|
|
//
|
|
myTrigger = trigger;
|
|
myOldTrigger = *myTrigger;
|
|
myEffectDCS = effect_DCS;
|
|
myEffectOffset = *offset_point;
|
|
myPSFXInfo = *psfx_definition;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLPSFXRenderable
|
|
//
|
|
DPLPSFXRenderable::~DPLPSFXRenderable()
|
|
{
|
|
// !!!!HACK Note that because the effect id changes every time we start one,
|
|
// the destructor will only stop the last PFX played. We should probably
|
|
// be keeping track of all the ID's we've sent down to make sure everything
|
|
// attached to the DCS gets properly killed.
|
|
Check(this);
|
|
dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLPSFXRenderable
|
|
//
|
|
Logical
|
|
DPLPSFXRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myTrigger);
|
|
#if DEBUG_LEVEL > 0
|
|
if(myEffectDCS != NULL)
|
|
Check_Pointer(myEffectDCS);
|
|
#endif
|
|
Check(&myEffectOffset);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLPSFXRenderable.
|
|
//
|
|
void
|
|
DPLPSFXRenderable::Execute()
|
|
{
|
|
Check_Pointer(myTrigger);
|
|
if(*myTrigger != myOldTrigger)
|
|
{
|
|
myOldTrigger = *myTrigger;
|
|
if(myOldTrigger == True)
|
|
{
|
|
// we put our id into the lower 16 bits because (at least) the upper 8 bits are flags
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
myPSFXInfo.identifier =
|
|
(myPSFXInfo.identifier & 0xffff0000) |
|
|
l4_application->GetVideoRenderer()->GetUniqueID();
|
|
dpl_Effect ( dpl_effect_type_particlestart, myEffectDCS, &myPSFXInfo );
|
|
}
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLPSFXStateRenderable
|
|
// This routine triggers a pfx whenever a state dial transitions to a designated
|
|
// state.
|
|
// NOTE this currently does NOT trigger if the state dial is in the trigger state
|
|
// when this renderable is created.
|
|
//
|
|
DPLPSFXStateRenderable::DPLPSFXStateRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
StateIndicator *effect_trigger, // Trigger effect when this state changes
|
|
unsigned my_trigger, // The state to edge trigger on
|
|
dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it
|
|
dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL)
|
|
Point3D *offset_point // Offset (or world coordinants if DCS is NULL)
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check(effect_trigger);
|
|
Check_Pointer(psfx_definition);
|
|
#if DEBUG_LEVEL > 0
|
|
if(effect_DCS != NULL)
|
|
Check_Pointer(effect_DCS);
|
|
#endif
|
|
Check(offset_point);
|
|
if(!psfx_definition)
|
|
{
|
|
Fail("A pfx was not defined in the .ini file\n");
|
|
}
|
|
//
|
|
// Initialze the local variables
|
|
//
|
|
myTriggerState = my_trigger;
|
|
myStateDial = effect_trigger;
|
|
myEffectDCS = effect_DCS;
|
|
myEffectOffset = *offset_point;
|
|
myPSFXInfo = *psfx_definition;
|
|
//
|
|
// Add us to the state's watcher socket
|
|
//
|
|
effect_trigger->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLPSFXStateRenderable
|
|
//
|
|
DPLPSFXStateRenderable::~DPLPSFXStateRenderable()
|
|
{
|
|
// !!!!HACK Note that because the effect id changes every time we start one,
|
|
// the destructor will only stop the last PFX played. We should probably
|
|
// be keeping track of all the ID's we've sent down to make sure everything
|
|
// attached to the DCS gets properly killed.
|
|
Check(this);
|
|
dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLPSFXStateRenderable
|
|
//
|
|
Logical
|
|
DPLPSFXStateRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
#if DEBUG_LEVEL > 0
|
|
if(myEffectDCS != NULL)
|
|
Check_Pointer(myEffectDCS);
|
|
#endif
|
|
Check(&myEffectOffset);
|
|
Check(myStateDial);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLPSFXStateRenderable.
|
|
// Note that this will get called by the state dial, not by the renderer
|
|
//
|
|
void
|
|
DPLPSFXStateRenderable::Execute()
|
|
{
|
|
Check(myStateDial);
|
|
//
|
|
// If the state dial is in the right state, trigger
|
|
//
|
|
if(myStateDial->GetState() == myTriggerState)
|
|
{
|
|
// we put our id into the lower 16 bits because (at least) the upper 8 bits are flags
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
myPSFXInfo.identifier =
|
|
(myPSFXInfo.identifier & 0xffff0000) |
|
|
l4_application->GetVideoRenderer()->GetUniqueID();
|
|
dpl_Effect ( dpl_effect_type_particlestart, myEffectDCS, &myPSFXInfo );
|
|
}
|
|
//
|
|
// Call the next lower execute method
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLMaterialRenderable
|
|
// This renderable creates a DPL Material structure and encapsulates it so
|
|
// it will be properly deleted when the object it's part of gets deleted.
|
|
DPLMaterialRenderable::DPLMaterialRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar ambient_red, // Material's ambient component
|
|
Scalar ambient_green,
|
|
Scalar ambient_blue,
|
|
Scalar emissive_red, // Material's emissive component
|
|
Scalar emissive_green,
|
|
Scalar emissive_blue,
|
|
Scalar diffuse_red, // Material's diffuse component
|
|
Scalar diffuse_green,
|
|
Scalar diffuse_blue,
|
|
Scalar specular_red, // Material's specular component
|
|
Scalar specular_green,
|
|
Scalar specular_blue,
|
|
Scalar specular_shininess,
|
|
Scalar opacity_red, // Material's opacity
|
|
Scalar opacity_green,
|
|
Scalar opacity_blue,
|
|
dpl_TEXTURE *texture, // Material's texture pointer
|
|
Scalar z_dither, // Material's Z dither value
|
|
int fog_immune // Material's Fog Imunity value
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
// Check input pointers
|
|
#if DEBUG_LEVEL > 0
|
|
if(texture)
|
|
Check_Pointer(texture);
|
|
#endif
|
|
// Create and initialize the DPL material
|
|
myMaterial = dpl_NewMaterial();
|
|
Check_Pointer(myMaterial);
|
|
//
|
|
// Materials should be static most of the time, if they are dynamic it means someone
|
|
// inheriting from us is going to try and modify the material. So if we are dynamic
|
|
// we leave the rest of this stuff for that routine to do
|
|
//
|
|
if(execution_type == DPLMaterialRenderable::Static)
|
|
{
|
|
dpl_SetMaterialAmbient (myMaterial, ambient_red, ambient_green, ambient_blue);
|
|
dpl_SetMaterialEmissive (myMaterial, emissive_red, emissive_green, emissive_blue);
|
|
dpl_SetMaterialDiffuse (myMaterial, diffuse_red, diffuse_green, diffuse_blue);
|
|
dpl_SetMaterialSpecular (myMaterial, specular_red, specular_green, specular_blue, specular_shininess);
|
|
dpl_SetMaterialOpacity (myMaterial, opacity_red, opacity_green, opacity_blue);
|
|
if(texture)
|
|
dpl_SetMaterialTexture(myMaterial, texture);
|
|
if(z_dither)
|
|
dpl_SetMaterialDitherZ(myMaterial, z_dither);
|
|
if(fog_immune)
|
|
dpl_SetMaterialFogImmunity(myMaterial,fog_immune);
|
|
dpl_FlushMaterial(myMaterial);
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLMaterialRenderable
|
|
DPLMaterialRenderable::~DPLMaterialRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
dpl_DeleteMaterial(myMaterial);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLMaterialRenderable
|
|
Logical
|
|
DPLMaterialRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myMaterial);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DPLMaterialRenderable
|
|
void
|
|
DPLMaterialRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for MorphMaterialRenderable
|
|
// This renderable takes two material specifications and loads up a third
|
|
// material with a morph between the first two.
|
|
MorphMaterialRenderable::MorphMaterialRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
Scalar ambient_red_1, // Material's ambient component
|
|
Scalar ambient_green_1,
|
|
Scalar ambient_blue_1,
|
|
Scalar emissive_red_1, // Material's emissive component
|
|
Scalar emissive_green_1,
|
|
Scalar emissive_blue_1,
|
|
Scalar diffuse_red_1, // Material's diffuse component
|
|
Scalar diffuse_green_1,
|
|
Scalar diffuse_blue_1,
|
|
Scalar specular_red_1, // Material's specular component
|
|
Scalar specular_green_1,
|
|
Scalar specular_blue_1,
|
|
Scalar specular_shininess_1,
|
|
Scalar opacity_red_1, // Material's opacity
|
|
Scalar opacity_green_1,
|
|
Scalar opacity_blue_1,
|
|
dpl_TEXTURE *texture_1, // Material's texture pointer
|
|
Scalar z_dither_1, // Material's Z dither value
|
|
int fog_immune_1, // Material's Fog Imunity value
|
|
Scalar ambient_red_2, // Material's ambient component
|
|
Scalar ambient_green_2,
|
|
Scalar ambient_blue_2,
|
|
Scalar emissive_red_2, // Material's emissive component
|
|
Scalar emissive_green_2,
|
|
Scalar emissive_blue_2,
|
|
Scalar diffuse_red_2, // Material's diffuse component
|
|
Scalar diffuse_green_2,
|
|
Scalar diffuse_blue_2,
|
|
Scalar specular_red_2, // Material's specular component
|
|
Scalar specular_green_2,
|
|
Scalar specular_blue_2,
|
|
Scalar specular_shininess_2,
|
|
Scalar opacity_red_2, // Material's opacity
|
|
Scalar opacity_green_2,
|
|
Scalar opacity_blue_2,
|
|
Scalar z_dither_2, // Material's Z dither value
|
|
Scalar *morph_control
|
|
):
|
|
DPLMaterialRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type,
|
|
ambient_red_1, ambient_green_1, ambient_blue_1, // Material's ambient component
|
|
emissive_red_1, emissive_green_1, emissive_blue_1, // Material's emissive component
|
|
diffuse_red_1, diffuse_green_1, diffuse_blue_1, // Material's diffuse component
|
|
specular_red_1, specular_green_1, specular_blue_1, specular_shininess_1, // Material's specular component
|
|
opacity_red_1, opacity_green_1, opacity_blue_1, // Material's opacity
|
|
texture_1, // Material's texture pointer
|
|
z_dither_1, // Material's Z dither value
|
|
fog_immune_1) // Material's Fog Imunity value
|
|
{
|
|
Scalar
|
|
Weight1,
|
|
Weight2;
|
|
//
|
|
// Remember the parameters of the two materials we are morphing between
|
|
//
|
|
myAmbientRed1 = ambient_red_1; // Material's ambient component
|
|
myAmbientGreen1 = ambient_green_1;
|
|
myAmbientBlue1 = ambient_blue_1;
|
|
myEmissiveRed1 = emissive_red_1; // Material's emissive component
|
|
myEmissiveGreen1 = emissive_green_1;
|
|
myEmissiveBlue1 = emissive_blue_1;
|
|
myDiffuseRed1 = diffuse_red_1; // Material's diffuse component
|
|
myDiffuseGreen1 = diffuse_green_1;
|
|
myDiffuseBlue1 = diffuse_blue_1;
|
|
mySpecularRed1 = specular_red_1; // Material's specular component
|
|
mySpecularGreen1 = specular_green_1;
|
|
mySpecularBlue1 = specular_blue_1;
|
|
mySpecularShininess1 = specular_shininess_1;
|
|
myOpacityRed1 = opacity_red_1; // Material's opacity
|
|
myOpacityGreen1 = opacity_green_1;
|
|
myOpacityBlue1 = opacity_blue_1;
|
|
myTexture1 = texture_1; // Material's texture pointer
|
|
myZDither1 = z_dither_1; // Material's Z dither value
|
|
myFogImmune1 = fog_immune_1; // Material's Fog Imunity value
|
|
myAmbientRed2 = ambient_red_2; // Material's ambient component
|
|
myAmbientGreen2 = ambient_green_2;
|
|
myAmbientBlue2 = ambient_blue_2;
|
|
myEmissiveRed2 = emissive_red_2; // Material's emissive component
|
|
myEmissiveGreen2 = emissive_green_2;
|
|
myEmissiveBlue2 = emissive_blue_2;
|
|
myDiffuseRed2 = diffuse_red_2; // Material's diffuse component
|
|
myDiffuseGreen2 = diffuse_green_2;
|
|
myDiffuseBlue2 = diffuse_blue_2;
|
|
mySpecularRed2 = specular_red_2; // Material's specular component
|
|
mySpecularGreen2 = specular_green_2;
|
|
mySpecularBlue2 = specular_blue_2;
|
|
mySpecularShininess2 = specular_shininess_2;
|
|
myOpacityRed2 = opacity_red_2; // Material's opacity
|
|
myOpacityGreen2 = opacity_green_2;
|
|
myOpacityBlue2 = opacity_blue_2;
|
|
myZDither2 = z_dither_2; // Material's Z dither value
|
|
myMorphControl = morph_control;
|
|
oldMorphControl = *morph_control;
|
|
//
|
|
// Calculate the target material
|
|
//
|
|
Weight1 = 1.0 - oldMorphControl;
|
|
Weight2 = oldMorphControl;
|
|
myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2);
|
|
myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2);
|
|
myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2);
|
|
myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2);
|
|
myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2);
|
|
myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2);
|
|
myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2);
|
|
myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2);
|
|
myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2);
|
|
mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2);
|
|
mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2);
|
|
mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2);
|
|
mySpecularShininess = (mySpecularShininess1*Weight1) + (mySpecularShininess2*Weight2);
|
|
myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2);
|
|
myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2);
|
|
myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2);
|
|
myZDither = (myZDither1*Weight1) + (myZDither2*Weight2);
|
|
//
|
|
// Initialize the target material
|
|
//
|
|
dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue);
|
|
dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue);
|
|
dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue);
|
|
dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess);
|
|
dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue);
|
|
if(myTexture1)
|
|
dpl_SetMaterialTexture(myMaterial, myTexture1);
|
|
if(myZDither)
|
|
dpl_SetMaterialDitherZ(myMaterial,myZDither);
|
|
if(myFogImmune1)
|
|
dpl_SetMaterialFogImmunity(myMaterial,myFogImmune1);
|
|
dpl_FlushMaterial(myMaterial);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for MorphMaterialRenderable
|
|
MorphMaterialRenderable::~MorphMaterialRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the MorphMaterialRenderable
|
|
Logical
|
|
MorphMaterialRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the MorphMaterialRenderable
|
|
void
|
|
MorphMaterialRenderable::Execute()
|
|
{
|
|
Scalar
|
|
Weight1,
|
|
Weight2;
|
|
|
|
Check(this);
|
|
// See if the morph control variable has changed
|
|
if(oldMorphControl != *myMorphControl)
|
|
{
|
|
//
|
|
// Re-calculate the target material
|
|
//
|
|
oldMorphControl = *myMorphControl;
|
|
Weight1 = 1.0 - oldMorphControl;
|
|
Weight2 = oldMorphControl;
|
|
myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2);
|
|
myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2);
|
|
myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2);
|
|
myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2);
|
|
myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2);
|
|
myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2);
|
|
myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2);
|
|
myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2);
|
|
myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2);
|
|
mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2);
|
|
mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2);
|
|
mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2);
|
|
mySpecularShininess = (mySpecularShininess1*Weight1) + (mySpecularShininess2*Weight2);
|
|
myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2);
|
|
myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2);
|
|
myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2);
|
|
myZDither = (myZDither1*Weight1) + (myZDither2*Weight2);
|
|
//
|
|
// Reset the target material and flush it
|
|
// Note we don't try to morph texture or fog immune
|
|
//
|
|
dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue);
|
|
dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue);
|
|
dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue);
|
|
dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess);
|
|
dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue);
|
|
if(myZDither)
|
|
dpl_SetMaterialDitherZ(myMaterial,myZDither);
|
|
dpl_FlushMaterial(myMaterial);
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLDamageMaterialRenderable
|
|
// This renderable handles modifying a material in response to damage. We
|
|
// get the pointer to an existing DPL material on startup and we get out
|
|
// color and texture settings from that
|
|
DPLDamageMaterialRenderable::DPLDamageMaterialRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_MATERIAL *damage_material, // The material we want to control
|
|
Scalar *damage_attribute, // The attribute containing the current damage level
|
|
Scalar damage_percent // Degradation factor to make damaged material
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
Scalar
|
|
Weight1,
|
|
Weight2;
|
|
|
|
Check_Pointer(damage_material);
|
|
Check_Pointer(damage_attribute);
|
|
Verify(damage_percent >= 0.0f && damage_percent <= 1.0f);
|
|
//
|
|
// Grab the material's components, remember them and figure the target colors
|
|
//
|
|
myMaterial = damage_material;
|
|
myDamageAttribute = damage_attribute;
|
|
oldDamageAttribute = *myDamageAttribute;
|
|
dpl_GetMaterialAmbient (myMaterial, &myAmbientRed1, &myAmbientGreen1, &myAmbientBlue1);
|
|
dpl_GetMaterialEmissive (myMaterial, &myEmissiveRed1, &myEmissiveGreen1, &myEmissiveBlue1);
|
|
dpl_GetMaterialDiffuse (myMaterial, &myDiffuseRed1, &myDiffuseGreen1, &myDiffuseBlue1);
|
|
dpl_GetMaterialSpecular (myMaterial, &mySpecularRed1, &mySpecularGreen1, &mySpecularBlue1, &mySpecularShininess1);
|
|
dpl_GetMaterialOpacity (myMaterial, &myOpacityRed1, &myOpacityGreen1, &myOpacityBlue1);
|
|
myAmbientRed2 = damage_percent * myAmbientRed1; // Material's ambient component
|
|
myAmbientGreen2 = damage_percent * myAmbientGreen1;
|
|
myAmbientBlue2 = damage_percent * myAmbientBlue1;
|
|
myEmissiveRed2 = damage_percent * myEmissiveRed1; // Material's emissive component
|
|
myEmissiveGreen2 = damage_percent * myEmissiveGreen1;
|
|
myEmissiveBlue2 = damage_percent * myEmissiveBlue1;
|
|
myDiffuseRed2 = damage_percent * myDiffuseRed1; // Material's diffuse component
|
|
myDiffuseGreen2 = damage_percent * myDiffuseGreen1;
|
|
myDiffuseBlue2 = damage_percent * myDiffuseBlue1;
|
|
mySpecularRed2 = damage_percent * mySpecularRed1; // Material's specular component
|
|
mySpecularGreen2 = damage_percent * mySpecularGreen1;
|
|
mySpecularBlue2 = damage_percent * mySpecularBlue1;
|
|
mySpecularShininess2 = damage_percent * mySpecularShininess1;
|
|
myOpacityRed2 = damage_percent * myOpacityRed1; // Material's opacity
|
|
myOpacityGreen2 = damage_percent * myOpacityGreen1;
|
|
myOpacityBlue2 = damage_percent * myOpacityBlue1;
|
|
//
|
|
// Calculate the target material using the current level of damage
|
|
//
|
|
Weight1 = 1.0f - oldDamageAttribute;
|
|
Weight2 = oldDamageAttribute;
|
|
myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2);
|
|
myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2);
|
|
myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2);
|
|
myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2);
|
|
myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2);
|
|
myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2);
|
|
myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2);
|
|
myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2);
|
|
myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2);
|
|
mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2);
|
|
mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2);
|
|
mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2);
|
|
mySpecularShininess = (mySpecularShininess1*Weight1)+ (mySpecularShininess2*Weight2);
|
|
myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2);
|
|
myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2);
|
|
myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2);
|
|
//
|
|
// Set the target material
|
|
//
|
|
dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue);
|
|
dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue);
|
|
dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue);
|
|
dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess);
|
|
// dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue);
|
|
dpl_FlushMaterial(myMaterial);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLDamageMaterialRenderable
|
|
DPLDamageMaterialRenderable::~DPLDamageMaterialRenderable()
|
|
{
|
|
// Check our structure before we do anything
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLDamageMaterialRenderable
|
|
Logical
|
|
DPLDamageMaterialRenderable::TestInstance() const
|
|
{
|
|
// Call our parent's TestInstance first
|
|
VideoRenderable::TestInstance();
|
|
Check_Pointer(myMaterial);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DPLDamageMaterialRenderable
|
|
void
|
|
DPLDamageMaterialRenderable::Execute()
|
|
{
|
|
Scalar
|
|
Weight1,
|
|
Weight2;
|
|
|
|
Check(this);
|
|
if(oldDamageAttribute != *myDamageAttribute)
|
|
{
|
|
//
|
|
// Re-calculate the target material
|
|
//
|
|
oldDamageAttribute = *myDamageAttribute;
|
|
Weight1 = 1.0 - oldDamageAttribute;
|
|
Weight2 = oldDamageAttribute;
|
|
myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2);
|
|
myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2);
|
|
myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2);
|
|
myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2);
|
|
myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2);
|
|
myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2);
|
|
myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2);
|
|
myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2);
|
|
myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2);
|
|
mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2);
|
|
mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2);
|
|
mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2);
|
|
mySpecularShininess = (mySpecularShininess1*Weight1)+ (mySpecularShininess2*Weight2);
|
|
myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2);
|
|
myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2);
|
|
myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2);
|
|
//
|
|
// Reset the target material and flush it
|
|
//
|
|
dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue);
|
|
dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue);
|
|
dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue);
|
|
dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess);
|
|
// dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue);
|
|
dpl_FlushMaterial(myMaterial);
|
|
}
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~End of the new renderable class hiearchy~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~Dynamic Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~these renderables allow things to change after construction~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
//#############################################################################
|
|
// This is the DPLEyeRenderable class. This is a DYNAMIC renderable that
|
|
// places the renderer's eyepoint relative to some other DCS/renderable.
|
|
// At the moment the eyepoint won't actually move in response to an argument
|
|
// but this will be changed after we have something to hook the eye to.
|
|
//#############################################################################
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the DPLEyeRenderable
|
|
// All the arguments are required.
|
|
//
|
|
DPLEyeRenderable::DPLEyeRenderable(
|
|
Entity* This_Entity,
|
|
dpl_ZONE* This_Zone,
|
|
const LinearMatrix& Offset_Matrix,
|
|
dpl_DCS* Parent_DCS,
|
|
dpl_VIEW* This_View,
|
|
EulerAngles* eyepoint_rotation // Pointer to attribute that contains eye rotations
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(This_Entity);
|
|
Check_Pointer(This_Zone);
|
|
Check(&Offset_Matrix);
|
|
Check_Pointer(Parent_DCS);
|
|
Check_Pointer(This_View);
|
|
#if DEBUG_LEVEL > 0
|
|
if(eyepoint_rotation)
|
|
Check(eyepoint_rotation);
|
|
#endif
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that sets the eye location
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
myOrientationMatrix = Offset_Matrix;
|
|
myEyepointRotation = eyepoint_rotation;
|
|
if(myEyepointRotation)
|
|
{
|
|
oldEyepointRotation = *myEyepointRotation;
|
|
}
|
|
else
|
|
{
|
|
oldEyepointRotation = NULL;
|
|
}
|
|
//
|
|
// Create the dpl DCS for this renderable, connect it to it's parent
|
|
// and set it into the current zone.
|
|
//
|
|
myDCS = dpl_NewDCS ();
|
|
Check_Pointer(myDCS);
|
|
dpl_AddDCSToDCS ( myParentDCS, myDCS );
|
|
dpl_SetDCSZone ( myDCS, This_Zone );
|
|
//
|
|
// Load up the DCS matrix with the supplied matrix
|
|
//
|
|
LinearMatrix rotation_matrix(True);
|
|
if(myEyepointRotation)
|
|
{
|
|
rotation_matrix = *myEyepointRotation;
|
|
}
|
|
rotation_matrix *= myOrientationMatrix;
|
|
float32* dplMatrix = dpl_GetDCSMatrix(myDCS);
|
|
Check_Pointer(dplMatrix);
|
|
*((Matrix4x4*)dplMatrix) = rotation_matrix;
|
|
//
|
|
// float32* tempMatrix = dpl_GetDCSMatrix(myDCS);
|
|
// Check_Pointer(tempMatrix);
|
|
// *(Matrix4x4*)tempMatrix = OrientationMatrix;
|
|
//
|
|
// Flush out the instance and DCS
|
|
//
|
|
dpl_SetViewDCS ( This_View, myDCS);
|
|
dpl_FlushView ( This_View);
|
|
dpl_FlushDCS ( myDCS );
|
|
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLEyeRenderable
|
|
// After calling this the eyepoint must be relocated to another DCS before
|
|
// the execute method of the renderer is called.
|
|
//
|
|
DPLEyeRenderable::~DPLEyeRenderable()
|
|
{
|
|
Check(this);
|
|
// Below is probably unnecessary as the parent should be destroyed too
|
|
// but Phil is making a patch to allow us to check that.
|
|
// dpl_RemoveDCSFromDCS(myParentDCS, myDCS);
|
|
dpl_DeleteDCS(myDCS);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLEyeRenderable
|
|
//
|
|
Logical
|
|
DPLEyeRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check_Pointer(myDCS);
|
|
Check_Pointer(myParentDCS);
|
|
Check(&myOrientationMatrix);
|
|
Check(myEntity);
|
|
if(myEyepointRotation)
|
|
{
|
|
Check(myEyepointRotation);
|
|
}
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLEyeRenderable.
|
|
//
|
|
void
|
|
DPLEyeRenderable::Execute()
|
|
{
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// If we have an eyepoint rotation specified, generate a new matrix each
|
|
// time based upon the setting of the eyepoint rotation
|
|
//----------------------------------------------------------------------
|
|
//
|
|
if (myEyepointRotation)
|
|
{
|
|
if(*myEyepointRotation != oldEyepointRotation)
|
|
{
|
|
oldEyepointRotation = *myEyepointRotation;
|
|
Check(myEyepointRotation);
|
|
LinearMatrix rotation_matrix(True);
|
|
rotation_matrix = *myEyepointRotation;
|
|
rotation_matrix *= myOrientationMatrix;
|
|
float32* dplMatrix = dpl_GetDCSMatrix(myDCS);
|
|
Check_Pointer(dplMatrix);
|
|
*((Matrix4x4*)dplMatrix) = rotation_matrix;
|
|
HACK_DPL_FLUSH_DCS(myDCS);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
//#############################################################################
|
|
// This is the DPLChildPointRenderable class. This is a dynamic renderable that
|
|
// lets you build a translating joint between two objects. If you supply a
|
|
// NULL Graphic_Object pointer when constructing the renderable it will be
|
|
// built without hooking up an instance of a graphical object.
|
|
//#############################################################################
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the DPLChildPointRenderable
|
|
//
|
|
DPLChildPointRenderable::DPLChildPointRenderable(
|
|
Entity* This_Entity,
|
|
dpl_ZONE* This_Zone,
|
|
dpl_OBJECT* Graphic_Object,
|
|
dpl_ISECT_MODE Intersect_Mode,
|
|
uint32 Intersect_Mask,
|
|
const LinearMatrix &Offset_Matrix,
|
|
dpl_DCS *Parent_DCS,
|
|
Point3D *my_point
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(This_Entity);
|
|
Check_Pointer(This_Zone);
|
|
#if DEBUG_LEVEL > 0
|
|
if(Graphic_Object != NULL)
|
|
Check_Pointer(Graphic_Object);
|
|
#endif
|
|
Check(&Offset_Matrix);
|
|
Check_Pointer(Parent_DCS);
|
|
Check(my_point);
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that sets the eye location
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
myPoint = my_point;
|
|
OrientationMatrix = Offset_Matrix;
|
|
OldPoint = *my_point;
|
|
//
|
|
// Create the dpl DCS, add it to the parent DCS, set it into the current zone,
|
|
// and stuff the orientation matrix into it
|
|
//
|
|
myOffsetDCS = dpl_NewDCS();
|
|
Check_Pointer ( myOffsetDCS );
|
|
dpl_AddDCSToDCS ( myParentDCS, myOffsetDCS );
|
|
dpl_SetDCSZone ( myOffsetDCS, This_Zone );
|
|
|
|
myDCS = dpl_NewDCS();
|
|
Check_Pointer ( myDCS );
|
|
dpl_AddDCSToDCS ( myOffsetDCS, myDCS );
|
|
dpl_SetDCSZone ( myDCS, This_Zone );
|
|
//
|
|
// Setup the offset matrix in the offset DCS
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myOffsetDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = OrientationMatrix;
|
|
//
|
|
// Setup the initial state of the hinge joint
|
|
//
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
*(Matrix4x4*)tempMatrix2 = *myPoint;
|
|
//
|
|
// If there was a graphic, create an instance with that graphic in it and link
|
|
// it to the DCS.
|
|
//
|
|
if(Graphic_Object == NULL)
|
|
{
|
|
myInstance = NULL;
|
|
}
|
|
else
|
|
{
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer ( myInstance );
|
|
dpl_SetInstanceObject ( myInstance, Graphic_Object );
|
|
dpl_SetInstanceIntersect ( myInstance, Intersect_Mode );
|
|
dpl_SetInstanceSectMask ( myInstance, Intersect_Mask );
|
|
dpl_SetInstanceVisibility ( myInstance, 1 );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
//
|
|
// Flush out the DCS and add this to the static component list
|
|
//
|
|
dpl_FlushDCS ( myOffsetDCS );
|
|
dpl_FlushDCS ( myDCS );
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the DPLChildPointRenderable
|
|
//
|
|
|
|
DPLChildPointRenderable::~DPLChildPointRenderable()
|
|
{
|
|
Check(this);
|
|
// Below is probably unnecessary as the parent should be destroyed too
|
|
// but Phil is making a patch to allow us to check that.
|
|
// dpl_RemoveDCSFromDCS(myParentDCS, myDCS);
|
|
|
|
dpl_DeleteDCS(myDCS);
|
|
dpl_DeleteDCS(myOffsetDCS);
|
|
if(myInstance != NULL)
|
|
{
|
|
dpl_DeleteInstance(myInstance);
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DPLChildPointRenderable
|
|
// This method should really use a watcher to make sure the position of the
|
|
// object has changed before updating the DCS matrix.
|
|
//
|
|
void
|
|
DPLChildPointRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
//
|
|
// Load up the DCS matrix with the localToWorld matrix from the entity
|
|
// then flush out the new DCS
|
|
//
|
|
if(OldPoint != *myPoint)
|
|
{
|
|
OldPoint = *myPoint;
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
*(Matrix4x4*)tempMatrix2 = OldPoint;
|
|
HACK_DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLChildPointRenderable
|
|
//
|
|
Logical
|
|
DPLChildPointRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check_Pointer ( myDCS );
|
|
Check_Pointer ( myParentDCS );
|
|
Check_Pointer ( myOffsetDCS );
|
|
Check(myPoint);
|
|
if(myInstance != NULL)
|
|
{
|
|
Check_Pointer(myInstance);
|
|
}
|
|
Check(&OrientationMatrix);
|
|
Check(myEntity);
|
|
|
|
return True;
|
|
}
|
|
//
|
|
//#############################################################################
|
|
// This is the DPLScaleRenderable class. This is a dynamic renderable that
|
|
// lets you scale everything downstream of it in the hiearchy. It is also
|
|
// setup to switch it's own instances on and off based on the value in visible.
|
|
//#############################################################################
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the DPLScaleRenderable
|
|
//
|
|
DPLScaleRenderable::DPLScaleRenderable(
|
|
Entity* This_Entity,
|
|
dpl_ZONE* This_Zone,
|
|
dpl_OBJECT* Graphic_Object,
|
|
dpl_ISECT_MODE Intersect_Mode,
|
|
uint32 Intersect_Mask,
|
|
const LinearMatrix &Offset_Matrix,
|
|
dpl_DCS *Parent_DCS,
|
|
Vector3D *scale_vector,
|
|
Logical *visible
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(This_Entity);
|
|
Check_Pointer(This_Zone);
|
|
Check_Pointer(Graphic_Object);
|
|
Check(&Offset_Matrix);
|
|
Check_Pointer(Parent_DCS);
|
|
Check(scale_vector);
|
|
Check_Pointer(visible);
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that offsets it to the correct position.
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
myScaleVector = scale_vector;
|
|
myVisible = visible;
|
|
OffsetMatrix = Offset_Matrix;
|
|
OldScaleVector = *scale_vector;
|
|
OldVisible = *visible;
|
|
//
|
|
// Create the dpl DCS, add it to the parent DCS, set it into the current zone,
|
|
// and stuff the orientation matrix into it
|
|
//
|
|
myDCS = dpl_NewDCS();
|
|
Check_Pointer ( myDCS );
|
|
dpl_AddDCSToDCS ( myParentDCS, myDCS );
|
|
dpl_SetDCSZone ( myDCS, This_Zone );
|
|
//
|
|
// Setup the dcs matrix to it's initial state
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= OldScaleVector;
|
|
tempAffine *= OffsetMatrix;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
//
|
|
// If there was a graphic, create an instance with that graphic in it and link
|
|
// it to the DCS.
|
|
//
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer ( myInstance );
|
|
dpl_SetInstanceObject ( myInstance, Graphic_Object );
|
|
dpl_SetInstanceIntersect ( myInstance, Intersect_Mode );
|
|
dpl_SetInstanceSectMask ( myInstance, Intersect_Mask );
|
|
dpl_SetInstanceVisibility ( myInstance, OldVisible );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
dpl_FlushInstance ( myInstance );
|
|
//
|
|
// Flush out the DCS and add this to the static component list
|
|
//
|
|
dpl_FlushDCS ( myDCS );
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the DPLScaleRenderable
|
|
//
|
|
|
|
DPLScaleRenderable::~DPLScaleRenderable()
|
|
{
|
|
Check(this);
|
|
// Below is probably unnecessary as the parent should be destroyed too
|
|
// but Phil is making a patch to allow us to check that.
|
|
// dpl_RemoveDCSFromDCS(myParentDCS, myDCS);
|
|
|
|
dpl_DeleteDCS(myDCS);
|
|
dpl_DeleteInstance(myInstance);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DPLScaleRenderable
|
|
// This method should really use a watcher to make sure the position of the
|
|
// object has changed before updating the DCS matrix.
|
|
//
|
|
void
|
|
DPLScaleRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
//
|
|
// Load up the DCS matrix with the localToWorld matrix from the entity
|
|
// then flush out the new DCS
|
|
//
|
|
if(OldVisible != *myVisible)
|
|
{
|
|
OldVisible = *myVisible;
|
|
dpl_SetInstanceVisibility ( myInstance, OldVisible );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
|
|
if(OldScaleVector != *myScaleVector)
|
|
{
|
|
OldScaleVector = *myScaleVector;
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= OldScaleVector;
|
|
tempAffine *= OffsetMatrix;
|
|
*(Matrix4x4*)tempMatrix2 = tempAffine;
|
|
HACK_DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLChildRenderable
|
|
//
|
|
Logical
|
|
DPLScaleRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check_Pointer ( myDCS );
|
|
Check_Pointer ( myParentDCS );
|
|
Check_Pointer(myInstance);
|
|
Check(&OffsetMatrix);
|
|
Check(myEntity);
|
|
Check(myScaleVector);
|
|
|
|
return True;
|
|
}
|
|
//
|
|
//#############################################################################
|
|
// This is the DPLScaleQuatRenderable class. This is a dynamic renderable that
|
|
// lets you control joint position with a Quaternion, Scale with a vector and
|
|
// switch the instance on and off with a logical.
|
|
//#############################################################################
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the DPLScaleQuatRenderable
|
|
//
|
|
DPLScaleQuatRenderable::DPLScaleQuatRenderable(
|
|
Entity* This_Entity,
|
|
dpl_ZONE* This_Zone,
|
|
dpl_OBJECT* Graphic_Object,
|
|
dpl_ISECT_MODE Intersect_Mode,
|
|
uint32 Intersect_Mask,
|
|
const LinearMatrix &Offset_Matrix,
|
|
dpl_DCS *Parent_DCS,
|
|
Quaternion *rotation_quaternion,
|
|
Vector3D *scale_vector,
|
|
Logical *visible
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
Quaternion my_quat;
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(This_Entity);
|
|
Check_Pointer(This_Zone);
|
|
Check_Pointer(Graphic_Object);
|
|
Check(&Offset_Matrix);
|
|
Check_Pointer(Parent_DCS);
|
|
Check(rotation_quaternion);
|
|
Check(scale_vector);
|
|
Check_Pointer(visible);
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that offsets it to the correct position.
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
myRotationQuaternion = rotation_quaternion;
|
|
myScaleVector = scale_vector;
|
|
myVisible = visible;
|
|
OffsetMatrix = Offset_Matrix;
|
|
OldRotationQuaternion = *rotation_quaternion;
|
|
OldScaleVector = *scale_vector;
|
|
OldVisible = *visible;
|
|
//
|
|
// Create the dpl DCS, add it to the parent DCS, set it into the current zone,
|
|
// and stuff the orientation matrix into it
|
|
//
|
|
myDCS = dpl_NewDCS();
|
|
Check_Pointer ( myDCS );
|
|
dpl_AddDCSToDCS ( myParentDCS, myDCS );
|
|
dpl_SetDCSZone ( myDCS, This_Zone );
|
|
//
|
|
// Setup the dcs matrix to it's initial state
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
// tempAffine.Multiply(OldRotationQuaternion,OffsetMatrix);
|
|
tempAffine *= OldScaleVector;
|
|
tempAffine *= OldRotationQuaternion;
|
|
tempAffine *= OffsetMatrix;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
//
|
|
// If there was a graphic, create an instance with that graphic in it and link
|
|
// it to the DCS.
|
|
//
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer ( myInstance );
|
|
dpl_SetInstanceObject ( myInstance, Graphic_Object );
|
|
dpl_SetInstanceIntersect ( myInstance, Intersect_Mode );
|
|
dpl_SetInstanceSectMask ( myInstance, Intersect_Mask );
|
|
dpl_SetInstanceVisibility ( myInstance, OldVisible );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
dpl_FlushInstance ( myInstance );
|
|
//
|
|
// Flush out the DCS and add this to the static component list
|
|
//
|
|
dpl_FlushDCS ( myDCS );
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the DPLScaleQuatRenderable
|
|
//
|
|
|
|
DPLScaleQuatRenderable::~DPLScaleQuatRenderable()
|
|
{
|
|
Check(this);
|
|
// Below is probably unnecessary as the parent should be destroyed too
|
|
// but Phil is making a patch to allow us to check that.
|
|
// dpl_RemoveDCSFromDCS(myParentDCS, myDCS);
|
|
|
|
dpl_DeleteDCS(myDCS);
|
|
dpl_DeleteInstance(myInstance);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the DPLScaleQuatRenderable
|
|
// This method should really use a watcher to make sure the position of the
|
|
// object has changed before updating the DCS matrix.
|
|
//
|
|
void
|
|
DPLScaleQuatRenderable::Execute()
|
|
{
|
|
Check(this);
|
|
//
|
|
// Load up the DCS matrix with the localToWorld matrix from the entity
|
|
// then flush out the new DCS
|
|
//
|
|
if(OldVisible != *myVisible)
|
|
{
|
|
OldVisible = *myVisible;
|
|
dpl_SetInstanceVisibility ( myInstance, OldVisible );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
|
|
//
|
|
// The memcmp below is sort of a HACK but all I really care about is if the
|
|
// value in the quaternion has been changed since last time I saw it, this
|
|
// seems to be the easiest way to find out as JM hasn't written an == operator
|
|
//
|
|
if((OldScaleVector != *myScaleVector) ||
|
|
(memcmp(&OldRotationQuaternion,myRotationQuaternion, sizeof(Quaternion)) != 0))
|
|
{
|
|
OldScaleVector = *myScaleVector;
|
|
OldRotationQuaternion = *myRotationQuaternion;
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
AffineMatrix tempAffine(True);
|
|
// tempAffine.Multiply(OldRotationQuaternion,OffsetMatrix);
|
|
tempAffine *= OldScaleVector;
|
|
tempAffine *= OldRotationQuaternion;
|
|
tempAffine *= OffsetMatrix;
|
|
*(Matrix4x4*)tempMatrix2 = tempAffine;
|
|
HACK_DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLScaleQuatRenderable
|
|
//
|
|
Logical
|
|
DPLScaleQuatRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check_Pointer ( myDCS );
|
|
Check_Pointer ( myParentDCS );
|
|
Check_Pointer(myInstance);
|
|
Check(&OffsetMatrix);
|
|
Check(myEntity);
|
|
Check(myRotationQuaternion);
|
|
Check(myScaleVector);
|
|
Check_Pointer(myVisible);
|
|
|
|
return True;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~Static Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~these renderables remain constant after construction~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
//
|
|
//#############################################################################
|
|
// This is the DPLStaticChildRenderable class. This is a STATIC renderable that
|
|
// lets you build a DCS that is a child of a pre-existing DCS. If you supply a
|
|
// NULL Graphic_Object pointer when constructing the renderable it will be
|
|
// built without hooking up an instance of a graphical object.
|
|
//#############################################################################
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for the DPLStaticChildRenderable
|
|
//
|
|
DPLStaticChildRenderable::DPLStaticChildRenderable(
|
|
Entity* This_Entity,
|
|
dpl_ZONE* This_Zone,
|
|
dpl_OBJECT* Graphic_Object,
|
|
dpl_ISECT_MODE Intersect_Mode,
|
|
uint32 Intersect_Mask,
|
|
const LinearMatrix& Offset_Matrix,
|
|
dpl_DCS* Parent_DCS
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(This_Entity);
|
|
Check_Pointer(This_Zone);
|
|
Check(&Offset_Matrix);
|
|
Check_Pointer(Parent_DCS);
|
|
#if DEBUG_LEVEL > 0
|
|
if(Graphic_Object != NULL)
|
|
Check_Pointer(Graphic_Object);
|
|
#endif
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that sets the eye location
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
OrientationMatrix = Offset_Matrix;
|
|
//
|
|
// Create the dpl DCS, add it to the parent DCS, set it into the current zone,
|
|
// and stuff the orientation matrix into it
|
|
//
|
|
myDCS = dpl_NewDCS ();
|
|
Check_Pointer ( myDCS );
|
|
dpl_AddDCSToDCS ( myParentDCS, myDCS );
|
|
dpl_SetDCSZone ( myDCS, This_Zone );
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
*(Matrix4x4*)tempMatrix = OrientationMatrix;
|
|
//
|
|
// If there was a graphic, create an instance with that graphic in it and link
|
|
// it to the DCS.
|
|
//
|
|
if(Graphic_Object == NULL)
|
|
{
|
|
myInstance = NULL;
|
|
}
|
|
else
|
|
{
|
|
myInstance = dpl_NewInstance();
|
|
Check_Pointer ( myInstance );
|
|
dpl_SetInstanceObject ( myInstance, Graphic_Object );
|
|
dpl_SetInstanceIntersect ( myInstance, Intersect_Mode );
|
|
dpl_SetInstanceSectMask ( myInstance, Intersect_Mask );
|
|
dpl_SetInstanceVisibility ( myInstance, 1 );
|
|
dpl_AddInstanceToDCS ( myDCS, myInstance );
|
|
dpl_FlushInstance ( myInstance );
|
|
}
|
|
//
|
|
// Flush out the DCS and add this to the static component list
|
|
//
|
|
dpl_FlushDCS ( myDCS );
|
|
myEntity->AddStaticVideoComponent(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for the DPLStaticChildRenderable
|
|
//
|
|
|
|
DPLStaticChildRenderable::~DPLStaticChildRenderable()
|
|
{
|
|
Check(this);
|
|
// Below is probably unnecessary as the parent should be destroyed too
|
|
// but Phil is making a patch to allow us to check that.
|
|
// dpl_RemoveDCSFromDCS(myParentDCS, myDCS);
|
|
|
|
dpl_DeleteDCS(myDCS);
|
|
if(myInstance != NULL)
|
|
{
|
|
dpl_DeleteInstance(myInstance);
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLStaticChildRenderable
|
|
//
|
|
Logical
|
|
DPLStaticChildRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check_Pointer(myDCS);
|
|
Check_Pointer(myParentDCS);
|
|
if(myInstance != NULL)
|
|
{
|
|
Check_Pointer(myInstance);
|
|
}
|
|
Check(&OrientationMatrix);
|
|
Check(myEntity);
|
|
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~Special Effects Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//#############################################################################
|
|
// This is the DPLSFXRenderable class. This renderable is used to trigger a
|
|
// special effect in the world. The effect can be relative to a DCS or can be
|
|
// positioned in world coordinants by passing NULL as Parent_DCS. The trigger
|
|
// is a specific attribute entering a specific state. The effect will be
|
|
// generated repeatedly till the trigger changes state.
|
|
//
|
|
// This renderable is useful for triggering one-shot effects like puffs of smoke
|
|
// from guns or for triggering effects that the renderer will automatically
|
|
// repeat on it's own.
|
|
//#############################################################################
|
|
#define DPLSFXRenderable_MAX_RATE 28.0 // Repeat rate when speed = 1.0
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLSFXRenderable
|
|
//
|
|
DPLSFXRenderable::DPLSFXRenderable(
|
|
Entity *This_Entity, // Entity to attach the effect to
|
|
dpl_ZONE* , //*This_Zone, // DPL zone everything will be in
|
|
const Point3D &Offset_Point, // Point offset from the parent DCS
|
|
dpl_DCS *Parent_DCS, // Parent DCS (can be NULL for world)
|
|
StateIndicator *Effect_Trigger, // Trigger effect when this state changes
|
|
int Trigger_State, // Trigger effect when in this state
|
|
int Effect_Type, // Type of effect to trigger
|
|
Scalar Repeat_Speed // Effect repeat speed.
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check(This_Entity);
|
|
// Check_Pointer(This_Zone);
|
|
Check(&Offset_Point);
|
|
#if DEBUG_LEVEL > 0
|
|
if(Parent_DCS != NULL)
|
|
Check_Pointer(Parent_DCS);
|
|
#endif
|
|
Check(Effect_Trigger);
|
|
//
|
|
// Remember the entity and DCS this renderable is attached to
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
myOffsetPoint = Offset_Point;
|
|
myEffectTrigger = Effect_Trigger;
|
|
myEffectTriggerOld = myEffectTrigger->GetState();
|
|
myEffectTriggerState = Trigger_State;
|
|
myEffectType = Effect_Type;
|
|
myRepeatSpeed = 1.0/(Repeat_Speed * DPLSFXRenderable_MAX_RATE);
|
|
myLastEffect = 0.0;
|
|
//
|
|
// Register this effect as a dynamic renderable of the entity
|
|
//
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLSFXRenderable
|
|
//
|
|
DPLSFXRenderable::~DPLSFXRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLSFXRenderable
|
|
//
|
|
Logical
|
|
DPLSFXRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check(myEntity);
|
|
#if DEBUG_LEVEL > 0
|
|
if(myParentDCS != NULL)
|
|
Check_Pointer(myParentDCS);
|
|
#endif
|
|
Check(&myOffsetPoint)
|
|
Check_Pointer(myEffectTrigger);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLSFXRenderable.
|
|
// This watches the pre-assigned attribute pointer and triggers a special effect
|
|
// whenever that attribute changes.
|
|
//
|
|
void
|
|
DPLSFXRenderable::Execute()
|
|
{
|
|
Scalar
|
|
current_time;
|
|
//
|
|
// Check data we're going to use.
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
if(myParentDCS != NULL)
|
|
Check_Pointer(myParentDCS);
|
|
#endif
|
|
Check_Pointer(myEffectTrigger);
|
|
//
|
|
// Is the attribute in the trigger state?
|
|
//
|
|
if(myEffectTrigger->GetState() == myEffectTriggerState)
|
|
{
|
|
//
|
|
// The effect is on, see if this is an edge
|
|
//
|
|
if(myEffectTriggerOld != myEffectTrigger->GetState())
|
|
{
|
|
//
|
|
// An edge, reset the repeat timers so we will get an effect right now.
|
|
//
|
|
myLastEffect = 0.0;
|
|
}
|
|
//
|
|
// Is it time for another effect yet?
|
|
//
|
|
current_time = Now();
|
|
if((myLastEffect + myRepeatSpeed) < current_time)
|
|
{
|
|
//
|
|
// Trigger the effect
|
|
//
|
|
dpl_EXPLOSION_EFFECT_INFO my_explosion;
|
|
my_explosion.type = myEffectType;
|
|
my_explosion.x = myOffsetPoint.x;
|
|
my_explosion.y = myOffsetPoint.y;
|
|
my_explosion.z = myOffsetPoint.z;
|
|
dpl_Effect ( dpl_effect_type_explosion, myParentDCS, &my_explosion );
|
|
myLastEffect = current_time;
|
|
}
|
|
}
|
|
myEffectTriggerOld = myEffectTrigger->GetState();
|
|
}
|
|
//#############################################################################
|
|
// This is the DPLRepeatSFXRenderable class. This renderable is used to trigger
|
|
// a special effect that repeats periodically with the repeat rate under program
|
|
// control. The most common use will probably be generating smoke trails. If
|
|
// the density argument is set to zero, no smoke will be generated.
|
|
//#############################################################################
|
|
#define DPLRepeatSFXRenderable_MAX_RATE 5.0
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLRepeatSFXRenderable
|
|
//
|
|
DPLRepeatSFXRenderable::DPLRepeatSFXRenderable(
|
|
Entity *This_Entity,
|
|
dpl_ZONE* , //*This_Zone,
|
|
const Point3D &Offset_Point,
|
|
dpl_DCS *Parent_DCS, // offset is relative to this
|
|
int Effect_Type, // type code for the effect
|
|
Scalar *Speed
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(This_Entity);
|
|
// Check_Pointer(This_Zone);
|
|
Check(&Offset_Point);
|
|
#if DEBUG_LEVEL > 0
|
|
if(Parent_DCS != NULL)
|
|
Check_Pointer(Parent_DCS); // it is allowed to be null
|
|
#endif
|
|
Check_Pointer(Speed);
|
|
//
|
|
// Remember the entity and DCS this renderable is attached to
|
|
//
|
|
myEntity = This_Entity;
|
|
myParentDCS = Parent_DCS;
|
|
myOffsetPoint = Offset_Point;
|
|
myEffectType = Effect_Type;
|
|
mySpeed = Speed;
|
|
myLastSmoke = 0.0;
|
|
//
|
|
// Setup as a dynamic renderable
|
|
//
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLRepeatSFXRenderable
|
|
//
|
|
DPLRepeatSFXRenderable::~DPLRepeatSFXRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLRepeatSFXRenderable
|
|
//
|
|
Logical
|
|
DPLRepeatSFXRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check(myEntity);
|
|
#if DEBUG_LEVEL > 0
|
|
if(myParentDCS != NULL)
|
|
Check_Pointer(myParentDCS); // it is allowed to be null
|
|
#endif
|
|
Check(&myOffsetPoint);
|
|
Check_Pointer(mySpeed);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLRepeatSFXRenderable.
|
|
// This watches the pre-assigned attribute pointer and triggers a special effect
|
|
// whenever that attribute changes.
|
|
//
|
|
void
|
|
DPLRepeatSFXRenderable::Execute()
|
|
{
|
|
#define MAX_REPEAT_RATE 5.0
|
|
Scalar
|
|
current_time;
|
|
//
|
|
// If speed is zero, the effect is turned off so we do nothing
|
|
//
|
|
if(*mySpeed == 0.0)
|
|
{
|
|
myLastSmoke = 0.0;
|
|
return;
|
|
}
|
|
//
|
|
// Figure how often we should generate smoke, speed ranges from 0 to 1, with
|
|
// 1 being the fastest
|
|
//
|
|
current_time = Now();
|
|
if((myLastSmoke + (1.0/((*mySpeed) * DPLRepeatSFXRenderable_MAX_RATE))) < current_time)
|
|
{
|
|
dpl_EXPLOSION_EFFECT_INFO my_explosion;
|
|
myLastSmoke = current_time;
|
|
my_explosion.type = myEffectType;
|
|
my_explosion.x = myOffsetPoint.x;
|
|
my_explosion.y = myOffsetPoint.y;
|
|
my_explosion.z = myOffsetPoint.z;
|
|
dpl_Effect ( dpl_effect_type_explosion, myParentDCS, &my_explosion );
|
|
}
|
|
}
|
|
//#############################################################################
|
|
// This is the DPLTranslocationRenderable class. This renderable handles the
|
|
// entire process of doing a UFT translocation effect from the perspective of
|
|
// people watching the player. This renderable is connected to the player object
|
|
// and manages positioning itself in the world based on information from that
|
|
// object. HACK HACK HACK (this will be obsolete when RP is fixed)
|
|
//#############################################################################
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for DPLTranslocationRenderable
|
|
//
|
|
DPLTranslocationRenderable::DPLTranslocationRenderable(
|
|
Entity *This_Entity, // Entity to attach the effect to
|
|
dpl_ZONE *This_Zone, // DPL zone everything will be in
|
|
StateIndicator *Effect_Trigger, // Trigger effects off of this state dial
|
|
Point3D *Drop_Zone_Location, // Attribute that holds where the new drop will be
|
|
unsigned Drop_Zone_State
|
|
):
|
|
Component(TrivialNodeClassID)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check(This_Entity);
|
|
Check_Pointer(This_Zone);
|
|
Check(Effect_Trigger);
|
|
Check(Drop_Zone_Location);
|
|
//
|
|
// Remember the entity and DCS this renderable is attached to
|
|
//
|
|
myEntity = This_Entity;
|
|
myZone = This_Zone;
|
|
myEffectTrigger = Effect_Trigger;
|
|
myEffectTriggerOld = myEffectTrigger->GetState();
|
|
myDropZoneLocation = Drop_Zone_Location;
|
|
myDropZoneState = Drop_Zone_State;
|
|
myState = IdleState;
|
|
//
|
|
// Load up the object we're going to use for the translocation
|
|
//
|
|
dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere", dpl_load_normal );
|
|
Check_Pointer(myTranslocateSphere);
|
|
//
|
|
// Setup a DCS that we can put the effect on so it can be rotated, scaled and
|
|
// placed anywhere we want in the world.
|
|
//
|
|
myInstance = dpl_NewInstance();
|
|
myDCS = dpl_NewDCS();
|
|
Check_Pointer (myInstance);
|
|
Check_Pointer (myDCS);
|
|
dpl_AddDCSToScene (myDCS);
|
|
dpl_SetDCSZone (myDCS, myZone);
|
|
dpl_SetInstanceObject (myInstance, myTranslocateSphere);
|
|
dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj);
|
|
dpl_SetInstanceSectMask (myInstance, NULL);
|
|
dpl_SetInstanceVisibility (myInstance, False);
|
|
dpl_AddInstanceToDCS (myDCS, myInstance);
|
|
dpl_FlushInstance (myInstance);
|
|
dpl_FlushDCS (myDCS);
|
|
//
|
|
// Register this effect as a dynamic renderable of the entity
|
|
//
|
|
// myEntity->AddDynamicVideoComponent(this);
|
|
//
|
|
// HACK HACK this needs to be folded back into the new videorenderable hiearchy
|
|
myEntity->AddStaticVideoComponent(this);
|
|
L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
l4_application->GetVideoRenderer()->AddDynamicRenderable(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for DPLTranslocationRenderable
|
|
//
|
|
DPLTranslocationRenderable::~DPLTranslocationRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the DPLTranslocationRenderable
|
|
//
|
|
Logical
|
|
DPLTranslocationRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check(myEntity);
|
|
Check(myEffectTrigger);
|
|
Check_Pointer(myZone);
|
|
Check(myDropZoneLocation);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for DPLTranslocationRenderable.
|
|
// Note that the states listed here are temporary for testing and will be changed
|
|
// to player based effects as things are finalized.
|
|
//
|
|
void
|
|
DPLTranslocationRenderable::Execute()
|
|
{
|
|
Scalar
|
|
current_time,
|
|
scale_factor;
|
|
unsigned
|
|
current_trigger_state;
|
|
//
|
|
// Check data we're going to use and get our current state to a local variable
|
|
//
|
|
Check_Pointer(myEffectTrigger);
|
|
current_trigger_state = myEffectTrigger->GetState();
|
|
// HACK, because this renderable doesn't know what renderer it's on yet.
|
|
{L4Application *l4_application = Cast_Object(L4Application*, application);
|
|
Check(l4_application);
|
|
current_time = l4_application->GetVideoRenderer()->GetCurrentFrameTime();}
|
|
// current_time = myRenderer->GetCurrentFrameTime();
|
|
//
|
|
// Simple state engine to manage the death/translocation effect
|
|
//
|
|
switch(myState)
|
|
{
|
|
case IdleState:
|
|
{
|
|
//
|
|
// Watch for transition to the dropzone acquired state
|
|
//
|
|
if(current_trigger_state == myDropZoneState)
|
|
{
|
|
myState = InitialExpandState;
|
|
myEffectTimer = current_time;
|
|
scale_factor = current_time - myEffectTimer;
|
|
if(scale_factor < 0.05f)
|
|
scale_factor = 0.05f;
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
tempAffine = *myDropZoneLocation;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
dpl_SetInstanceVisibility (myInstance, True);
|
|
dpl_FlushInstance (myInstance);
|
|
HACK_DPL_FLUSH_DCS (myDCS);
|
|
}
|
|
break;
|
|
}
|
|
case InitialExpandState:
|
|
{
|
|
scale_factor = current_time - myEffectTimer;
|
|
if(scale_factor < 0.05f)
|
|
scale_factor = 0.05f;
|
|
if(scale_factor >= 1.0)
|
|
{
|
|
scale_factor = 1.0;
|
|
myState = HoldAtSizeState;
|
|
}
|
|
// Below is a hack to build a scaling identity matrix
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
tempAffine = *myDropZoneLocation;
|
|
*(Matrix4x4*)tempMatrix2 = tempAffine;
|
|
HACK_DPL_FLUSH_DCS (myDCS);
|
|
break;
|
|
}
|
|
case HoldAtSizeState:
|
|
{
|
|
if((current_time - myEffectTimer) >= 3.0)
|
|
{
|
|
myState = ColapseState;
|
|
myEffectTimer = current_time + 1.0;
|
|
}
|
|
break;
|
|
}
|
|
case ColapseState:
|
|
{
|
|
scale_factor = myEffectTimer - current_time;
|
|
if(scale_factor < 0.05f)
|
|
{
|
|
scale_factor = 0.05f;
|
|
dpl_SetInstanceVisibility (myInstance, False);
|
|
dpl_FlushInstance (myInstance);
|
|
myState = IdleState;
|
|
}
|
|
// Below is a hack to build a scaling identity matrix
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
tempAffine = *myDropZoneLocation;
|
|
*(Matrix4x4*)tempMatrix2 = tempAffine;
|
|
HACK_DPL_FLUSH_DCS (myDCS);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// This is brand new stuff as of 5/12/96
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for OnePSFXRenderable
|
|
// This renderable triggers off a single PSFX effect and then hangs around and
|
|
// kills the effect when the renderable goes away. This is useful for things
|
|
// like missiles which you want to leave a smoke trail that stops if the object
|
|
// is destroyed. You REALLY want to do this whenever you attach an effect to
|
|
// a DCS since if the DCS goes away the DPL renderer will go wackey.
|
|
//
|
|
OnePSFXRenderable::OnePSFXRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it
|
|
dpl_DCS *effect_DCS, // DCS the effect is relative to (may be NULL)
|
|
Point3D *offset_point // Offset (or world coordinants if DCS is NULL)
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
#if DEBUG_LEVEL > 0
|
|
if(effect_DCS != NULL)
|
|
Check_Pointer(effect_DCS);
|
|
#endif
|
|
Check(offset_point);
|
|
if(!psfx_definition)
|
|
{
|
|
Fail("A pfx was not defined in the .ini file\n");
|
|
}
|
|
//
|
|
// Initialze the local variables
|
|
//
|
|
myPSFXInfo = *psfx_definition;
|
|
//
|
|
// Start the PFX immediately
|
|
//
|
|
myPSFXInfo.identifier = (myPSFXInfo.identifier & 0xffff0000) | myRenderer->GetUniqueID();
|
|
dpl_Effect ( dpl_effect_type_particlestart, effect_DCS, &myPSFXInfo );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for OnePSFXRenderable
|
|
//
|
|
OnePSFXRenderable::~OnePSFXRenderable()
|
|
{
|
|
//
|
|
// Since this renderable only sends one PSFX ID down, we only have to kill
|
|
// one PSFX, no need to track how many are spawned.
|
|
//
|
|
Check(this);
|
|
dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo );
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the OnePSFXRenderable
|
|
//
|
|
Logical
|
|
OnePSFXRenderable::TestInstance() const
|
|
{
|
|
VideoRenderable::TestInstance();
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for OnePSFXRenderable.
|
|
//
|
|
void
|
|
OnePSFXRenderable::Execute()
|
|
{
|
|
// Call the next lower execute method
|
|
#if DEBUG_LEVEL > 0
|
|
VideoRenderable::Execute();
|
|
#endif
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for TranslocationRenderable
|
|
// This renderable does the UFT translocation effect from the perspective of
|
|
// someone else watching the person translocating. We connect this to the
|
|
// player object and uses information from that object to position itself.
|
|
//
|
|
TranslocationRenderable::TranslocationRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_ZONE *this_zone, // DPL zone everything will be in
|
|
StateIndicator *effect_trigger, // Trigger effects off of this state dial
|
|
Point3D *drop_zone_location, // Attribute that holds where the new drop will be
|
|
unsigned drop_zone_state // State that indicates drop zone is valid (starts effect)
|
|
):
|
|
VideoRenderable(entity, execution_type)
|
|
{
|
|
//
|
|
// Check the inbound data, note that the parent DCS could be a null pointer
|
|
//
|
|
Check_Pointer(this_zone);
|
|
Check(effect_trigger);
|
|
Check(drop_zone_location);
|
|
//
|
|
// Remember the entity and DCS this renderable is attached to
|
|
//
|
|
myZone = this_zone;
|
|
myEffectTrigger = effect_trigger;
|
|
myDropZoneLocation = drop_zone_location;
|
|
myDropZoneState = drop_zone_state;
|
|
myState = IdleState;
|
|
//
|
|
// Load up the object we're going to use for the translocation
|
|
//
|
|
dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere", dpl_load_normal );
|
|
Check_Pointer(myTranslocateSphere);
|
|
//
|
|
// Setup a DCS that we can put the effect on so it can be rotated, scaled and
|
|
// placed anywhere we want in the world.
|
|
//
|
|
myInstance = dpl_NewInstance();
|
|
myDCS = dpl_NewDCS();
|
|
Check_Pointer (myInstance);
|
|
Check_Pointer (myDCS);
|
|
dpl_AddDCSToScene (myDCS);
|
|
dpl_SetDCSZone (myDCS, myZone);
|
|
dpl_SetInstanceObject (myInstance, myTranslocateSphere);
|
|
dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj);
|
|
dpl_SetInstanceSectMask (myInstance, NULL);
|
|
dpl_SetInstanceVisibility (myInstance, False);
|
|
dpl_AddInstanceToDCS (myDCS, myInstance);
|
|
dpl_FlushInstance (myInstance);
|
|
dpl_FlushDCS (myDCS);
|
|
//
|
|
// Plug us into the watcher hook of the effect trigger state dial
|
|
//
|
|
myEffectTrigger->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for TranslocationRenderable
|
|
//
|
|
TranslocationRenderable::~TranslocationRenderable()
|
|
{
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the TranslocationRenderable
|
|
//
|
|
Logical
|
|
TranslocationRenderable::TestInstance() const
|
|
{
|
|
Component::TestInstance();
|
|
|
|
Check(myEffectTrigger);
|
|
Check_Pointer(myZone);
|
|
Check(myDropZoneLocation);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute method for TranslocationRenderable.
|
|
// Note that the states listed here are temporary for testing and will be changed
|
|
// to player based effects as things are finalized.
|
|
//
|
|
void
|
|
TranslocationRenderable::Execute()
|
|
{
|
|
Scalar
|
|
current_time,
|
|
scale_factor;
|
|
unsigned
|
|
current_trigger_state;
|
|
//
|
|
// Check data we're going to use and get our current state to a local variable
|
|
//
|
|
Check(myEffectTrigger);
|
|
current_trigger_state = myEffectTrigger->GetState();
|
|
current_time = myRenderer->GetCurrentFrameTime();
|
|
//
|
|
// Simple state engine to manage the death/translocation effect
|
|
//
|
|
// cout<<"TranslocationRenderable::Execute\n";
|
|
switch(myState)
|
|
{
|
|
case IdleState:
|
|
{
|
|
//
|
|
// Watch for transition to the dropzone acquired state
|
|
//
|
|
if(current_trigger_state == myDropZoneState)
|
|
{
|
|
myState = InitialExpandState;
|
|
myEffectTimer = current_time;
|
|
scale_factor = current_time - myEffectTimer;
|
|
if(scale_factor < 0.05f)
|
|
scale_factor = 0.05f;
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
tempAffine = *myDropZoneLocation;
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
dpl_SetInstanceVisibility (myInstance, True);
|
|
dpl_FlushInstance (myInstance);
|
|
DPL_FLUSH_DCS (myDCS);
|
|
myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"TranslocationRenderable Going Dynamic\n";
|
|
}
|
|
break;
|
|
}
|
|
case InitialExpandState:
|
|
{
|
|
scale_factor = current_time - myEffectTimer;
|
|
if(scale_factor < 0.05f)
|
|
scale_factor = 0.05f;
|
|
if(scale_factor >= 1.0)
|
|
{
|
|
scale_factor = 1.0;
|
|
myState = HoldAtSizeState;
|
|
}
|
|
// Below is a hack to build a scaling identity matrix
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
tempAffine = *myDropZoneLocation;
|
|
*(Matrix4x4*)tempMatrix2 = tempAffine;
|
|
DPL_FLUSH_DCS (myDCS);
|
|
break;
|
|
}
|
|
case HoldAtSizeState:
|
|
{
|
|
if((current_time - myEffectTimer) >= 3.0)
|
|
{
|
|
myState = ColapseState;
|
|
myEffectTimer = current_time + 1.0;
|
|
}
|
|
break;
|
|
}
|
|
case ColapseState:
|
|
{
|
|
scale_factor = myEffectTimer - current_time;
|
|
if(scale_factor < 0.05f)
|
|
{
|
|
scale_factor = 0.05f;
|
|
dpl_SetInstanceVisibility (myInstance, False);
|
|
dpl_FlushInstance (myInstance);
|
|
myState = IdleState;
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
// cout<<"TranslocationRenderable Going Static\n";
|
|
}
|
|
// Below is a hack to build a scaling identity matrix
|
|
float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix2 );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine(0,0) = scale_factor;
|
|
tempAffine(1,1) = scale_factor;
|
|
tempAffine(2,2) = scale_factor;
|
|
tempAffine = *myDropZoneLocation;
|
|
*(Matrix4x4*)tempMatrix2 = tempAffine;
|
|
DPL_FLUSH_DCS (myDCS);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for SpinScaleQuatWatcherRenderable
|
|
//
|
|
SpinScaleQuatWatcherRenderable::SpinScaleQuatWatcherRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
StateIndicator *control, // the state dial that controls this renderable
|
|
unsigned effect_trigger_state,// the state that turns on the renderable
|
|
Quaternion *rotation_quaternion,// rotates the object
|
|
Vector3D *scale_vector, // Scales the object
|
|
Scalar z_spin_rate // spins the object about z (radians/frame)
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(control);
|
|
Check(rotation_quaternion);
|
|
Check(scale_vector);
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that offsets it to the correct position.
|
|
//
|
|
myControl = control;
|
|
myTriggerState = effect_trigger_state;
|
|
myVisible = False;
|
|
myRotationQuaternion = rotation_quaternion;
|
|
myScaleVector = scale_vector;
|
|
myZSpinRate = z_spin_rate;
|
|
OldZSpin = 0;
|
|
//
|
|
// Setup the dcs matrix to it's initial state
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= (*myScaleVector);
|
|
tempAffine *= (*myRotationQuaternion);
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
dpl_FlushDCS ( myDCS );
|
|
//
|
|
// Set the instance visibility correctly
|
|
//
|
|
dpl_SetInstanceVisibility ( myInstance, myVisible );
|
|
dpl_FlushInstance ( myInstance );
|
|
//
|
|
// Plug us into the watcher hook of the effect trigger state dial
|
|
//
|
|
myControl->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for SpinScaleQuatWatcherRenderable
|
|
//
|
|
SpinScaleQuatWatcherRenderable::~SpinScaleQuatWatcherRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the SpinScaleQuatWatcherRenderable
|
|
//
|
|
Logical
|
|
SpinScaleQuatWatcherRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
ChildOffsetRenderable::TestInstance();
|
|
Check(myControl);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the SpinScaleQuatWatcherRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
SpinScaleQuatWatcherRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Check data we're going to use and get our current state to a local variable
|
|
//
|
|
// cout<<"SpinScaleQuatWatcherRenderable::Execute "<<myControl->GetState()<<"\n";
|
|
if(myControl->GetState() == myTriggerState)
|
|
{
|
|
//
|
|
// We're in the trigger state, if we aren't already visible, make us
|
|
// visible and dynamic now.
|
|
//
|
|
if(!myVisible)
|
|
{
|
|
myVisible = True;
|
|
dpl_SetInstanceVisibility ( myInstance, True );
|
|
dpl_FlushInstance ( myInstance );
|
|
myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"SpinScaleQuatWatcherRenderable Going Dynamic\n";
|
|
}
|
|
//
|
|
// Now update the beam
|
|
//
|
|
OldZSpin += myZSpinRate;
|
|
if(OldZSpin > TWO_PI)
|
|
OldZSpin -= TWO_PI;
|
|
Hinge temp_hinge(Z_Axis, OldZSpin);
|
|
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
|
|
AffineMatrix tempAffine(True);
|
|
Quaternion temp_quaternion;
|
|
temp_quaternion = temp_hinge;
|
|
tempAffine = temp_quaternion;
|
|
tempAffine *= (*myScaleVector);
|
|
tempAffine *= (*myRotationQuaternion);
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We've left the trigger state, so if we're visible we make the beam
|
|
// invisible and go static.
|
|
//
|
|
if(myVisible)
|
|
{
|
|
myVisible = False;
|
|
dpl_SetInstanceVisibility ( myInstance, False );
|
|
dpl_FlushInstance ( myInstance );
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
// cout<<"SpinScaleQuatWatcherRenderable Going Static\n";
|
|
}
|
|
}
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Constructor for ScaleQuatWatcherRenderable
|
|
//
|
|
ScaleQuatWatcherRenderable::ScaleQuatWatcherRenderable(
|
|
Entity *entity, // Entity to attach the renderable to
|
|
ExecutionType execution_type, // How/when to execute the renderable
|
|
dpl_OBJECT *graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
dpl_ZONE *this_zone, // DPL Zone this stuff will live in (for culling)
|
|
dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object
|
|
uint32 intersect_mask, // intersection mask for the object
|
|
dpl_DCS *parent_DCS, // the parent DCS we will be offsetting from
|
|
LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS
|
|
StateIndicator *control, // the state dial that controls this renderable
|
|
unsigned effect_trigger_state,// the state that turns on the renderable
|
|
Quaternion *rotation_quaternion,// rotates the object
|
|
Vector3D *scale_vector // Scales the object
|
|
):
|
|
ChildOffsetRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
execution_type, // How/when to execute the renderable
|
|
graphical_object, // object to hang on the DCS, may be a list later <NULL>
|
|
this_zone, // DPL Zone this stuff will live in (for culling)
|
|
intersect_mode, // type of intersections to do on this object
|
|
intersect_mask, // intersection mask for the object
|
|
parent_DCS, // the parent DCS we will be offsetting from
|
|
offset_matrix) // offset matrix to be applied prior to joint DCS
|
|
{
|
|
//
|
|
// Check the inbound data
|
|
//
|
|
Check(control);
|
|
Check(rotation_quaternion);
|
|
Check(scale_vector);
|
|
//
|
|
// Remember the entity that this renderable is attached to and the
|
|
// orientation matrix that offsets it to the correct position.
|
|
//
|
|
myControl = control;
|
|
myTriggerState = effect_trigger_state;
|
|
myVisible = False;
|
|
myRotationQuaternion = rotation_quaternion;
|
|
myScaleVector = scale_vector;
|
|
//
|
|
// Setup the dcs matrix to it's initial state
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= (*myScaleVector);
|
|
tempAffine *= (*myRotationQuaternion);
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
dpl_FlushDCS ( myDCS );
|
|
//
|
|
// Set the instance visibility correctly
|
|
//
|
|
dpl_SetInstanceVisibility ( myInstance, myVisible );
|
|
dpl_FlushInstance ( myInstance );
|
|
//
|
|
// Plug us into the watcher hook of the effect trigger state dial
|
|
//
|
|
myControl->AddVideoWatcher(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Destructor for ScaleQuatWatcherRenderable
|
|
//
|
|
ScaleQuatWatcherRenderable::~ScaleQuatWatcherRenderable()
|
|
{
|
|
//
|
|
// Check our structure before we do anything
|
|
//
|
|
Check(this);
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// TestInstance for the ScaleQuatWatcherRenderable
|
|
//
|
|
Logical
|
|
ScaleQuatWatcherRenderable::TestInstance() const
|
|
{
|
|
//
|
|
// Call our parent's TestInstance first
|
|
//
|
|
ChildOffsetRenderable::TestInstance();
|
|
Check(myControl);
|
|
return True;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Execute for the ScaleQuatWatcherRenderable
|
|
// Nothing to execute here so we just pass it down to the next lower level.
|
|
//
|
|
void
|
|
ScaleQuatWatcherRenderable::Execute()
|
|
{
|
|
//
|
|
// Check our variables
|
|
//
|
|
Check(this);
|
|
//
|
|
// Check data we're going to use and get our current state to a local variable
|
|
//
|
|
//cout<<"ScaleQuatWatcherRenderable::Execute "<<myControl->GetState()<<"\n";
|
|
if(myControl->GetState() == myTriggerState)
|
|
{
|
|
//
|
|
// We're in the trigger state, if we aren't already visible, make us
|
|
// visible and dynamic now.
|
|
//
|
|
if(!myVisible)
|
|
{
|
|
myVisible = True;
|
|
dpl_SetInstanceVisibility ( myInstance, True );
|
|
dpl_FlushInstance ( myInstance );
|
|
myRenderer->AddDynamicRenderable(this);
|
|
// cout<<"ScaleQuatWatcherRenderable Going Dynamic\n";
|
|
}
|
|
//
|
|
// Now update the beam
|
|
//
|
|
float32* tempMatrix = dpl_GetDCSMatrix( myDCS );
|
|
Check_Pointer ( tempMatrix );
|
|
AffineMatrix tempAffine(True);
|
|
tempAffine *= (*myScaleVector);
|
|
tempAffine *= (*myRotationQuaternion);
|
|
*(Matrix4x4*)tempMatrix = tempAffine;
|
|
DPL_FLUSH_DCS ( myDCS );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We've left the trigger state, so if we're visible we make the beam
|
|
// invisible and go static.
|
|
//
|
|
if(myVisible)
|
|
{
|
|
myVisible = False;
|
|
dpl_SetInstanceVisibility ( myInstance, False );
|
|
dpl_FlushInstance ( myInstance );
|
|
myRenderer->RemoveDynamicRenderable(this);
|
|
// cout<<"ScaleQuatWatcherRenderable Going Static\n";
|
|
}
|
|
}
|
|
// if(*myTest != myVisible)
|
|
// {
|
|
// cout<<"myTest="<<*myTest<<" myVisible="<<myVisible<<"\n";
|
|
// }
|
|
//
|
|
// Call the execute method in our parent
|
|
//
|
|
ChildOffsetRenderable::Execute();
|
|
}
|
|
|