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

