//===========================================================================// // 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 #pragma hdrstop #if !defined(L4VIDRND_HPP) # include #endif #if !defined(VECTOR2D_HPP) # include #endif #if !defined(MATRIX_HPP) # include #endif #if !defined(MOVER_HPP) # include #endif #if !defined(PLAYER_HPP) # include #endif #if !defined(L4VIDEO_HPP) # include #endif #if !defined(NTTMGR_HPP) # include #endif #if !defined(l4APP_HPP) # include #endif #include #include #include #include #include #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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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= 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= 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;iiGetApplicationState() == 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 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 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 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 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 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 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 "<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 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 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 "<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="<