Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1714 lines
52 KiB
C++
1714 lines
52 KiB
C++
#include "rpl4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "rpl4vid.h"
|
|
#include "..\rp\chute.h"
|
|
#include "..\munga\door.h"
|
|
#include "..\munga\doorfram.h"
|
|
#include "..\munga_l4\l4vidrnd.h"
|
|
#include "..\munga\mission.h"
|
|
#include "..\rp\rpplayer.h"
|
|
#include "..\rp\weapsys.h"
|
|
#include "..\munga\notation.h"
|
|
#include "..\munga\namelist.h"
|
|
#include "..\rp\vtv.h"
|
|
#include "..\munga\app.h"
|
|
|
|
// RB 1/14/07
|
|
//#include <dpl\dpl.h>
|
|
//#include <dpl\dplutils.h>
|
|
//#include <dpl\dpl_vpx.h>
|
|
|
|
extern Entity
|
|
*Entity_Being_Created; // !!! temp, till callback handlers become a class
|
|
// HACK, this code makes sure the left and right engine geometry is loaded
|
|
// one time and re-used. A more generic solution using the connection
|
|
// manager will be created once we are sure it is safe to apply this
|
|
// optimization to all cases.
|
|
d3d_OBJECT
|
|
*left_engine,
|
|
*right_engine;
|
|
//
|
|
//#############################################################################
|
|
// Constructor for the video renderer
|
|
//#############################################################################
|
|
//
|
|
RPL4VideoRenderer::RPL4VideoRenderer(
|
|
HWND hWnd,
|
|
unsigned int screenWidth,
|
|
unsigned int screenHeight,
|
|
bool fullscreen,
|
|
InterestType interest_type,
|
|
InterestDepth depth_calibration
|
|
) : DPLRenderer(hWnd, screenWidth, screenHeight, fullscreen, interest_type, depth_calibration)
|
|
{
|
|
//STUBBED: DPL RB 1/14/07
|
|
vtvCount = 0;
|
|
vtvsExpected = 999;
|
|
////
|
|
//// Preload a couple of things for DPL
|
|
////
|
|
// dpl_LoadObject ( "chg", dpl_load_normal );
|
|
// dpl_LoadObject ( "rivet", dpl_load_normal );
|
|
// dpl_LoadObject ( "lsaber", dpl_load_normal );
|
|
// dpl_LoadObject ( "bst", dpl_load_normal );
|
|
// dpl_LoadObject ( "tsphere", dpl_load_normal );
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// Destructor for the video renderer
|
|
//#############################################################################
|
|
//
|
|
RPL4VideoRenderer::~RPL4VideoRenderer()
|
|
{
|
|
}
|
|
#if 0
|
|
void
|
|
RPL4VideoRenderer::MakeJointedMoverRenderables(
|
|
Entity *entity
|
|
ViewFrom view_type
|
|
)
|
|
{
|
|
bool inDeathZone
|
|
dpl_ISECT_MODE
|
|
intersect_mode;
|
|
uint32
|
|
intersect_mask;
|
|
char
|
|
my_filename[40];
|
|
dpl_LOAD_MODE
|
|
cache_mode;
|
|
|
|
JointedMover
|
|
*jointed_mover;
|
|
|
|
Verify(entity->IsDerivedFrom(JointedMover::GetClassDerivations());
|
|
jointed_mover = Cast_Object(
|
|
JointedMover*,
|
|
entity
|
|
);
|
|
|
|
cache_mode = dpl_load_nocache;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Outside or Inside View
|
|
//~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (type == inside_entity)
|
|
{
|
|
inDepthZone = true;
|
|
//buildInZone = dplDeathZone;
|
|
intersect_mode = dpl_isect_mode_obj;
|
|
intersect_mask = NULL;
|
|
skl_type = EntitySegment::SkeletonType_A;
|
|
}
|
|
else
|
|
{
|
|
inDepthZone = true;
|
|
//buildInZone = dplDeathZone;
|
|
intersect_mode = dpl_isect_mode_geometry;
|
|
intersect_mask = INTERSECT_ALL;
|
|
skl_type = EntitySegment::SkeletonType_N;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the root renderable and tie it to the entity
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
RootRenderable *this_root =
|
|
new RootRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
RootRenderable::Dynamic, // How/when to execute the renderable
|
|
NULL, // object to hang on the DCS, may be a list later <NULL>
|
|
false, // 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
|
|
Register_Object(this_root);
|
|
if(eyeRelative && (entity == GetLinkedEntity()))
|
|
{
|
|
dpl_DCS* aDCS=this_root->GetDCS();
|
|
Check_Pointer(aDCS);
|
|
Check_Pointer(dplTestEyeDCS);
|
|
dpl_AddDCSToDCS( aDCS, dplTestEyeDCS );
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// create an array for the parent DCS' sizeof(segmentTable)
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_DCS **dcs_array = new (dpl_DCS(*[jointed_mover->segmentCount]));
|
|
Register_Pointer(dcs_array);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get The Joint Subsystem
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CString *object_file_name;
|
|
JointSubsystem* joint_subsystem = jointed_mover->GetJointSubsystem();
|
|
Check(joint_subsystem);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the Segment table for this jointed Mover
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EntitySegment::SegmentTableIterator segment_iterator(jointed_mover->segmentTable);
|
|
EntitySegment *current_segment;
|
|
while ((current_segment = segment_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(current_segment);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the offset matrix
|
|
//~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
LinearMatrix offset_matrix;
|
|
offset_matrix = current_segment->GetBaseOffset();
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the parent DCS of the DCS we will be creating
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_DCS *parent_DCS;
|
|
if(!current_segment->GetParent())
|
|
{
|
|
parent_DCS = this_root->GetDCS();
|
|
}
|
|
else
|
|
{
|
|
int parent_index;
|
|
parent_index = current_segment->GetParentIndex();
|
|
Verify(
|
|
(parent_index >= 0) &&
|
|
(parent_index < jointed_mover->segmentCount)
|
|
);
|
|
parent_DCS = dcs_array[parent_index];
|
|
}
|
|
Check_Pointer(parent_DCS);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// See if this segment is a Site
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if(current_segment->IsSiteSegment())
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// If this is an eye site build the eye renderable
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if(type == insideEntity &&
|
|
strcmp(current_segment->GetName(), "siteeyepoint") == 0)
|
|
{
|
|
EulerAngles* eyepoint_rotation =
|
|
(EulerAngles*)entity->GetAttributePointer("EyepointRotation");
|
|
#if 0 //DEBUG_LEVEL > 0
|
|
DPLEyeRenderable* this_eye =
|
|
#endif
|
|
mCamera =
|
|
new DPLEyeRenderable(
|
|
entity,
|
|
false,
|
|
offset_matrix,
|
|
parent_DCS,
|
|
dplMainView,
|
|
eyepoint_rotation
|
|
);
|
|
Register_Object(this_eye);
|
|
}
|
|
continue;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the dpl object and load it
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
object_file_name = current_segment->GetVideoObjectName(skl_type);
|
|
if(object_file_name)
|
|
{
|
|
Dump(*object_file_name);
|
|
//cout<<"normal object "<<*object_file_name<<"\n";
|
|
strcpy(my_filename,*object_file_name);
|
|
*(my_filename + (strlen(my_filename) - 4)) = '\0';
|
|
this_object = dpl_LoadObject ( my_filename,cache_mode );
|
|
}
|
|
else
|
|
{
|
|
this_object = NULL;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the segment index
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int this_segment_index;
|
|
this_segment_index = current_segment->GetIndex();
|
|
Verify(
|
|
(this_segment_index >= 0) &&
|
|
(this_segment_index < jointed_mover->segmentCount)
|
|
);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// If this segment has a joint Get it
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int joint_index;
|
|
joint_index = current_segment->GetJointIndex();
|
|
Joint::JointType joint_type;
|
|
Joint *this_joint = NULL;
|
|
if(joint_index == -1)
|
|
{
|
|
joint_type = Joint::StaticJointType;
|
|
}
|
|
else
|
|
{
|
|
Verify(joint_index < joint_subsystem->GetJointCount());
|
|
this_joint = joint_subsystem->GetJoint(joint_index);
|
|
Check(this_joint);
|
|
joint_type = this_joint->GetJointType();
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Make the appropriate renderable
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
switch(joint_type)
|
|
{
|
|
case Joint::HingeXJointType:
|
|
case Joint::HingeYJointType:
|
|
case Joint::HingeZJointType:
|
|
{
|
|
HingeRenderable *this_child =
|
|
new HingeRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
HingeRenderable::Dynamic, // How/when to execute the renderable
|
|
this_object, // object to hang on the DCS, may be a list later <NULL>
|
|
false, // 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
|
|
this_joint->GetHingePtr()); // Hinge attribute we will use to control the joint
|
|
Register_Object(this_child);
|
|
dcs_array[this_segment_index] = this_child->GetDCS();
|
|
}
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
{
|
|
BallJointRenderable *this_child =
|
|
new BallJointRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
BallJointRenderable::Dynamic, // How/when to execute the renderable
|
|
this_object, // object to hang on the DCS, may be a list later <NULL>
|
|
false, // 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
|
|
this_joint->GetEulerAnglesPtr());// Euler angles to control rotation of the ball joint
|
|
Register_Object(this_child);
|
|
dcs_array[this_segment_index] = this_child->GetDCS();
|
|
break;
|
|
}
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
BallTranslateJointRenderable *this_child =
|
|
new BallTranslateJointRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
BallTranslateJointRenderable::Dynamic, // How/when to execute the renderable
|
|
this_object, // object to hang on the DCS, may be a list later <NULL>
|
|
false, // 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
|
|
this_joint->GetEulerAnglesPtr(), // Euler angles to control rotation of the ball joint
|
|
this_joint->GetTranslationPtr() // offset for the translation part of the joint
|
|
);
|
|
Register_Object(this_child);
|
|
dcs_array[this_segment_index] = this_child->GetDCS();
|
|
break;
|
|
}
|
|
case Joint::StaticJointType:
|
|
default:
|
|
{
|
|
DPLStaticChildRenderable *this_child =
|
|
new DPLStaticChildRenderable(
|
|
entity,
|
|
false,
|
|
this_object,
|
|
intersect_mode,
|
|
intersect_mask,
|
|
offset_matrix,
|
|
parent_DCS
|
|
);
|
|
Register_Object(this_child);
|
|
dcs_array[this_segment_index] = this_child->GetDCS();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Cycle through the VTV's subsystems and create the site renderables
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
for(int ii=0;ii<entity->GetSubsystemCount();++ii)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Controls Mapper is not propagated across
|
|
// the network so we must ignore it here for replicants
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (ii == VTV::ControlsMapperSubsystem)
|
|
{
|
|
continue;
|
|
}
|
|
Subsystem *current_subsystem = entity->GetSubsystem(ii);
|
|
Check(current_subsystem);
|
|
int site_index = current_subsystem->GetSegmentIndex();
|
|
if (site_index != -1)
|
|
{
|
|
EntitySegment *site_segment = entity->GetSegment(site_index);
|
|
Check(site_segment);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the parentDCS for this site
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
dpl_DCS *parent_DCS;
|
|
if(!site_segment->GetParent())
|
|
{
|
|
parent_DCS = this_root->GetDCS();
|
|
}
|
|
else
|
|
{
|
|
int parent_index;
|
|
parent_index = site_segment->GetParentIndex();
|
|
Verify(
|
|
(parent_index >= 0) &&
|
|
(parent_index < jointed_mover->segmentCount)
|
|
);
|
|
parent_DCS = dcs_array[parent_index];
|
|
}
|
|
Check_Pointer(parent_DCS);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~
|
|
// Get the base offset
|
|
//~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
LinearMatrix base_offset = site_segment->GetBaseOffset();
|
|
switch(current_subsystem->GetClassID())
|
|
{
|
|
class LaserDrillClassID:
|
|
this_object = dpl_LoadObject ( "lsaber", dpl_load_normal );
|
|
Check_Pointer(this_object);
|
|
Vector3D* laser_scale =
|
|
(Vector3D*)current_subsystem->GetAttributePointer("LaserScale");
|
|
Logical* laser_on =
|
|
(Logical*)current_subsystem->GetAttributePointer("LaserOn");
|
|
DPLScaleRenderable *this_scaler =
|
|
new DPLScaleRenderable(
|
|
entity,
|
|
buildInZone,
|
|
this_object,
|
|
dpl_isect_mode,
|
|
NULL,
|
|
base_offset,
|
|
parent_DCS,
|
|
laser_scale,
|
|
laser_on
|
|
);
|
|
Register_Object(this_scaler);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Unregister_Pointer(dcs_array);
|
|
delete[] dcs_array;
|
|
|
|
Check_Fpu();
|
|
}
|
|
#endif
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// RPL4VideoRenderer::RecurseSKLFile This routine is called recursively to
|
|
// to descend the hiearchy of a notation file and create all the renderables
|
|
// needed to get an object visible.
|
|
//
|
|
void
|
|
RPL4VideoRenderer::RecurseSKLFile(
|
|
Entity *entity,
|
|
HierarchicalDrawComponent *parent,
|
|
NotationFile *mech_skeleton,
|
|
const char *page_name,
|
|
int recursion_depth,
|
|
ViewFrom type,
|
|
int *joint_counter,
|
|
dpl_LOAD_MODE cache_mode
|
|
)
|
|
{
|
|
//STUBBED: DPL RB 1/14/07
|
|
NameList
|
|
*joint_pages,
|
|
*site_pages;
|
|
|
|
NameList::Entry
|
|
*entry;
|
|
|
|
const char
|
|
*site_page_name,
|
|
*next_joint_page_name; // The next joint name (argument to a recursive call)
|
|
|
|
const char
|
|
*object_file_name,
|
|
*my_joint_type;
|
|
|
|
char
|
|
*gun_name,
|
|
*gun_attribute_name,
|
|
my_filename[40];
|
|
|
|
int
|
|
gun_site;
|
|
|
|
|
|
|
|
#ifdef NOISY_RENDERER
|
|
int
|
|
i; // loop counter
|
|
#endif
|
|
|
|
Point3D
|
|
translation(0,0,0);
|
|
|
|
EulerAngles
|
|
rotation(0,0,0);
|
|
|
|
HierarchicalDrawComponent
|
|
*next_parent;
|
|
|
|
d3d_OBJECT *this_object = NULL;
|
|
|
|
dpl_ISECT_MODE
|
|
intersect_mode;
|
|
uint32
|
|
intersect_mask;
|
|
bool inDeathZone;
|
|
//
|
|
// get the intersect mode hooked up properly
|
|
//
|
|
if(type == insideEntity)
|
|
{
|
|
inDeathZone = true;
|
|
//buildInZone = dplDeathZone;
|
|
// intersect_mode = dpl_isect_mode_obj;
|
|
intersect_mask = NULL;
|
|
}
|
|
else
|
|
{
|
|
inDeathZone = false;
|
|
//buildInZone = dplMainZone;
|
|
// intersect_mode = dpl_isect_mode_geometry;
|
|
intersect_mask = INTERSECT_ALL;
|
|
}
|
|
//
|
|
// indent by the recursion depth and print out the current page name
|
|
//
|
|
#ifdef NOISY_RENDERER
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Tell(page_name << "\n");
|
|
#endif
|
|
//
|
|
// suck the brains out of this page to create the renderable from
|
|
//
|
|
mech_skeleton->GetEntry(page_name, "tranx" ,&translation.x);
|
|
mech_skeleton->GetEntry(page_name, "trany" ,&translation.y);
|
|
mech_skeleton->GetEntry(page_name, "tranz" ,&translation.z);
|
|
mech_skeleton->GetEntry(page_name, "pitch" ,&rotation.pitch.angle);
|
|
mech_skeleton->GetEntry(page_name, "yaw" ,&rotation.yaw.angle);
|
|
mech_skeleton->GetEntry(page_name, "roll" ,&rotation.roll.angle);
|
|
|
|
if(mech_skeleton->GetEntry(page_name, "Object" ,&object_file_name))
|
|
{
|
|
strcpy(my_filename,object_file_name);
|
|
*(my_filename + (strlen(my_filename) - 4)) = '\0';
|
|
#ifdef NOISY_RENDERER
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Tell("BGF file: " << my_filename << "\n");
|
|
#endif
|
|
// // HACK, this code makes sure the left and right engine geometry is loaded
|
|
// // one time and re-used. A more generic solution using the connection
|
|
// // manager will be created once we are sure it is safe to apply this
|
|
// // optimization to all cases.
|
|
// if( (strcmp("vra",my_filename) == 0) ||
|
|
// (strcmp("vrc",my_filename) == 0) ||
|
|
// (strcmp("vrn",my_filename) == 0) ||
|
|
// (strcmp("vrt",my_filename) == 0))
|
|
// {
|
|
// if(right_engine == 0)
|
|
// {
|
|
// char *file = new char[strlen(my_filename) + 5];
|
|
// strcpy_s(file,strlen(my_filename)+5,my_filename);
|
|
// strcat_s(file,strlen(my_filename)+5,".bgf");
|
|
// this_object = d3d_OBJECT::LoadObject ( GetDevice(), file );
|
|
// right_engine = this_object;
|
|
//// cout<<"Load right engine\n";
|
|
// }
|
|
// else
|
|
// {
|
|
// this_object = right_engine;
|
|
//// cout<<"re-use right engine\n";
|
|
// }
|
|
// }
|
|
// else if( (strcmp("vla",my_filename) == 0) ||
|
|
// (strcmp("vlc",my_filename) == 0) ||
|
|
// (strcmp("vln",my_filename) == 0) ||
|
|
// (strcmp("vlt",my_filename) == 0))
|
|
// {
|
|
// if(left_engine == 0)
|
|
// {
|
|
// char *file = new char[strlen(my_filename) + 5];
|
|
// strcpy_s(file,strlen(my_filename)+5,my_filename);
|
|
// strcat_s(file,strlen(my_filename)+5,".bgf");
|
|
// this_object = d3d_OBJECT::LoadObject ( GetDevice(), file );
|
|
// left_engine = this_object;
|
|
//// cout<<"Load left engine\n";
|
|
// }
|
|
// else
|
|
// {
|
|
// this_object = left_engine;
|
|
//// cout<<"re-use left engine\n";
|
|
// }
|
|
// }
|
|
// else
|
|
{
|
|
char *file = new char[strlen(my_filename) + 5];
|
|
strcpy_s(file,strlen(my_filename)+5,my_filename);
|
|
strcat_s(file,strlen(my_filename)+5,".bgf");
|
|
this_object = d3d_OBJECT::LoadObject ( GetDevice(), file );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this_object = NULL;
|
|
}
|
|
//
|
|
// dump out the data for me to look at
|
|
//
|
|
#ifdef NOISY_RENDERER
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Dump(translation);
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Dump(rotation);
|
|
#endif
|
|
//
|
|
// Construct the renderable to display this part of the thing
|
|
//
|
|
LinearMatrix Offset_Matrix;
|
|
Offset_Matrix = translation;
|
|
Offset_Matrix = rotation;
|
|
my_joint_type = "none";
|
|
mech_skeleton->GetEntry(page_name, "Type" ,&my_joint_type);
|
|
if(recursion_depth>1)
|
|
(*joint_counter)++;
|
|
if(strncmp(my_joint_type,"hinge",5) == 0)
|
|
{
|
|
Tell("Hinge Joint " << (*joint_counter) << "\n");
|
|
|
|
VTV *vtv = (VTV*) entity;
|
|
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
|
|
Verify(
|
|
(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
|
|
Joint::HingeXJointType) ||
|
|
(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
|
|
Joint::HingeYJointType) ||
|
|
(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
|
|
Joint::HingeZJointType)
|
|
);
|
|
const Hinge *hinge_joint =
|
|
&joint_subsystem->GetJoint(*joint_counter)->GetHinge();
|
|
HingeRenderable *this_child =
|
|
new HingeRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
HingeRenderable::Dynamic, // How/when to execute the renderable
|
|
this_object, // object to hang on the DCS, may be a list later <NULL>
|
|
inDeathZone, // 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, // the parent DCS we will be offsetting from
|
|
&Offset_Matrix, // offset matrix to be applied prior to joint DCS
|
|
hinge_joint); // Hinge attribute we will use to control the joint
|
|
Register_Object(this_child);
|
|
next_parent = this_child;
|
|
}
|
|
else if(strcmp(my_joint_type,"ball") == 0)
|
|
{
|
|
Tell("Ball Joint " << (*joint_counter) << "\n");
|
|
VTV *vtv = (VTV*) entity;
|
|
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
|
|
const EulerAngles *euler_angles =
|
|
&joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles();
|
|
Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
|
|
Joint::BallJointType);
|
|
BallJointRenderable *this_child =
|
|
new BallJointRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
BallJointRenderable::Dynamic, // How/when to execute the renderable
|
|
this_object, // object to hang on the DCS, may be a list later <NULL>
|
|
false, // 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, // the parent DCS we will be offsetting from
|
|
&Offset_Matrix, // offset matrix to be applied prior to joint DCS
|
|
euler_angles); // Euler angles to control rotation of the ball joint
|
|
Register_Object(this_child);
|
|
next_parent = this_child;
|
|
}
|
|
else if(strcmp(my_joint_type,"balltranslate") == 0)
|
|
{
|
|
Tell("Ball Translation Joint " << (*joint_counter) << "\n");
|
|
VTV *vtv = (VTV*) entity;
|
|
JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
|
|
const EulerAngles *euler_angles =
|
|
&joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles();
|
|
const Point3D *point_3D =
|
|
&joint_subsystem->GetJoint(*joint_counter)->GetTranslation();
|
|
|
|
Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() ==
|
|
Joint::BallTranslationJointType);
|
|
BallTranslateJointRenderable *this_child =
|
|
new BallTranslateJointRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
BallTranslateJointRenderable::Dynamic, // How/when to execute the renderable
|
|
this_object, // object to hang on the DCS, may be a list later <NULL>
|
|
false, // 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, // the parent DCS we will be offsetting from
|
|
&Offset_Matrix, // offset matrix to be applied prior to joint DCS
|
|
euler_angles, // Euler angles to control rotation of the ball joint
|
|
point_3D); // offset for the translation part of the joint
|
|
Register_Object(this_child);
|
|
next_parent = this_child;
|
|
}
|
|
else
|
|
{
|
|
// Tell("Static Joint" << (*joint_counter) << "\n");
|
|
DPLStaticChildRenderable *this_child =
|
|
new DPLStaticChildRenderable(
|
|
entity,
|
|
inDeathZone,
|
|
this_object,
|
|
intersect_mode,
|
|
intersect_mask,
|
|
Offset_Matrix,
|
|
parent
|
|
);
|
|
Register_Object(this_child);
|
|
next_parent = this_child;
|
|
}
|
|
//
|
|
// Get a the list of joint pages from the current page
|
|
//
|
|
if(type == insideEntity)
|
|
{
|
|
// dpl_SetDCSNearField ( next_parent_dcs, True );
|
|
// dpl_FlushDCS(next_parent_dcs);
|
|
}
|
|
joint_pages = mech_skeleton->MakeEntryList(page_name,"joint");
|
|
Register_Object(joint_pages);
|
|
recursion_depth++;
|
|
//
|
|
// Recursively process all the joint pages on the current page
|
|
//
|
|
for( entry = joint_pages->GetFirstEntry();
|
|
entry;
|
|
entry = entry->GetNextEntry())
|
|
{
|
|
// Get the name of the next joint page
|
|
next_joint_page_name = (char *)entry->dataReference;
|
|
// Process the next page recursively through this routine
|
|
RecurseSKLFile(
|
|
entity,
|
|
next_parent,
|
|
mech_skeleton,
|
|
next_joint_page_name,
|
|
recursion_depth,
|
|
type,
|
|
joint_counter,
|
|
cache_mode);
|
|
}
|
|
//
|
|
// now check the list of sites for stuff to hook up
|
|
//
|
|
site_pages = mech_skeleton->MakeEntryList(page_name,"site");
|
|
Register_Object(site_pages);
|
|
//
|
|
// process all the site pages on the current page
|
|
//
|
|
for( entry = site_pages->GetFirstEntry();
|
|
entry;
|
|
entry = entry->GetNextEntry())
|
|
{
|
|
// Get the name of the next joint page
|
|
site_page_name = (char *)entry->dataReference;
|
|
//
|
|
// Setup a eyepoint site, connect it to a rotation attribute so we can move it
|
|
// arround.
|
|
//
|
|
if(type == insideEntity &&
|
|
strcmp(site_page_name, "siteeyepoint") == 0)
|
|
{
|
|
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
|
|
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
|
|
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
|
|
mech_skeleton->GetEntry(site_page_name, "pitch" ,&rotation.pitch.angle);
|
|
mech_skeleton->GetEntry(site_page_name, "yaw" ,&rotation.yaw.angle);
|
|
mech_skeleton->GetEntry(site_page_name, "roll" ,&rotation.roll.angle);
|
|
#ifdef NOISY_RENDERER
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Tell(site_page_name << "\n");
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Dump(translation);
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Dump(rotation);
|
|
#endif
|
|
EulerAngles* eyepoint_rotation = (EulerAngles*)entity->GetAttributePointer("EyepointRotation");
|
|
Offset_Matrix = translation;
|
|
Offset_Matrix = rotation;
|
|
#if 0 //DEBUG_LEVEL > 0
|
|
DPLEyeRenderable* this_eye =
|
|
#endif
|
|
mCamera =
|
|
new DPLEyeRenderable(
|
|
entity,
|
|
// buildInZone,
|
|
Offset_Matrix,
|
|
next_parent,
|
|
eyepoint_rotation
|
|
);
|
|
Register_Object(this_eye);
|
|
}
|
|
//
|
|
// Setup a gunport site, this works for all the sites
|
|
// this is kind of funky but will be replaced as the VID file goes on line.
|
|
// !!! Hack
|
|
//
|
|
gun_site = False;
|
|
gun_name = "";
|
|
gun_attribute_name = "";
|
|
if(strcmp(site_page_name,"sitefrontrightport") == 0)
|
|
{
|
|
gun_site = True;
|
|
gun_name = "LaserGun1";
|
|
gun_attribute_name = "FrontLaserOn";
|
|
}
|
|
else if(strcmp(site_page_name,"sitefrontleftport") == 0)
|
|
{
|
|
gun_site = True;
|
|
gun_name = "LaserGun2";
|
|
gun_attribute_name = "FrontLaserOn";
|
|
}
|
|
else if(strcmp(site_page_name,"sitefrontcenterport") == 0)
|
|
{
|
|
gun_site = True;
|
|
gun_name = "LaserGun";
|
|
gun_attribute_name = "FrontLaserOn";
|
|
}
|
|
else if(strcmp(site_page_name,"sitebackrightport") == 0)
|
|
{
|
|
gun_site = True;
|
|
gun_name = "LaserGun1";
|
|
gun_attribute_name = "RearLaserOn";
|
|
}
|
|
else if(strcmp(site_page_name,"sitebackleftport") == 0)
|
|
{
|
|
gun_site = True;
|
|
gun_name = "LaserGun2";
|
|
gun_attribute_name = "RearLaserOn";
|
|
}
|
|
else if(strcmp(site_page_name,"sitebackcenterport") == 0)
|
|
{
|
|
gun_site = True;
|
|
gun_name = "LaserGun";
|
|
gun_attribute_name = "RearLaserOn";
|
|
}
|
|
if(gun_site)
|
|
{
|
|
LaserGun* laser_subsystem=
|
|
(LaserGun*)entity->FindSubsystem(gun_name);
|
|
if(laser_subsystem)
|
|
{
|
|
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
|
|
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
|
|
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
|
|
mech_skeleton->GetEntry(site_page_name, "pitch" ,&rotation.pitch.angle);
|
|
mech_skeleton->GetEntry(site_page_name, "yaw" ,&rotation.yaw.angle);
|
|
mech_skeleton->GetEntry(site_page_name, "roll" ,&rotation.roll.angle);
|
|
Vector3D* laser_scale =
|
|
(Vector3D*)laser_subsystem->GetAttributePointer("LaserScale");
|
|
Logical* laser_on =
|
|
(Logical*)laser_subsystem->GetAttributePointer(gun_attribute_name);
|
|
this_object = d3d_OBJECT::LoadObject ( GetDevice(), "lsaber.bgf" );
|
|
|
|
if( laser_subsystem && laser_scale && laser_on && this_object)
|
|
{
|
|
Tell("Hooked "<<gun_name<<" to site "<<site_page_name<<"\n");
|
|
Check(laser_scale);
|
|
Check_Pointer(laser_on);
|
|
Offset_Matrix.BuildIdentity();
|
|
Offset_Matrix = translation;
|
|
Offset_Matrix = rotation;
|
|
#if DEBUG_LEVEL > 0
|
|
DPLScaleRenderable *this_scaler =
|
|
#endif
|
|
new DPLScaleRenderable(
|
|
entity,
|
|
inDeathZone,
|
|
this_object,
|
|
intersect_mode,
|
|
intersect_mask,
|
|
Offset_Matrix,
|
|
next_parent,
|
|
laser_scale,
|
|
laser_on);
|
|
Register_Object(this_scaler);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Setup a chute site, get the position and attributes to control it and bind
|
|
// them all up for use.
|
|
//
|
|
if(strcmp(site_page_name, "sitechute") == 0)
|
|
{
|
|
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
|
|
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
|
|
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
|
|
Chute* chute_subsystem=
|
|
(Chute*)entity->FindSubsystem("Chute");
|
|
if (chute_subsystem)
|
|
{
|
|
Check(chute_subsystem);
|
|
Quaternion* chute_rotation =
|
|
(Quaternion*)chute_subsystem->GetAttributePointer("ChuteDirection");
|
|
Vector3D* chute_scale =
|
|
(Vector3D*)chute_subsystem->GetAttributePointer("ScaleFactor");
|
|
Logical* chute_open =
|
|
(Logical*)chute_subsystem->GetAttributePointer("ChuteOn");
|
|
this_object = d3d_OBJECT::LoadObject ( GetDevice(), "cht.bgf" );
|
|
if(chute_rotation && chute_scale && chute_open && this_object)
|
|
{
|
|
Check(chute_rotation);
|
|
Check(chute_scale);
|
|
Check_Pointer(chute_open);
|
|
Check_Pointer(this_object);
|
|
Offset_Matrix.BuildIdentity();
|
|
Offset_Matrix = translation;
|
|
#if DEBUG_LEVEL > 0
|
|
DPLScaleQuatRenderable *this_scaler =
|
|
#endif
|
|
new DPLScaleQuatRenderable(
|
|
entity,
|
|
inDeathZone,
|
|
this_object,
|
|
intersect_mode,
|
|
intersect_mask,
|
|
Offset_Matrix,
|
|
next_parent,
|
|
chute_rotation,
|
|
chute_scale,
|
|
chute_open);
|
|
Register_Object(this_scaler);
|
|
}
|
|
else
|
|
{
|
|
if(!chute_rotation)
|
|
DEBUG_STREAM<<"ChuteSite couldn't find ChuteDirection attribute\n" << std::flush;
|
|
if(!chute_scale)
|
|
DEBUG_STREAM<<"ChuteSite couldn't find ChuteScale attribute\n" << std::flush;
|
|
if(!chute_open)
|
|
DEBUG_STREAM<<"ChuteSite couldn't find ChuteOn attribute\n" << std::flush;
|
|
if(!this_object)
|
|
DEBUG_STREAM<<"ChuteSite couldn't find chute DPL object\n" << std::flush;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Setup a booster site, get the site position and the attribute(s) that will
|
|
// control the booster. Setup origin matrix and renderables to control the
|
|
// appearance of the booster.
|
|
//
|
|
if(strcmp(site_page_name, "sitebooster") == 0)
|
|
{
|
|
#ifdef NOISY_RENDERER
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Tell(site_page_name << "\n");
|
|
Tell(recursion_depth);
|
|
for (i = 0; i < recursion_depth; i++)
|
|
Tell("..");
|
|
Dump(translation);
|
|
#endif
|
|
mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x);
|
|
mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y);
|
|
mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z);
|
|
Vector3D* booster_scale =
|
|
(Vector3D*)entity->GetAttributePointer("BoosterScale");
|
|
Logical* booster_on =
|
|
(Logical*)entity->GetAttributePointer("BoosterOn");
|
|
this_object = d3d_OBJECT::LoadObject ( GetDevice(), "bst.bgf" );
|
|
if( booster_scale && booster_on && this_object)
|
|
{
|
|
Check(booster_scale);
|
|
Check_Pointer(booster_on);
|
|
Offset_Matrix.BuildIdentity();
|
|
Offset_Matrix = translation;
|
|
#if DEBUG_LEVEL > 0
|
|
DPLScaleRenderable* this_scaler =
|
|
#endif
|
|
/*new DPLScaleRenderable(
|
|
entity,
|
|
inDeathZone,
|
|
this_object,
|
|
intersect_mode,
|
|
intersect_mask,
|
|
Offset_Matrix,
|
|
next_parent,
|
|
booster_scale,
|
|
booster_on);*/
|
|
}
|
|
else
|
|
{
|
|
if(!booster_scale)
|
|
DEBUG_STREAM<<"BoosterSite couldn't find BoosterScale attribute\n" << std::flush;
|
|
if(!booster_on)
|
|
DEBUG_STREAM<<"BoosterSite couldn't find BoosterOn attribute\n" << std::flush;
|
|
if(!this_object)
|
|
DEBUG_STREAM<<"BoosterSite couldn't find booster DPL object\n" << std::flush;
|
|
}
|
|
Scalar* booster_smoke_density =
|
|
(Scalar*)entity->GetAttributePointer("BoosterSmokeDensity");
|
|
if( booster_smoke_density )
|
|
{
|
|
translation.z +=3.0;
|
|
#if 1
|
|
#if DEBUG_LEVEL > 0
|
|
DPLRepeatSFXRenderable* this_effect =
|
|
#endif
|
|
new DPLRepeatSFXRenderable(
|
|
entity,
|
|
inDeathZone,
|
|
translation,
|
|
next_parent, // offset is relative to this
|
|
0, // type code for the effect
|
|
booster_smoke_density);
|
|
Register_Object(this_effect);
|
|
#else
|
|
DPLPSFXRenderable* this_effect =
|
|
new DPLPSFXRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
DPLPSFXRenderable::Dynamic, // How/when to execute the renderable
|
|
booster_on, // address containing the trigger
|
|
myPSFXDescriptons[4], // Pointer to the psfx description in memory
|
|
next_parent_dcs, // DCS the effect is relative to (may be NULL)
|
|
&translation); // Offset (or world coordinants if DCS is NULL)
|
|
Register_Object(this_effect);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if(!booster_smoke_density)
|
|
DEBUG_STREAM<<"BoosterSite couldn't find BoosterSmokeDensity attribute\n" << std::flush;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// Unregister the namelist objects we created in this subroutine
|
|
//
|
|
Check(joint_pages);
|
|
Unregister_Object(joint_pages);
|
|
delete joint_pages;
|
|
Check(site_pages);
|
|
Unregister_Object(site_pages);
|
|
delete site_pages;
|
|
}
|
|
|
|
|
|
//
|
|
//#############################################################################
|
|
// This starts the process for of reading in a .skl file for a vtv.
|
|
//#############################################################################
|
|
//
|
|
HierarchicalDrawComponent*
|
|
RPL4VideoRenderer::ReadSKLFile(
|
|
Entity *entity, // The entity we are dealing with
|
|
ResourceDescription *model_resource, // Pointer to the video resource
|
|
ViewFrom type, // type of reference to create
|
|
char skeleton_type) // TEMPORARY!!!! to handle color substitutions
|
|
{
|
|
//STUBBED: DPL RB 1/14/07
|
|
//dpl_ZONE
|
|
// *buildInZone;
|
|
bool inDeathZone;
|
|
int
|
|
joint_counter;
|
|
char
|
|
*skl_filename,
|
|
TempFileName[256];
|
|
NotationFile
|
|
*object_skeleton;
|
|
dpl_ISECT_MODE
|
|
intersect_mode;
|
|
uint32
|
|
intersect_mask;
|
|
// test code for load size reduction
|
|
left_engine = 0;
|
|
right_engine = 0;
|
|
//
|
|
// Currently, the name of the .skl file to read in is in the video resource
|
|
// After reading in the .skl file we die if the page count was zero,
|
|
// indicating an empty file.
|
|
//
|
|
strcpy(TempFileName,"video\\");
|
|
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|
// HACK to test video resource format changes
|
|
skl_filename = (char *)model_resource->resourceAddress;
|
|
skl_filename += sizeof(int);
|
|
strcat(TempFileName, skl_filename);
|
|
//strcat(TempFileName, ".skl");
|
|
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
|
// !!! Temporary hack to get proper vtv skl file to load
|
|
TempFileName[8] = skeleton_type;
|
|
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
#ifdef NOISY_RENDERER
|
|
Tell("RPL4VID.cpp loading .skl file "<<TempFileName<<"\n");
|
|
#endif
|
|
object_skeleton = new NotationFile(TempFileName);
|
|
if(object_skeleton->PageCount() == 0)
|
|
{
|
|
DEBUG_STREAM << "RPL4VID.cpp couldn't load .skl file "<<TempFileName<<"\n" << std::flush;
|
|
delete object_skeleton;
|
|
return NULL;
|
|
}
|
|
//
|
|
// Register the notation file and check it
|
|
//
|
|
Register_Object(object_skeleton);
|
|
Check(object_skeleton);
|
|
|
|
//
|
|
// Create the root renderable and tie it to the entity
|
|
//
|
|
if(type == insideEntity)
|
|
{
|
|
inDeathZone = true;
|
|
//buildInZone = dplDeathZone;
|
|
// intersect_mode = dpl_isect_mode_obj;
|
|
intersect_mask = NULL;
|
|
}
|
|
else
|
|
{
|
|
inDeathZone = false;
|
|
//buildInZone = dplMainZone;
|
|
// intersect_mode = dpl_isect_mode_geometry;
|
|
intersect_mask = INTERSECT_ALL;
|
|
}
|
|
|
|
RootRenderable *this_root =
|
|
new RootRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
RootRenderable::Dynamic, // How/when to execute the renderable
|
|
NULL, // object to hang on the DCS, may be a list later <NULL>
|
|
inDeathZone, // 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
|
|
Register_Object(this_root);
|
|
|
|
if(eyeRelative && entity == GetLinkedEntity())
|
|
{
|
|
dpl_DCS* aDCS=this_root->GetDCS();
|
|
Check_Pointer(aDCS);
|
|
Check_Pointer(dplTestEyeDCS);
|
|
// dpl_AddDCSToDCS( aDCS, dplTestEyeDCS );
|
|
}
|
|
|
|
//
|
|
// Process all the interesting notation file pages
|
|
//
|
|
Check(object_skeleton);
|
|
joint_counter = -1;
|
|
LinearMatrix starting_matrix(True);
|
|
dpl_LOAD_MODE dpl_load_nocache;
|
|
RecurseSKLFile(
|
|
entity,
|
|
this_root,
|
|
object_skeleton,
|
|
"ROOT",
|
|
1,
|
|
type,
|
|
&joint_counter,
|
|
dpl_load_nocache);
|
|
//
|
|
// Close the notation file
|
|
//
|
|
Unregister_Object(object_skeleton);
|
|
delete object_skeleton;
|
|
return this_root;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// This is the routine that will eventually process the script to create all
|
|
// the renderables necessary to get an object on the screen. For the moment it
|
|
// is just executing a hardwired script.
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RPL4VideoRenderer::MakeEntityRenderables(
|
|
Entity *entity, // The entity we are dealing with
|
|
ResourceDescription *model_resource, // Pointer to the video resource
|
|
ViewFrom view_type) // Type of reference (inside/outside...etc.)
|
|
|
|
{
|
|
#define MAX_DOS_FILENAME 15
|
|
HierarchicalDrawComponent
|
|
*root;
|
|
//
|
|
// Make sure the callback system knows what entity is being created
|
|
// !!!! This global will be replaced later.
|
|
//
|
|
Entity_Being_Created = entity;
|
|
//
|
|
// Examine the class id of the entity and call the appropriate creation script.
|
|
// If we don't recognize the entity ID here we fall through to the inhereted
|
|
// level and let it take care of it.
|
|
//
|
|
switch(entity->GetClassID())
|
|
{
|
|
case VTVClassID:
|
|
{
|
|
vtvCount++;
|
|
Tell("-------Creating VTV #"<<vtvCount<<"-------\n");
|
|
//
|
|
// Call routine to setup material substitution
|
|
//
|
|
char geo_sub = SetupMaterialSubstitutionList(entity,view_type);
|
|
//
|
|
// Go on with VTV creation
|
|
//
|
|
root = ReadSKLFile(entity,model_resource,view_type,geo_sub);
|
|
if(view_type == insideEntity)
|
|
{
|
|
//
|
|
// Script for renderables needed for inside view of the vehicle
|
|
//
|
|
vehicleReticle = (Reticle *)entity->GetAttributePointer("TargetReticle");
|
|
if(vehicleReticle)
|
|
{
|
|
Tell("RPL4VideoRenderer::vehicleReticle should be hooked up\n");
|
|
mReticle = new ReticleRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
ReticleRenderable::Dynamic, // How/when to execute the renderable
|
|
&vehicleReticle, // Pointer to the reticle structure in the entity
|
|
dplMainView); // the view associated with our eye
|
|
|
|
Register_Object(this_reticle);
|
|
}
|
|
else
|
|
{
|
|
Tell("RPL4VideoRenderer::vehicleReticle NOT hooked up\n");
|
|
}
|
|
StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
|
|
if(simulation_state)
|
|
{
|
|
Tell("RPL4VideoRenderer::translocate effect hooked up\n");
|
|
#if DEBUG_LEVEL > 0
|
|
POVTranslocateRenderable* translocate =
|
|
#endif
|
|
new POVTranslocateRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
POVTranslocateRenderable::Watcher, // How/when to execute the renderable
|
|
true, // DPL zone the world is in
|
|
dplDeathZone, // DPL zone the player's VTV and death effect are in
|
|
root, // the parent DCS we will be offsetting from
|
|
simulation_state, // State dial we use to control the translocation
|
|
VTV::BurningState); // State that controls start/end of the effect
|
|
Register_Object(translocate);
|
|
}
|
|
else
|
|
{
|
|
Tell("RPL4VideoRenderer::translocate effect NOT hooked up\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Script for renderables needed for outside view of the vehicle
|
|
//
|
|
Point3D my_offset_point(0.0, 0.0, 0.0);
|
|
StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
|
|
if(simulation_state)
|
|
{
|
|
Tell("RPL4VideoRenderer::death effect hooked up\n");
|
|
#if 1
|
|
#if DEBUG_LEVEL > 0
|
|
DPLSFXRenderable* my_death_effect =
|
|
#endif
|
|
new DPLSFXRenderable(
|
|
entity, // Entity to attach the effect to
|
|
false, // DPL zone everything will be in
|
|
my_offset_point, // Point offset from the parent DCS
|
|
root, // Parent DCS (can be NULL for world)
|
|
simulation_state, // Trigger effect when this attribute changes
|
|
VTV::BurningState, // Trigger effect when in this state
|
|
6, // Type of effect to trigger
|
|
0.1); // Effect repeat speed.
|
|
#else
|
|
#if DEBUG_LEVEL > 0
|
|
DPLPSFXStateRenderable* my_death_effect =
|
|
#endif
|
|
new DPLPSFXStateRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
DPLPSFXStateRenderable::Watcher, // How/when to execute the renderable
|
|
simulation_state, // Trigger effect when this state changes
|
|
VTV::BurningState, // The state to edge trigger on
|
|
myPSFXDescriptons[2], // name of file with the PFX description in it
|
|
root_DCS, // DCS the effect is relative to (may be NULL)
|
|
&my_offset_point); // Offset (or world coordinants if DCS is NULL)
|
|
#endif
|
|
Register_Object(my_death_effect);
|
|
}
|
|
else
|
|
{
|
|
Tell("RPL4VideoRenderer::death effect NOT hooked up\n");
|
|
}
|
|
StateIndicator* collision_state = (StateIndicator *)entity->GetAttributePointer("CollisionState");
|
|
if(simulation_state)
|
|
{
|
|
Tell("RPL4VideoRenderer::collision effects hooked up\n");
|
|
#if DEBUG_LEVEL > 0
|
|
DPLSFXRenderable* initial_collision_effect =
|
|
#endif
|
|
new DPLSFXRenderable(
|
|
entity, // Entity to attach the effect to
|
|
false, // DPL zone everything will be in
|
|
my_offset_point, // Point offset from the parent DCS
|
|
root, // Parent DCS (can be NULL for world)
|
|
collision_state, // Trigger effect when this attribute changes
|
|
VTV::InitialHitState, // Trigger effect when in this state
|
|
1, // Type of effect to trigger
|
|
0.1); // Effect repeat speed.
|
|
Register_Object(initial_collision_effect);
|
|
#if DEBUG_LEVEL > 0
|
|
DPLSFXRenderable* scrape_collision_effect =
|
|
#endif
|
|
new DPLSFXRenderable(
|
|
entity, // Entity to attach the effect to
|
|
false, // DPL zone everything will be in
|
|
my_offset_point, // Point offset from the parent DCS
|
|
root, // Parent DCS (can be NULL for world)
|
|
collision_state, // Trigger effect when this attribute changes
|
|
VTV::SlideState, // Trigger effect when in this state
|
|
1, // Type of effect to trigger
|
|
0.1); // Effect repeat speed.
|
|
Register_Object(scrape_collision_effect);
|
|
}
|
|
else
|
|
{
|
|
Tell("RPL4VideoRenderer::collision effects NOT hooked up\n");
|
|
}
|
|
}
|
|
//
|
|
// Teardown the vtv materal substitution namelists and disconnect DPL substitution handler
|
|
//
|
|
TearDownMaterialSubstitutionList();
|
|
#if 0
|
|
//
|
|
// Check for all players loaded
|
|
//
|
|
if((vtvCount >= vtvsExpected) &&
|
|
(GetRendererStatus() == LoadingRendererStatus))
|
|
{
|
|
Tell("Renderer Status set to running in RPL4VideoRenderer::MakeEntityRenderables\n");
|
|
SetRendererStatusToRunning();
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
//
|
|
// This constructs the renderables needed for the player class
|
|
//
|
|
case CrusherClassID:
|
|
case BlockerClassID:
|
|
case RunnerClassID:
|
|
case PlayerClassID:
|
|
case RPPlayerClassID:
|
|
{
|
|
//
|
|
// We need to construct the translocate effect but only if this is a
|
|
// player on another computer. We check this by asking if this is
|
|
// a replicant instance.
|
|
//
|
|
StateIndicator* player_simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState");
|
|
if(entity->GetInstance() == Player::ReplicantInstance)
|
|
{
|
|
//
|
|
// Setup the translocation effect for third party view
|
|
//
|
|
Point3D* drop_zone_position = (Point3D *)entity->GetAttributePointer("DropZoneLocation");
|
|
if(player_simulation_state && drop_zone_position)
|
|
{
|
|
Tell("third party translocate effect is hooked up\n");
|
|
#if DEBUG_LEVEL > 0
|
|
TranslocationRenderable *my_translocate=
|
|
#endif
|
|
new TranslocationRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
TranslocationRenderable::Watcher, // How/when to execute the renderable
|
|
false, // DPL zone everything will be in
|
|
player_simulation_state, // Trigger effects off of this state dial
|
|
drop_zone_position, // Attribute that holds where the new drop will be
|
|
RPPlayer::DropZoneAcquiredState); // State that indicates drop zone is valid (starts effect)
|
|
Register_Object(my_translocate);
|
|
}
|
|
else
|
|
{
|
|
Tell("third party translocate effect NOT hooked up\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(player_simulation_state)
|
|
{
|
|
Tell("Start/end effect hooked up\n");
|
|
#if DEBUG_LEVEL > 0
|
|
POVStartEndRenderable* start_end =
|
|
#endif
|
|
new POVStartEndRenderable(
|
|
entity, // Entity to attach the renderable to
|
|
POVStartEndRenderable::Watcher, // How/when to execute the renderable
|
|
true, // DPL zone the world is in
|
|
dplDeathZone, // DPL zone the player's VTV and death effect are in
|
|
dplMainView, // The view containing our eye
|
|
player_simulation_state, // State dial we use to control the translocation
|
|
fogRed, // Fog color
|
|
fogGreen,
|
|
fogBlue,
|
|
fogNear, // The near fog plane
|
|
fogFar, // The far fog plane
|
|
RPPlayer::MissionStartingState, // State that signals start of mission
|
|
RPPlayer::MissionEndingState); // State that signals end of mission
|
|
Register_Object(start_end);
|
|
}
|
|
else
|
|
{
|
|
Tell("Start/end effect NOT hooked up\n");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
//
|
|
// At the RP level we have no default method for creating objects so we call the
|
|
// next level down (l4) and let it have a try at creating the renderables.
|
|
//
|
|
default:
|
|
{
|
|
DPLRenderer::MakeEntityRenderables(
|
|
entity, // The entity we are dealing with
|
|
model_resource, // video resource for this entity
|
|
view_type); // type of reference to create !!! should be enum
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Make sure the callback system knows what entity is being created
|
|
// !!!! This global will be replaced later.
|
|
//
|
|
Entity_Being_Created = NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// LoadMissionImplementation For the moment it doesn't do much, just determines
|
|
// how many players we should be expecting and sets a variable in the renderer
|
|
// about it.
|
|
//
|
|
void
|
|
RPL4VideoRenderer::LoadMissionImplementation(Mission* mission)
|
|
{
|
|
Tell("RPL4VideoRenderer::LoadMissionImplementation has been called\n");
|
|
//
|
|
// First call our inhereted method to make sure the division card is initialized right
|
|
//
|
|
DPLRenderer::LoadMissionImplementation(mission);
|
|
#if 0
|
|
//
|
|
// This is a !!! HACK to figure out in advance how many VTV's to expect so we can
|
|
// setup the game state properly.
|
|
//
|
|
Mission::HostAddressIterator mission_iterator(mission);
|
|
vtvsExpected = mission_iterator.GetSize();
|
|
//
|
|
// Check for all players loaded
|
|
//
|
|
if((vtvCount >= vtvsExpected) &&
|
|
(GetRendererStatus() == LoadingRendererStatus))
|
|
{
|
|
Tell("Renderer Status set to running in RPL4VideoRenderer::LoadMissionImplementation\n");
|
|
SetRendererStatusToRunning();
|
|
}
|
|
#endif
|
|
}
|
|
//
|
|
//#############################################################################
|
|
// SetupMaterialSubstitutionList This routine sets up the material substitution
|
|
// prior to loading a vehicle.
|
|
//#############################################################################
|
|
//
|
|
char
|
|
RPL4VideoRenderer::SetupMaterialSubstitutionList(
|
|
Entity* entity,
|
|
ViewFrom view_type) // The entity we will be substituting for.
|
|
{
|
|
//STUBBED: DPL RB 1/14/07
|
|
extern NameList
|
|
*materialSubstitutionList;
|
|
static const char
|
|
* const color_parameter = "%color%",
|
|
* const badge_parameter = "%badge%";
|
|
static int
|
|
color_parm_len = strlen(color_parameter),
|
|
badge_parm_len = strlen(badge_parameter);
|
|
NotationFile
|
|
*veh_tbl; // vehicle table from resource file
|
|
NameList::Entry
|
|
*entry; // used to loop through namelists
|
|
const char
|
|
*egg_color, // color name in egg file (from entity)
|
|
*egg_badge, // badge name in egg file (from entity)
|
|
*veh_color, // color code from vehicle table
|
|
*veh_badge; // badge code from vehicle table
|
|
const char
|
|
*source, // tracks progress in source string
|
|
*pc; // jumps ahead of source pointer
|
|
char
|
|
*destination, // tracks progress in destination string
|
|
buffer[80]; // holds result while being constructed
|
|
int
|
|
len; // misc. length
|
|
char
|
|
*vehicleTableResource;
|
|
long
|
|
vehicleTableResourceLength;
|
|
char geometry_substitution = 'n';
|
|
|
|
Verify(materialSubstitutionList == NULL);
|
|
//
|
|
// Get the vehicle table out of resources.
|
|
//
|
|
ResourceDescription *res =
|
|
application->GetResourceFile()->FindResourceDescription(
|
|
"vehicletable",
|
|
ResourceDescription::VehicleTableResourceType
|
|
);
|
|
|
|
if (!res)
|
|
{
|
|
return(geometry_substitution);
|
|
}
|
|
Check(res);
|
|
res->Lock();
|
|
|
|
vehicleTableResource = (char *)res->resourceAddress;
|
|
vehicleTableResourceLength = (long)res->resourceSize;
|
|
|
|
char
|
|
*vehicle_table = new char[vehicleTableResourceLength];
|
|
Register_Pointer(vehicle_table);
|
|
memcpy(vehicle_table, vehicleTableResource, vehicleTableResourceLength);
|
|
|
|
veh_tbl = new NotationFile;
|
|
Register_Object(veh_tbl);
|
|
veh_tbl->ReadText(vehicle_table, vehicleTableResourceLength);
|
|
|
|
Unregister_Pointer(vehicle_table);
|
|
delete vehicle_table;
|
|
|
|
res->Unlock();
|
|
|
|
//
|
|
// Fetch the color and badge pointers out of the entity and into our local stuff
|
|
//
|
|
egg_color = ((VTV *)entity)->vehicleColor;
|
|
egg_badge = ((VTV *)entity)->vehicleBadge;
|
|
Check_Pointer(egg_color);
|
|
Check_Pointer(egg_badge);
|
|
if (!veh_tbl->GetEntry("color", egg_color, &veh_color))
|
|
{
|
|
veh_color = NULL;
|
|
}
|
|
|
|
if (!veh_tbl->GetEntry("badge", egg_badge, &veh_badge))
|
|
{
|
|
veh_badge = NULL;
|
|
}
|
|
else
|
|
{
|
|
if(view_type == insideEntity)
|
|
{
|
|
geometry_substitution = *(veh_badge + strlen(veh_badge) - 2); //ourself
|
|
}
|
|
else
|
|
{
|
|
geometry_substitution = *(veh_badge + strlen(veh_badge) - 1); //someone else
|
|
}
|
|
}
|
|
//--------------------------------------------------
|
|
// get generic substitution list from vehicle table
|
|
//--------------------------------------------------
|
|
materialSubstitutionList = veh_tbl->MakeEntryList("substitute");
|
|
Register_Object(materialSubstitutionList);
|
|
//-------------------------------------------------------------
|
|
// fill in % place holders with specifics for vtv being loaded
|
|
//-------------------------------------------------------------
|
|
entry = materialSubstitutionList->GetFirstEntry();
|
|
while (entry)
|
|
{
|
|
source = entry->GetChar();
|
|
*(destination = buffer) = '\0';
|
|
while ((pc = strchr(source, '%')) != NULL)
|
|
{
|
|
if ((len = pc-source) != 0)
|
|
{
|
|
strncpy(destination, source, len);
|
|
source = pc;
|
|
destination += len;
|
|
}
|
|
if (!strncmp(pc, color_parameter, color_parm_len))
|
|
{
|
|
if (veh_color)
|
|
{
|
|
Str_Copy(
|
|
destination,
|
|
veh_color,
|
|
sizeof(buffer)-(destination-buffer)
|
|
);
|
|
destination += strlen(veh_color);
|
|
}
|
|
source += color_parm_len;
|
|
}
|
|
else if (!strncmp(pc, badge_parameter, badge_parm_len))
|
|
{
|
|
if (veh_badge)
|
|
{
|
|
const char
|
|
*qc = veh_badge;
|
|
|
|
while (isgraph(*qc))
|
|
{
|
|
++qc;
|
|
}
|
|
if ((len = qc - veh_badge) != 0)
|
|
{
|
|
strncpy(destination, veh_badge, len);
|
|
destination += len;
|
|
}
|
|
}
|
|
source += badge_parm_len;
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------------
|
|
// % was not from recognized parameter
|
|
//-------------------------------------
|
|
*destination++ = *source++;
|
|
}
|
|
}
|
|
if (*source)
|
|
{
|
|
Str_Copy(
|
|
destination,
|
|
source,
|
|
sizeof(buffer)-(destination-buffer)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
*destination = '\0';
|
|
}
|
|
|
|
//---------------------------------------
|
|
// make copy of result and store in list
|
|
//---------------------------------------
|
|
destination = new char[strlen(buffer)+1];
|
|
Register_Pointer(destination);
|
|
strcpy(destination, buffer);
|
|
|
|
entry->dataReference = (void *)destination;
|
|
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
Unregister_Object(veh_tbl);
|
|
delete veh_tbl;
|
|
//dpl_SetMaterialNameCallback(substituteMaterial);
|
|
return geometry_substitution;
|
|
}
|
|
//
|
|
//#############################################################################
|
|
// TearDownMaterialSubstitutionList This routine destroys and disconnects the
|
|
// material substitution stuff after a vehicle has been loaded.
|
|
//#############################################################################
|
|
//
|
|
void
|
|
RPL4VideoRenderer::TearDownMaterialSubstitutionList()
|
|
{
|
|
//STUBBED: DPL RB 1/14/07
|
|
NameList::Entry
|
|
*entry;
|
|
char
|
|
*p;
|
|
|
|
extern NameList
|
|
*materialSubstitutionList;
|
|
|
|
if (materialSubstitutionList)
|
|
{
|
|
entry = materialSubstitutionList->GetFirstEntry();
|
|
while (entry)
|
|
{
|
|
if ((p = entry->GetChar()) != NULL)
|
|
{
|
|
Unregister_Pointer(p);
|
|
delete p;
|
|
entry->dataReference = NULL;
|
|
}
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
Unregister_Object(materialSubstitutionList);
|
|
delete materialSubstitutionList;
|
|
materialSubstitutionList = NULL;
|
|
}
|
|
//dpl_SetMaterialNameCallback(NULL);
|
|
}
|
|
//===========================================================================//
|