Files
CydandClaude Fable 5 fdd9ac9d97 Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)
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>
2026-07-02 13:21:58 -05:00

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();
}