Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2069 lines
49 KiB
C++
2069 lines
49 KiB
C++
//===========================================================================//
|
|
// File: jmover.cpp //
|
|
// Project: MUNGA Brick: Model Manager //
|
|
// Contents: Implementation details of moving entity class //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 01/21/95 JMA Initial coding. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <munga.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(JMOVER_HPP)
|
|
#include <jmover.hpp>
|
|
#endif
|
|
|
|
#if !defined(FILEUTIL_HPP)
|
|
#include <fileutil.hpp>
|
|
#endif
|
|
|
|
#if !defined(APP_HPP)
|
|
#include <app.hpp>
|
|
#endif
|
|
|
|
#if !defined(NOTATION_HPP)
|
|
#include <notation.hpp>
|
|
#endif
|
|
|
|
#if !defined(NAMELIST_HPP)
|
|
#include <namelist.hpp>
|
|
#endif
|
|
|
|
//#############################################################################
|
|
//############################ JointedMover #############################
|
|
//#############################################################################
|
|
|
|
//#############################################################################
|
|
// Shared Data Support
|
|
//
|
|
Derivation
|
|
JointedMover::ClassDerivations(Mover::ClassDerivations,"JointedMover");
|
|
|
|
JointedMover::SharedData
|
|
JointedMover::DefaultData(
|
|
JointedMover::ClassDerivations,
|
|
JointedMover::MessageHandlers,
|
|
JointedMover::AttributeIndex,
|
|
JointedMover::StateCount,
|
|
(Entity::MakeHandler)JointedMover::Make
|
|
);
|
|
|
|
//#############################################################################
|
|
// Attribute Support
|
|
//
|
|
|
|
const JointedMover::IndexEntry
|
|
JointedMover::AttributePointers[]=
|
|
{
|
|
{
|
|
JointedMover::SegmentCountAttributeID,
|
|
"SegmentCount",
|
|
(Simulation::AttributePointer)&JointedMover::segmentCount
|
|
},
|
|
{
|
|
JointedMover::SegmentTableAttributeID,
|
|
"SegmentTable",
|
|
(Simulation::AttributePointer)&JointedMover::segmentTable
|
|
},
|
|
{
|
|
JointedMover::JointSubsystemAttributeID,
|
|
"JointSubsystem",
|
|
(Simulation::AttributePointer)&JointedMover::jointSubsystem
|
|
}
|
|
};
|
|
|
|
JointedMover::AttributeIndexSet
|
|
JointedMover::AttributeIndex(
|
|
ELEMENTS(JointedMover::AttributePointers),
|
|
JointedMover::AttributePointers,
|
|
Mover::AttributeIndex
|
|
);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EntitySegment*
|
|
JointedMover::GetSegment(CString segment_name)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(segment_name);
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
|
|
EntitySegment *current_segment;
|
|
|
|
while( (current_segment = iterator.ReadAndNext() ) != NULL)
|
|
{
|
|
if(segment_name.Compare(current_segment->GetName()) == 0)
|
|
{
|
|
return current_segment;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EntitySegment*
|
|
JointedMover::GetSegmentFromDamageZone(CString damage_zone)
|
|
{
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
EntitySegment *current_segment;
|
|
while ((current_segment = iterator.ReadAndNext() ) != NULL)
|
|
{
|
|
EntitySegment::IntegerTableIterator *damage_iterator;
|
|
damage_iterator = current_segment->MakeDamageZoneIndexTable();
|
|
Register_Object(damage_iterator);
|
|
EntitySegment::IntegerPlug *index_plug;
|
|
while ((index_plug = damage_iterator->ReadAndNext() ) != NULL)
|
|
{
|
|
CString current_name;
|
|
Verify(index_plug->GetItem() >= 0);
|
|
Verify(index_plug->GetItem() <= damageZoneCount);
|
|
|
|
current_name = damageZones[index_plug->GetItem()]->damageZoneName;
|
|
Check_Pointer(¤t_name);
|
|
if(current_name.Compare(damage_zone) == 0)
|
|
{
|
|
Unregister_Object(damage_iterator);
|
|
delete damage_iterator;
|
|
return current_segment;
|
|
}
|
|
}
|
|
Unregister_Object(damage_iterator);
|
|
delete damage_iterator;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
JointedMover::GetSegmentToWorld(
|
|
EntitySegment &my_segment,
|
|
LinearMatrix *transform
|
|
)
|
|
{
|
|
Check(this);
|
|
JointSubsystem *joints = GetJointSubsystem();
|
|
Check(joints);
|
|
|
|
//
|
|
//---------------------------------------------------------------
|
|
// Check to see if the segment transforms need to be recalculated
|
|
//---------------------------------------------------------------
|
|
//
|
|
if (joints->AreJointsModified())
|
|
{
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
EntitySegment *current_segment;
|
|
while( (current_segment = iterator.ReadAndNext() ) != NULL)
|
|
{
|
|
current_segment->ModifySegment();
|
|
}
|
|
joints->ModifyJoints(False);
|
|
}
|
|
|
|
//
|
|
//-----------------------------
|
|
// Compute the actual transform
|
|
//-----------------------------
|
|
//
|
|
transform->Multiply(
|
|
my_segment.GetSegmentToEntity(),
|
|
localToWorld
|
|
);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//#############################################################################
|
|
// Construction and Destruction
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
JointedMover::JointedMover(
|
|
JointedMover::MakeMessage *creation_message,
|
|
JointedMover::SharedData &virtual_data
|
|
):
|
|
Mover(creation_message, virtual_data),
|
|
jointSubsystem(NULL),
|
|
segmentTable(this, True)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the JointSubsystem
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
JointSubsystem *joint_subsystem = new JointSubsystem(
|
|
(Entity*) this,
|
|
Entity::EntitySubsystemID
|
|
);
|
|
|
|
Register_Object(joint_subsystem);
|
|
jointSubsystem.Add(joint_subsystem);
|
|
Check(joint_subsystem);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get Resource Description
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription *skl_resource =
|
|
application->GetResourceFile()->SearchList(
|
|
creation_message->resourceID,
|
|
ResourceDescription::SkeletonStreamResourceType
|
|
);
|
|
Check(skl_resource);
|
|
skl_resource->Lock();
|
|
|
|
DynamicMemoryStream segment_stream(
|
|
skl_resource->resourceAddress,
|
|
skl_resource->resourceSize);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// read in segmentCount and jointCount
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int joint_count;
|
|
segment_stream >> segmentCount >> joint_count;
|
|
|
|
int current_joint_type;
|
|
int current_joint_index = 0;
|
|
|
|
CString segment_name;
|
|
EntitySegment *parent_segment;
|
|
EntitySegment *current_segment;
|
|
int segment_joint_index;
|
|
Joint *segment_joint_pointer;
|
|
int parent_index;
|
|
CString video_object_name;
|
|
LinearMatrix segment_offset(LinearMatrix::Identity);
|
|
Logical site_segment;
|
|
|
|
int ii;
|
|
for(ii=0;ii<segmentCount;ii++)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~
|
|
// Read segment name
|
|
//~~~~~~~~~~~~~~~~~~
|
|
//
|
|
segment_stream >> segment_name >> parent_index;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// read parent index & find parentSegment ptr
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if(parent_index == -1)
|
|
{
|
|
parent_segment = NULL;
|
|
}
|
|
else
|
|
{
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
parent_segment = iterator.GetNth(parent_index);
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Determine if this segment is a site
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
segment_stream >> site_segment >> current_joint_type;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the joint type & init the joint
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if(current_joint_type != Joint::NULLJointType)
|
|
{
|
|
segment_joint_index = current_joint_index;
|
|
segment_joint_pointer =
|
|
new Joint(
|
|
joint_subsystem,
|
|
(Joint::JointType)current_joint_type
|
|
);
|
|
Register_Object(segment_joint_pointer);
|
|
joint_subsystem->AddJoint(current_joint_index, segment_joint_pointer);
|
|
|
|
++current_joint_index;
|
|
}
|
|
else
|
|
{
|
|
segment_joint_pointer = NULL;
|
|
segment_joint_index = -1;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in the segment offset matrix
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
segment_stream >> segment_offset;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get The Primary Damage Zone
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int primary_dzone_index;
|
|
segment_stream >> primary_dzone_index;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create this segment and add
|
|
// add it to the segment table
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
current_segment = new EntitySegment(
|
|
segment_name,
|
|
ii, // my_index
|
|
parent_index,
|
|
segment_joint_index,
|
|
segment_joint_pointer,
|
|
segment_offset,
|
|
parent_segment,
|
|
site_segment,
|
|
primary_dzone_index
|
|
);
|
|
Register_Object(current_segment);
|
|
segmentTable.AddValue(current_segment, ii);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in ALL VideoObjectNames
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int video_object_count;
|
|
EntitySegment::SkeletonType skl_type;
|
|
|
|
segment_stream >> video_object_count;
|
|
Verify(video_object_count);
|
|
|
|
int jj;
|
|
for(jj=0;jj<video_object_count;++jj)
|
|
{
|
|
segment_stream >> skl_type >> video_object_name;
|
|
if(video_object_name.Compare("None"))
|
|
{
|
|
current_segment->AddVideoObjectName(
|
|
video_object_name,
|
|
skl_type,
|
|
DamageZone::ExistsGraphicState
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in ALL DESTROYED VideoObjectNames
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int destroyed_video_object_count;
|
|
|
|
segment_stream >> destroyed_video_object_count;
|
|
|
|
for(jj=0;jj<destroyed_video_object_count;++jj)
|
|
{
|
|
segment_stream >> skl_type >> video_object_name;
|
|
if(video_object_name.Compare("None"))
|
|
{
|
|
current_segment->AddVideoObjectName(
|
|
video_object_name,
|
|
skl_type,
|
|
DamageZone::DestroyedGraphicState
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in DamageZone information
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int damage_zone_count;
|
|
int damage_zone_index;
|
|
|
|
segment_stream >> damage_zone_count;
|
|
if(damage_zone_count)
|
|
{
|
|
|
|
for(int dd=0;dd<damage_zone_count;++dd)
|
|
{
|
|
segment_stream >> damage_zone_index;
|
|
current_segment->AddDamageZone(damage_zone_index, dd);
|
|
}
|
|
}
|
|
//
|
|
// Read in the Children Information
|
|
//
|
|
int children_count;
|
|
int child_index;
|
|
|
|
segment_stream >> children_count;
|
|
|
|
if(children_count)
|
|
{
|
|
for(int jj=0;jj<children_count;++jj)
|
|
{
|
|
segment_stream >> child_index;
|
|
current_segment->AddChildIndex(child_index, jj);
|
|
}
|
|
}
|
|
}
|
|
skl_resource->Unlock();
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize all the child Pointers for each segment
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
for(ii=0;ii<segmentCount;++ii)
|
|
{
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
InitializeChildPointers(iterator.GetNth(ii));
|
|
}
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
JointedMover::InitializeChildPointers(EntitySegment *current_segment)
|
|
{
|
|
EntitySegment::IntegerTableIterator *iterator;
|
|
EntitySegment::SegmentTableIterator segment_iterator(segmentTable);
|
|
iterator = current_segment->MakeChildIndexTable();
|
|
Register_Object(iterator);
|
|
EntitySegment::IntegerPlug *current_index;
|
|
int child_count=0;
|
|
while((current_index = iterator->ReadAndNext()) != NULL)
|
|
{
|
|
EntitySegment *child_segment;
|
|
child_segment = segment_iterator.GetNth(current_index->GetItem());
|
|
Check(child_segment);
|
|
current_segment->AddChildPointer(child_segment, child_count);
|
|
++child_count;
|
|
}
|
|
Unregister_Object(iterator);
|
|
delete iterator;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
JointedMover::~JointedMover()
|
|
{
|
|
EntitySegment::SegmentTableIterator iterator(segmentTable);
|
|
iterator.DeletePlugs();
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// This should be deleted by the entity subsystemArray[jointSubsystem]
|
|
//---------------------------------------------------------------------
|
|
//
|
|
#if 0
|
|
JointSubsystem *joint_subsystem = jointSubsystem.GetCurrent();
|
|
Unregister_Object(joint_subsystem);
|
|
delete joint_subsystem;
|
|
#endif
|
|
}
|
|
|
|
//########################################################################
|
|
// DamageZone Support
|
|
//
|
|
ResourceDescription::ResourceID
|
|
JointedMover::CreateDamageZoneStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(resource_file);
|
|
Check_Pointer(model_name);
|
|
Check(model_file);
|
|
Check_Pointer(directories);
|
|
|
|
//
|
|
//-------------------
|
|
// Find the .skl file
|
|
//-------------------
|
|
//
|
|
const char* skl_entry;
|
|
if (
|
|
!model_file->GetEntry(
|
|
"video",
|
|
"skeleton",
|
|
&skl_entry
|
|
)
|
|
)
|
|
{
|
|
DEBUG_STREAM << model_name << " is missing .skl file specification!\n";
|
|
return -1;
|
|
}
|
|
char *skl_filename =
|
|
MakePathedFilename(directories->videoDirectory, skl_entry);
|
|
Register_Pointer(skl_filename);
|
|
|
|
NotationFile *skl_file = new NotationFile(skl_filename);
|
|
Register_Object(skl_file);
|
|
if (!skl_file->PageCount())
|
|
{
|
|
DEBUG_STREAM << skl_filename << " is empty or missing!\n";
|
|
Dump_And_Die_1:
|
|
Unregister_Pointer(skl_filename);
|
|
delete[] skl_filename;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
return ResourceDescription::NullResourceID;
|
|
}
|
|
|
|
//
|
|
//-------------------
|
|
// Find the .dmg file
|
|
//-------------------
|
|
//
|
|
const char* dmg_entry;
|
|
if (
|
|
!model_file->GetEntry(
|
|
"gamedata",
|
|
"DamageZones",
|
|
&dmg_entry
|
|
)
|
|
)
|
|
{
|
|
DEBUG_STREAM << model_name << " is missing .dmg file specification!\n";
|
|
goto Dump_And_Die_1;
|
|
}
|
|
|
|
char *dmg_filename =
|
|
MakePathedFilename(directories->modelDirectory, dmg_entry);
|
|
Register_Pointer(dmg_filename);
|
|
|
|
NotationFile *dmg_file = new NotationFile(dmg_filename);
|
|
Register_Object(dmg_file);
|
|
|
|
if (!dmg_file->PageCount())
|
|
{
|
|
DEBUG_STREAM << dmg_filename << " is empty or missing!\n";
|
|
Dump_And_Die_2:
|
|
Unregister_Pointer(dmg_filename);
|
|
delete[] dmg_filename;
|
|
Unregister_Object(dmg_file);
|
|
delete dmg_file;
|
|
goto Dump_And_Die_1;
|
|
}
|
|
|
|
//
|
|
// Get the number of Damage zones
|
|
//
|
|
int dzone_count;
|
|
if (
|
|
!skl_file->GetEntry(
|
|
"ROOT",
|
|
"DZoneCount",
|
|
&dzone_count
|
|
)
|
|
)
|
|
{
|
|
DEBUG_STREAM << model_name << " is missing DZoneCount \n";
|
|
goto Dump_And_Die_2;
|
|
}
|
|
|
|
DynamicMemoryStream damage_zone_stream;
|
|
|
|
//
|
|
// write the Damage Zone Count Info from the
|
|
// .dmg file to the stream
|
|
//
|
|
damage_zone_stream << dzone_count;
|
|
|
|
//
|
|
// Make an entry list of all the entries in the damage zone page
|
|
//
|
|
NameList *dzone_namelist =
|
|
skl_file->MakeEntryList("DamageZones","dz_");
|
|
Register_Object(dzone_namelist);
|
|
|
|
if (dzone_namelist->EntryCount() == 0)
|
|
{
|
|
DEBUG_STREAM << "No dZones listed in DamageZones Page"<<endl;
|
|
Dump_And_Die:
|
|
Unregister_Pointer(skl_filename);
|
|
delete skl_filename;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
Unregister_Pointer(dmg_filename);
|
|
delete dmg_filename;
|
|
Unregister_Object(dmg_file);
|
|
delete dmg_file;
|
|
return -1;
|
|
}
|
|
NameList::Entry *dzone_entry;
|
|
char current_dzone_name[32];
|
|
|
|
int num_dzones_found = 0;
|
|
|
|
dzone_entry = dzone_namelist->GetFirstEntry();
|
|
|
|
while (dzone_entry)
|
|
{
|
|
++num_dzones_found;
|
|
//
|
|
// Get dzone name in .skl file
|
|
//
|
|
Str_Copy(
|
|
current_dzone_name,
|
|
dzone_entry->GetName(),
|
|
sizeof(current_dzone_name)
|
|
);
|
|
|
|
//
|
|
// Create the stream for this damage zone
|
|
//
|
|
DamageZone::CreateStreamedDamageZone(
|
|
model_file,
|
|
model_name,
|
|
skl_file,
|
|
current_dzone_name,
|
|
&damage_zone_stream,
|
|
dmg_file,
|
|
directories
|
|
);
|
|
|
|
//
|
|
// Get next dzone entry in this segment page
|
|
//
|
|
dzone_entry = dzone_entry->GetNextEntry();
|
|
} // End while more dzone_entries
|
|
|
|
if(dzone_count != num_dzones_found)
|
|
{
|
|
DEBUG_STREAM <<"DZoneCount != damage zones found in Page DamageZones"<<endl;
|
|
goto Dump_And_Die;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Write the stream out to disk. Size is equal to the byte difference
|
|
// between stream and damage zone buffer
|
|
//--------------------------------------------------------------------
|
|
//
|
|
ResourceDescription *new_res =
|
|
resource_file->AddResourceMemoryStream(
|
|
model_name,
|
|
ResourceDescription::DamageZoneStreamResourceType,
|
|
1,
|
|
ResourceDescription::Preload,
|
|
&damage_zone_stream
|
|
);
|
|
Check(new_res);
|
|
//
|
|
// Free mem
|
|
//
|
|
Unregister_Pointer(skl_filename);
|
|
delete skl_filename;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
Unregister_Pointer(dmg_filename);
|
|
delete dmg_filename;
|
|
Unregister_Object(dmg_file);
|
|
delete dmg_file;
|
|
Unregister_Object(dzone_namelist);
|
|
delete dzone_namelist;
|
|
return new_res->resourceID;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription::ResourceID
|
|
JointedMover::CreateSkeletonStream(
|
|
ResourceFile *resource_file,
|
|
const char *model_name,
|
|
NotationFile *model_file,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check_Pointer(model_name);
|
|
Check(model_file);
|
|
Check_Pointer(directories);
|
|
|
|
//
|
|
//-------------------
|
|
// Find the .skl file
|
|
//-------------------
|
|
//
|
|
const char *entry_data;
|
|
if (
|
|
!model_file->GetEntry(
|
|
"video",
|
|
"skeleton",
|
|
&entry_data
|
|
)
|
|
)
|
|
{
|
|
DEBUG_STREAM << model_name << " is missing .skl file specification!\n";
|
|
return -1;
|
|
}
|
|
//
|
|
// Get the name of the SKL File
|
|
//
|
|
char *filename = MakePathedFilename(directories->videoDirectory, entry_data);
|
|
Register_Pointer(filename);
|
|
|
|
//
|
|
// Create a Notation file from the skl ASCII File
|
|
//
|
|
NotationFile *skl_file = new NotationFile(filename);
|
|
Register_Object(skl_file);
|
|
|
|
//
|
|
// Get number of Segments(or Pages)
|
|
//
|
|
int segment_count = skl_file->PageCount();
|
|
|
|
//
|
|
// Do not count Lab_Only and DamageZones they are not included
|
|
//
|
|
if (skl_file->PageExists("LAB_ONLY"))
|
|
--segment_count;
|
|
if(skl_file->PageExists("DamageZones"))
|
|
--segment_count;
|
|
|
|
if (!segment_count)
|
|
{
|
|
DEBUG_STREAM << model_name << " has no Segments!\n";
|
|
Dump_And_Die:
|
|
Unregister_Pointer(filename);
|
|
delete filename;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
return -1;
|
|
}
|
|
int joint_count;
|
|
if (
|
|
!skl_file->GetEntry(
|
|
"ROOT",
|
|
"JointCount",
|
|
&joint_count
|
|
)
|
|
)
|
|
{
|
|
DEBUG_STREAM << model_name << " is missing JointCount \n";
|
|
goto Dump_And_Die;
|
|
}
|
|
DynamicMemoryStream segment_stream;
|
|
|
|
//
|
|
// Write Segment Count to the stream
|
|
//
|
|
segment_stream << segment_count << joint_count;
|
|
|
|
//
|
|
// Create a list of the pages and get the first entry
|
|
//
|
|
NameList *segment_namelist = skl_file->MakePageList();
|
|
Register_Object(segment_namelist);
|
|
NameList::Entry *segment_entry = segment_namelist->GetFirstEntry();
|
|
int
|
|
parent_index = -1,
|
|
children_count;
|
|
|
|
CString
|
|
segment_page_name;
|
|
|
|
EulerAngles
|
|
rotation;
|
|
|
|
Point3D
|
|
translation;
|
|
|
|
LinearMatrix
|
|
base_offset(LinearMatrix::Identity);
|
|
|
|
while(segment_entry)
|
|
{
|
|
segment_page_name = segment_entry->GetName();
|
|
|
|
if(
|
|
(strcmp(segment_page_name, "LAB_ONLY") == 0) ||
|
|
(strcmp(segment_page_name,"DamageZones") ==0)
|
|
)
|
|
{
|
|
segment_entry = segment_entry->GetNextEntry();
|
|
continue;
|
|
}
|
|
|
|
segment_stream << segment_page_name;
|
|
//
|
|
// Get the information about the parent
|
|
//
|
|
const char *parent_name;
|
|
if(
|
|
skl_file->GetEntry(
|
|
segment_page_name,
|
|
"parent",
|
|
&parent_name
|
|
)
|
|
)
|
|
{
|
|
parent_index = GetSegmentIndex(parent_name, skl_file);
|
|
if(parent_index == -1)
|
|
{
|
|
DEBUG_STREAM<<model_file<<":"<<parent_name<<" Not Found!"<<endl;
|
|
goto Dump_And_Die;
|
|
}
|
|
}
|
|
segment_stream << parent_index;
|
|
|
|
//
|
|
// Get the joint Type, NULL Joint Type (-1) if no joint
|
|
//
|
|
const char *joint_name;
|
|
int joint_type = Joint::NULLJointType;
|
|
Logical is_site(False);
|
|
if(!skl_file->GetEntry(
|
|
segment_page_name,
|
|
"Type",
|
|
&joint_name)
|
|
)
|
|
{
|
|
if( strcmp("ROOT", segment_page_name) != 0)
|
|
{
|
|
is_site = True;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(strcmp(joint_name,"static")==0)
|
|
{
|
|
joint_type = Joint::StaticJointType;
|
|
}
|
|
else
|
|
if(strcmp(joint_name, "hingex")==0)
|
|
{
|
|
joint_type = Joint::HingeXJointType;
|
|
}
|
|
else
|
|
if(strcmp(joint_name,"hingey")==0)
|
|
{
|
|
joint_type = Joint::HingeYJointType;
|
|
}
|
|
else
|
|
if(strcmp(joint_name,"hingez")==0)
|
|
{
|
|
joint_type = Joint::HingeZJointType;
|
|
}
|
|
else
|
|
if(strcmp(joint_name,"ball")==0)
|
|
{
|
|
joint_type = Joint::BallJointType;
|
|
}
|
|
else
|
|
if(strcmp(joint_name,"balltranslate")==0)
|
|
{
|
|
joint_type = Joint::BallTranslationJointType;
|
|
}
|
|
}
|
|
segment_stream << is_site << joint_type;
|
|
//
|
|
// Get offsets
|
|
//
|
|
skl_file->GetEntry(segment_page_name, "tranx" ,&translation.x);
|
|
skl_file->GetEntry(segment_page_name, "trany" ,&translation.y);
|
|
skl_file->GetEntry(segment_page_name, "tranz" ,&translation.z);
|
|
skl_file->GetEntry(segment_page_name, "pitch" ,&rotation.pitch.angle);
|
|
skl_file->GetEntry(segment_page_name, "yaw" ,&rotation.yaw.angle);
|
|
skl_file->GetEntry(segment_page_name, "roll" ,&rotation.roll.angle);
|
|
|
|
base_offset = translation;
|
|
base_offset = rotation;
|
|
|
|
//
|
|
// Write out the base offset
|
|
//
|
|
segment_stream << base_offset;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the Primary Damage Zone
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
const char* skl_entry;
|
|
if (!model_file->GetEntry(
|
|
"video",
|
|
"skeleton",
|
|
&skl_entry
|
|
)
|
|
)
|
|
{
|
|
goto Dump_And_Die;
|
|
}
|
|
else
|
|
{
|
|
CString skl_filename =
|
|
MakePathedFilename(directories->videoDirectory, skl_entry);
|
|
|
|
NotationFile *skl_file = new NotationFile(skl_filename);
|
|
Register_Object(skl_file);
|
|
if (!skl_file->PageCount())
|
|
{
|
|
DEBUG_STREAM << skl_filename << " is empty or missing!"<<endl;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
goto Dump_And_Die;
|
|
}
|
|
int primary_damage_zone;
|
|
const char *dzone_name;
|
|
if (skl_file->GetEntry(
|
|
segment_page_name,
|
|
"dzone",
|
|
&dzone_name
|
|
)
|
|
)
|
|
{
|
|
primary_damage_zone = GetDamageZoneIndex(dzone_name, skl_file);
|
|
}
|
|
else
|
|
{
|
|
primary_damage_zone = -1;
|
|
}
|
|
segment_stream << primary_damage_zone;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
}
|
|
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in ALL VideoObjectNames
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (!
|
|
InitVideoObjectNames(
|
|
&segment_stream,
|
|
model_file,
|
|
segment_page_name,
|
|
directories
|
|
)
|
|
)
|
|
{
|
|
goto Dump_And_Die;
|
|
}
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Read in ALL DESTROYED VideoObjectNames
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (!
|
|
InitDestroyedVideoObjectNames(
|
|
&segment_stream,
|
|
model_file,
|
|
segment_page_name,
|
|
directories
|
|
)
|
|
)
|
|
{
|
|
goto Dump_And_Die;
|
|
}
|
|
|
|
//
|
|
// Get the damageZones associated with this segment
|
|
//
|
|
NameList *damage_zone_list =
|
|
skl_file->MakeEntryList(segment_entry->GetName(), "dzone");
|
|
Register_Object(damage_zone_list);
|
|
|
|
NameList::Entry *damage_zone_entry = damage_zone_list->GetFirstEntry();
|
|
|
|
int damage_zone_count = damage_zone_list->EntryCount();
|
|
|
|
segment_stream << damage_zone_count;
|
|
|
|
if (damage_zone_count)
|
|
{
|
|
for (int dd=0;dd<damage_zone_count;++dd)
|
|
{
|
|
|
|
CString damage_zone_name;
|
|
damage_zone_name = damage_zone_entry->GetChar();
|
|
|
|
int damage_zone_index;
|
|
damage_zone_index =
|
|
GetDamageZoneIndex(damage_zone_name, skl_file);
|
|
|
|
if(damage_zone_index == -1)
|
|
{
|
|
|
|
DEBUG_STREAM<<model_file<<":"<<damage_zone_name<<" Not Found!"<<endl;
|
|
goto Dump_And_Die;
|
|
|
|
}
|
|
segment_stream << damage_zone_index;
|
|
damage_zone_entry = damage_zone_entry->GetNextEntry();
|
|
}
|
|
}
|
|
Unregister_Object(damage_zone_list);
|
|
delete damage_zone_list;
|
|
|
|
//
|
|
// Get the number of children, 0 if no children
|
|
//
|
|
NameList *children_list =
|
|
skl_file->MakeEntryList(segment_entry->GetName(),"joint");
|
|
Register_Object(children_list);
|
|
NameList::Entry *child_entry = children_list->GetFirstEntry();
|
|
children_count = 0;
|
|
while(child_entry)
|
|
{
|
|
++children_count;
|
|
child_entry = child_entry->GetNextEntry();
|
|
}
|
|
//
|
|
// Write how many children
|
|
//
|
|
segment_stream << children_count;
|
|
if(children_count)
|
|
{
|
|
child_entry = children_list->GetFirstEntry();
|
|
//
|
|
// Write out the segment index for every child
|
|
//
|
|
for(int cc=0;cc<children_count;++cc)
|
|
{
|
|
int child_index = GetSegmentIndex(child_entry->GetChar(), skl_file);
|
|
if(child_index == -1)
|
|
{
|
|
DEBUG_STREAM<<model_name<<":"<<child_entry->GetName()<<" Not Found!!"<<endl;
|
|
|
|
goto Dump_And_Die;
|
|
}
|
|
segment_stream << child_index;
|
|
child_entry = child_entry->GetNextEntry();
|
|
}
|
|
}
|
|
Unregister_Object(children_list);
|
|
delete children_list;
|
|
segment_entry = segment_entry->GetNextEntry();
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Write the stream out to disk.
|
|
//--------------------------------------------------------------------
|
|
//
|
|
ResourceDescription *new_res =
|
|
resource_file->AddResourceMemoryStream(
|
|
model_name,
|
|
ResourceDescription::SkeletonStreamResourceType,
|
|
1,
|
|
ResourceDescription::Preload,
|
|
&segment_stream
|
|
);
|
|
Check(new_res);
|
|
|
|
//
|
|
// Fre Mem
|
|
//
|
|
Unregister_Pointer(filename);
|
|
delete filename;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
Unregister_Object(segment_namelist);
|
|
delete segment_namelist;
|
|
|
|
return new_res->resourceID;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
JointedMover::InitDestroyedVideoObjectNames(
|
|
MemoryStream *mem_stream,
|
|
NotationFile *model_file,
|
|
CString page_name,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(model_file);
|
|
Check(mem_stream);
|
|
|
|
NameList *skl_namelist = model_file->MakeEntryList("video","destroyed");
|
|
Register_Object(skl_namelist);
|
|
int entry_count = skl_namelist->EntryCount();
|
|
*mem_stream << entry_count;
|
|
|
|
if (!entry_count)
|
|
{
|
|
Unregister_Object(skl_namelist);
|
|
delete skl_namelist;
|
|
return True;
|
|
}
|
|
Verify(entry_count);
|
|
|
|
NameList::Entry *skl_entry = skl_namelist->GetFirstEntry();
|
|
while(skl_entry)
|
|
{
|
|
CString entry_name = skl_entry->GetName();
|
|
EntitySegment::SkeletonType skeleton_type;
|
|
if (! entry_name.Compare("destroyed") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_N;
|
|
}
|
|
else if (! entry_name.Compare("destroyeds") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_S;
|
|
}
|
|
else if (! entry_name.Compare("destroyedt") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_T;
|
|
}
|
|
else if (! entry_name.Compare("destroyedo") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_O;
|
|
}
|
|
else if (! entry_name.Compare("destroyeda") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_A;
|
|
}
|
|
else if (! entry_name.Compare("destroyedb") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_B;
|
|
}
|
|
else if (! entry_name.Compare("destroyedc") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_C;
|
|
}
|
|
else if (! entry_name.Compare("destroyedd") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_D;
|
|
}
|
|
*mem_stream << skeleton_type;
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the video object filename
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CString short_skl_filename = skl_entry->GetChar();
|
|
CString skl_filename =
|
|
MakePathedFilename(directories->videoDirectory, short_skl_filename);
|
|
|
|
NotationFile *skl_file = new NotationFile(skl_filename);
|
|
Register_Object(skl_file);
|
|
if (!skl_file->PageCount())
|
|
{
|
|
DEBUG_STREAM << skl_filename << " is empty or missing!"<<endl;
|
|
Dump_And_Die:
|
|
Unregister_Object(skl_namelist);
|
|
delete skl_namelist;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
return ResourceDescription::NullResourceID;
|
|
}
|
|
|
|
CString video_object_name;
|
|
const char *c_name;
|
|
if (skl_file->GetEntry(
|
|
page_name,
|
|
"Object",
|
|
&c_name
|
|
)
|
|
)
|
|
{
|
|
video_object_name = c_name;
|
|
}
|
|
else
|
|
{
|
|
video_object_name = "None";
|
|
}
|
|
*mem_stream << video_object_name;
|
|
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
|
|
skl_entry = skl_entry->GetNextEntry();
|
|
}
|
|
Unregister_Object(skl_namelist);
|
|
delete skl_namelist;
|
|
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
JointedMover::InitVideoObjectNames(
|
|
MemoryStream *mem_stream,
|
|
NotationFile *model_file,
|
|
CString page_name,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check(model_file);
|
|
Check(mem_stream);
|
|
|
|
NameList *skl_namelist = model_file->MakeEntryList("video","skeleton");
|
|
Register_Object(skl_namelist);
|
|
int entry_count = skl_namelist->EntryCount();
|
|
|
|
Verify(entry_count);
|
|
*mem_stream << entry_count;
|
|
|
|
NameList::Entry *skl_entry = skl_namelist->GetFirstEntry();
|
|
while(skl_entry)
|
|
{
|
|
CString entry_name = skl_entry->GetName();
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Write out the skeleton type
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EntitySegment::SkeletonType skeleton_type;
|
|
if (! entry_name.Compare("skeleton") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_N;
|
|
}
|
|
else if (! entry_name.Compare("skeletons") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_S;
|
|
}
|
|
else if (! entry_name.Compare("skeletont") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_T;
|
|
}
|
|
else if (! entry_name.Compare("skeletono") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_O;
|
|
}
|
|
else if (! entry_name.Compare("skeletona") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_A;
|
|
}
|
|
else if (! entry_name.Compare("skeletonb") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_B;
|
|
}
|
|
else if (! entry_name.Compare("skeletonc") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_C;
|
|
}
|
|
else if (! entry_name.Compare("skeletond") )
|
|
{
|
|
skeleton_type = EntitySegment::SkeletonType_D;
|
|
}
|
|
*mem_stream << skeleton_type;
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Get the video object filename
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CString short_skl_filename = skl_entry->GetChar();
|
|
CString skl_filename =
|
|
MakePathedFilename(directories->videoDirectory, short_skl_filename);
|
|
|
|
NotationFile *skl_file = new NotationFile(skl_filename);
|
|
Register_Object(skl_file);
|
|
if (!skl_file->PageCount())
|
|
{
|
|
DEBUG_STREAM << skl_filename << " is empty or missing!"<<endl;
|
|
Dump_And_Die:
|
|
Unregister_Object(skl_namelist);
|
|
delete skl_namelist;
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
return ResourceDescription::NullResourceID;
|
|
}
|
|
|
|
CString video_object_name;
|
|
const char *c_name;
|
|
if (skl_file->GetEntry(
|
|
page_name,
|
|
"Object",
|
|
&c_name
|
|
)
|
|
)
|
|
{
|
|
video_object_name = c_name;
|
|
}
|
|
else
|
|
{
|
|
video_object_name = "None";
|
|
}
|
|
*mem_stream << video_object_name;
|
|
|
|
Unregister_Object(skl_file);
|
|
delete skl_file;
|
|
|
|
skl_entry = skl_entry->GetNextEntry();
|
|
}
|
|
Unregister_Object(skl_namelist);
|
|
delete skl_namelist;
|
|
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
JointedMover::GetDamageZoneIndex(
|
|
CString damage_zone_name,
|
|
NotationFile *skl_file
|
|
)
|
|
{
|
|
int damage_zone_index = -1;
|
|
|
|
NameList *name_list = skl_file->MakeEntryList("DamageZones", "dz_");
|
|
Register_Object(name_list);
|
|
|
|
if (name_list->EntryCount() == 0)
|
|
{
|
|
DEBUG_STREAM << "No dZones listed in DamageZones Page"<<endl;
|
|
Unregister_Object(name_list);
|
|
delete name_list;
|
|
return -1;
|
|
}
|
|
NameList::Entry *damage_zone = name_list->GetFirstEntry();
|
|
while(damage_zone)
|
|
{
|
|
if(strcmp(damage_zone->GetName(), damage_zone_name) == 0)
|
|
{
|
|
Convert_From_Ascii(damage_zone->GetChar(), &damage_zone_index);
|
|
Unregister_Object(name_list);
|
|
delete name_list;
|
|
return damage_zone_index;
|
|
}
|
|
damage_zone = damage_zone->GetNextEntry();
|
|
}
|
|
Unregister_Object(name_list);
|
|
delete name_list;
|
|
|
|
return damage_zone_index;
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
JointedMover::GetSegmentIndex(
|
|
CString segment_name,
|
|
NotationFile *skl_file
|
|
)
|
|
{
|
|
int segment_index=-1;
|
|
|
|
char page_name[128];
|
|
NameList *page_list = skl_file->MakePageList();
|
|
Register_Object(page_list);
|
|
NameList::Entry *current_entry = page_list->GetFirstEntry();
|
|
while(current_entry)
|
|
{
|
|
Str_Copy(
|
|
page_name,
|
|
current_entry->GetName(),
|
|
sizeof(page_name)
|
|
);
|
|
if(
|
|
(strcmp(page_name, "LAB_ONLY") == 0) ||
|
|
(strcmp(page_name,"DamageZones") == 0)
|
|
)
|
|
{
|
|
current_entry = current_entry->GetNextEntry();
|
|
continue;
|
|
}
|
|
++segment_index;
|
|
if((strcmp(page_name, segment_name) == 0))
|
|
{
|
|
Unregister_Object(page_list);
|
|
delete page_list;
|
|
return segment_index;
|
|
}
|
|
current_entry = current_entry->GetNextEntry();
|
|
}
|
|
Unregister_Object(page_list);
|
|
delete page_list;
|
|
return -1;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
JointedMover*
|
|
JointedMover::Make(JointedMover::MakeMessage *creation_message)
|
|
{
|
|
return new JointedMover(creation_message, DefaultData);
|
|
}
|
|
//##########################################################################
|
|
//########################## Animation ###############################
|
|
//##########################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AnimationInstance::AnimationInstance(JointedMover *jointed_mover)
|
|
{
|
|
Check_Pointer(this);
|
|
Check(jointed_mover);
|
|
|
|
lerpToZero = False;
|
|
moverToAnimate = jointed_mover;
|
|
jointSubToAnimate = jointed_mover->GetJointSubsystem();
|
|
animationResource = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
AnimationInstance::SetAnimation(
|
|
ResourceDescription::ResourceID animation_number,
|
|
JointedMover::AnimationCallback finished_callback
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
finishedCallback = finished_callback;
|
|
currentTime = 0.0f;
|
|
currentFrame = 0;
|
|
|
|
if (animationResource)
|
|
{
|
|
Check(animationResource);
|
|
animationResource->Unlock();
|
|
}
|
|
animationResource =
|
|
application->GetResourceFile()->FindResourceDescription(
|
|
animation_number
|
|
);
|
|
Check(animationResource);
|
|
animationResource->Lock();
|
|
int *animation_data = (int*)animationResource->resourceAddress;
|
|
Check_Pointer(animation_data);
|
|
frameCount = animation_data[0];
|
|
jointCount = animation_data[1];
|
|
footStepThreshold = (float *)&animation_data[2];
|
|
jointIndices = &animation_data[3];
|
|
frameStart = (Scalar*)(jointIndices + jointCount);
|
|
|
|
keyFrames = frameStart + frameCount;
|
|
currentFrameTo = keyFrames;
|
|
void* to;
|
|
to = keyFrames;
|
|
//
|
|
//-----------------------------------
|
|
// find the end of the keyframes data
|
|
//-----------------------------------
|
|
//
|
|
for(int ii=0;ii<frameCount;++ii)
|
|
for(int jj=0;jj<jointCount;++jj)
|
|
{
|
|
switch(jointSubToAnimate->GetJoint(jointIndices[jj])->GetJointType())
|
|
{
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
to = (void *)((char *)to+sizeof(Vector3D));
|
|
break;
|
|
}
|
|
case Joint::HingeXJointType:
|
|
case Joint::HingeYJointType:
|
|
case Joint::HingeZJointType:
|
|
{
|
|
to = (void *)((char *)to+sizeof(Hinge));
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
// This should be contained in the keyframes
|
|
//
|
|
// keyJointPos = (Vector3D*)(keyFrames + jointCount*frameCount);
|
|
|
|
rootTranslations = (Vector3D*)(to);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AnimationInstance::~AnimationInstance()
|
|
{
|
|
if (animationResource)
|
|
{
|
|
Check(animationResource);
|
|
animationResource->Unlock();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Scalar
|
|
AnimationInstance::Animate(Scalar time_slice, Logical move_joints)
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Find the frame to lerp towards. As each frame boundary is crossed, set
|
|
// the joints to the position of that boundary and adjust the remaining time
|
|
// to lerp
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
int i;
|
|
//
|
|
//-----------------------------------------
|
|
// This void * can point to any joint type
|
|
//-----------------------------------------
|
|
//
|
|
void
|
|
*to;
|
|
|
|
|
|
Scalar frame_time = currentTime + time_slice;
|
|
Scalar movement = 0.0f;
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// to points to the place in the memory stream we left off at
|
|
// last time we were on this loop
|
|
//-------------------------------------------------------------
|
|
//
|
|
to = currentFrameTo;
|
|
Joint *current_joint;
|
|
|
|
while (currentFrame < frameCount)
|
|
{
|
|
if (frame_time < frameStart[currentFrame])
|
|
{
|
|
break;
|
|
}
|
|
for (i=0; i<jointCount; ++i)
|
|
{
|
|
current_joint = jointSubToAnimate->GetJoint(jointIndices[i]);
|
|
Check(current_joint);
|
|
switch(current_joint->GetJointType())
|
|
{
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Only modify the joint if the value has changed
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (current_joint->GetEulerAngles() != *(EulerAngles*)to)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetRotation(*(EulerAngles*)to);
|
|
}
|
|
}
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
|
|
if (current_joint->GetTranslation() != *(Point3D*)to)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetTranslation(*(Point3D*)to);
|
|
}
|
|
}
|
|
|
|
to = (void *)((char *)to+sizeof(Vector3D));
|
|
break;
|
|
}
|
|
case Joint::HingeXJointType:
|
|
case Joint::HingeYJointType:
|
|
case Joint::HingeZJointType:
|
|
{
|
|
if (current_joint->GetHinge() != *(Hinge*) to)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetHinge(*(Hinge*) to);
|
|
}
|
|
}
|
|
to = (void *)((char *)to+sizeof(Hinge));
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
|
|
if (current_joint->GetEulerAngles() != *(EulerAngles*)to)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetRotation(*(EulerAngles*)to);
|
|
}
|
|
}
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
break;
|
|
case Joint::StaticJointType:
|
|
break;
|
|
}
|
|
}
|
|
movement +=
|
|
(frameStart[currentFrame] - currentTime)
|
|
* rootTranslations[currentFrame].z;
|
|
currentTime = frameStart[currentFrame];
|
|
++currentFrame;
|
|
}
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// We we have run off the end of the animation, trigger the callback and
|
|
// return
|
|
//----------------------------------------------------------------------
|
|
//
|
|
if (currentFrame == frameCount)
|
|
{
|
|
|
|
movement +=
|
|
(moverToAnimate->*finishedCallback)(
|
|
animationResource->resourceID,
|
|
frame_time - frameStart[frameCount - 1],
|
|
move_joints
|
|
);
|
|
return movement;
|
|
}
|
|
|
|
currentFrameTo = to;
|
|
//
|
|
//-------------------------------------------------------
|
|
// Set up to lerp the rotations between to two key frames
|
|
//-------------------------------------------------------
|
|
//
|
|
Verify(!Small_Enough(frameStart[currentFrame] - currentTime));
|
|
Scalar delta =
|
|
(frame_time - currentTime)/(frameStart[currentFrame] - currentTime);
|
|
|
|
for (i=0; i<jointCount; ++i)
|
|
{
|
|
current_joint =
|
|
jointSubToAnimate->GetJoint(jointIndices[i]);
|
|
Check(current_joint);
|
|
switch(current_joint->GetJointType())
|
|
{
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
Point3D new_trans;
|
|
EulerAngles new_angles;
|
|
|
|
new_angles.Lerp(
|
|
current_joint->GetEulerAngles(),
|
|
*(EulerAngles*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetEulerAngles() != new_angles)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetRotation(new_angles);
|
|
}
|
|
}
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
|
|
new_trans.Lerp(
|
|
current_joint->GetTranslation(),
|
|
*(Vector3D*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetTranslation() != new_trans)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetTranslation(new_trans);
|
|
}
|
|
}
|
|
to = (void *)((char *)to+sizeof(Vector3D));
|
|
break;
|
|
}
|
|
case Joint::HingeZJointType:
|
|
case Joint::HingeYJointType:
|
|
case Joint::HingeXJointType:
|
|
{
|
|
Hinge new_hinge;
|
|
new_hinge.Lerp(
|
|
current_joint->GetHinge(),
|
|
*(Hinge*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetRadians() != new_hinge.rotationAmount)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetRotation(new_hinge.rotationAmount);
|
|
}
|
|
}
|
|
to = (void *)((char *)to+sizeof(Hinge));
|
|
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
{
|
|
EulerAngles new_angles;
|
|
new_angles.Lerp(
|
|
current_joint->GetEulerAngles(),
|
|
*(EulerAngles*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetEulerAngles() != new_angles)
|
|
{
|
|
if (move_joints)
|
|
{
|
|
current_joint->SetRotation(new_angles);
|
|
}
|
|
}
|
|
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
|
|
break;
|
|
}
|
|
case Joint::StaticJointType:
|
|
break;
|
|
}
|
|
}
|
|
movement += (frame_time - currentTime) * rootTranslations[currentFrame].z;
|
|
currentTime = frame_time;
|
|
return movement;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Logical
|
|
AnimationInstance::LerpToPose(Scalar time_slice, Scalar time_to_lerp, Logical move_joints)
|
|
{
|
|
Check(this);
|
|
|
|
int i;
|
|
//
|
|
//-----------------------------------------
|
|
// This void * can point to any joint type
|
|
//-----------------------------------------
|
|
//
|
|
void
|
|
*to;
|
|
|
|
|
|
if (!lerpToZero)
|
|
{
|
|
lerpToZero = True;
|
|
deltaTime = time_to_lerp;
|
|
}
|
|
|
|
Scalar delta = time_slice / deltaTime;
|
|
|
|
|
|
//
|
|
//-------------------------------------------------------------
|
|
// to points to the place in the memory stream we left off at
|
|
// last time we were on this loop
|
|
//-------------------------------------------------------------
|
|
//
|
|
|
|
to = currentFrameTo;
|
|
Joint *current_joint;
|
|
|
|
if (move_joints)
|
|
{
|
|
for (i=0; i<jointCount; ++i)
|
|
{
|
|
current_joint =
|
|
jointSubToAnimate->GetJoint(jointIndices[i]);
|
|
Check(current_joint);
|
|
switch(current_joint->GetJointType())
|
|
{
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
Point3D new_trans;
|
|
EulerAngles new_angles;
|
|
|
|
new_angles.Lerp(
|
|
current_joint->GetEulerAngles(),
|
|
*(EulerAngles*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetEulerAngles() != new_angles)
|
|
{
|
|
current_joint->SetRotation(new_angles);
|
|
}
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
|
|
new_trans.Lerp(
|
|
current_joint->GetTranslation(),
|
|
*(Vector3D*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetTranslation() != new_trans)
|
|
{
|
|
current_joint->SetTranslation(new_trans);
|
|
}
|
|
to = (void *)((char *)to+sizeof(Vector3D));
|
|
break;
|
|
}
|
|
case Joint::HingeZJointType:
|
|
case Joint::HingeYJointType:
|
|
case Joint::HingeXJointType:
|
|
{
|
|
Hinge new_hinge;
|
|
new_hinge.Lerp(
|
|
current_joint->GetHinge(),
|
|
*(Hinge*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetRadians() != new_hinge.rotationAmount)
|
|
{
|
|
current_joint->SetRotation(new_hinge.rotationAmount);
|
|
}
|
|
to = (void *)((char *)to+sizeof(Hinge));
|
|
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
{
|
|
EulerAngles new_angles;
|
|
new_angles.Lerp(
|
|
current_joint->GetEulerAngles(),
|
|
*(EulerAngles*)to,
|
|
delta
|
|
);
|
|
if (current_joint->GetEulerAngles() != new_angles)
|
|
{
|
|
current_joint->SetRotation(new_angles);
|
|
}
|
|
|
|
to = (void *)((char *)to+sizeof(EulerAngles));
|
|
|
|
break;
|
|
}
|
|
case Joint::StaticJointType:
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
deltaTime -= time_slice;
|
|
if (deltaTime <= 0.0f)
|
|
{
|
|
lerpToZero = False;
|
|
return False;
|
|
}
|
|
return True;
|
|
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Logical
|
|
AnimationInstance::LerpToRest(Scalar time_slice, Scalar time_to_lerp, Logical move_joints)
|
|
{
|
|
|
|
|
|
if (!lerpToZero)
|
|
{
|
|
lerpToZero = True;
|
|
deltaTime = time_to_lerp;
|
|
}
|
|
|
|
Scalar delta = time_slice / deltaTime;
|
|
|
|
if (move_joints)
|
|
{
|
|
EulerAngles zero_euler(0.0f, 0.0f, 0.0f);
|
|
Hinge zero_hingeX(0.0f, X_Axis);
|
|
Hinge zero_hingeY(0.0f, Y_Axis);
|
|
Hinge zero_hingeZ(0.0f, Z_Axis);
|
|
Vector3D zero_vector(0.0f, 0.0f, 0.0f);
|
|
|
|
for (int i=0; i<jointCount; ++i)
|
|
{
|
|
Joint *current_joint =
|
|
jointSubToAnimate->GetJoint(jointIndices[i]);
|
|
Check(current_joint);
|
|
switch(current_joint->GetJointType())
|
|
{
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
EulerAngles new_angles;
|
|
new_angles.Lerp(
|
|
current_joint->GetEulerAngles(),
|
|
zero_euler,
|
|
delta
|
|
);
|
|
if (current_joint->GetEulerAngles() != new_angles)
|
|
{
|
|
current_joint->SetRotation(new_angles);
|
|
}
|
|
|
|
Point3D new_trans;
|
|
|
|
new_trans.Lerp(
|
|
current_joint->GetTranslation(),
|
|
zero_vector,
|
|
delta
|
|
);
|
|
if (current_joint->GetTranslation() != new_trans)
|
|
{
|
|
current_joint->SetTranslation(new_trans);
|
|
}
|
|
break;
|
|
}
|
|
case Joint::HingeXJointType:
|
|
{
|
|
Hinge new_hinge;
|
|
|
|
new_hinge.Lerp(
|
|
current_joint->GetHinge(),
|
|
zero_hingeX,
|
|
delta
|
|
);
|
|
if(current_joint->GetRadians() != new_hinge.rotationAmount)
|
|
{
|
|
current_joint->SetRotation(new_hinge.rotationAmount);
|
|
}
|
|
break;
|
|
|
|
}
|
|
case Joint::HingeYJointType:
|
|
{
|
|
Hinge new_hinge;
|
|
new_hinge.Lerp(
|
|
current_joint->GetHinge(),
|
|
zero_hingeY,
|
|
delta
|
|
);
|
|
if(current_joint->GetRadians() != new_hinge.rotationAmount)
|
|
{
|
|
current_joint->SetRotation(new_hinge.rotationAmount);
|
|
}
|
|
break;
|
|
}
|
|
case Joint::HingeZJointType:
|
|
{
|
|
Hinge new_hinge;
|
|
new_hinge.Lerp(
|
|
current_joint->GetHinge(),
|
|
zero_hingeZ,
|
|
delta
|
|
);
|
|
if(current_joint->GetRadians() != new_hinge.rotationAmount)
|
|
{
|
|
current_joint->SetRotation(new_hinge.rotationAmount);
|
|
}
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
{
|
|
EulerAngles new_angles;
|
|
|
|
new_angles.Lerp(
|
|
current_joint->GetEulerAngles(),
|
|
zero_euler,
|
|
delta
|
|
);
|
|
if (current_joint->GetEulerAngles() != new_angles)
|
|
{
|
|
current_joint->SetRotation(new_angles);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Joint::StaticJointType:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
deltaTime -= time_slice;
|
|
if (deltaTime <= 0.0f)
|
|
{
|
|
lerpToZero = False;
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void
|
|
AnimationInstance::SnapToRest(Logical move_joints)
|
|
{
|
|
|
|
if (!move_joints)
|
|
{
|
|
return;
|
|
}
|
|
|
|
EulerAngles zero_euler(0.0f, 0.0f, 0.0f);
|
|
Hinge zero_hingeX(0.0f, X_Axis);
|
|
Hinge zero_hingeY(0.0f, Y_Axis);
|
|
Hinge zero_hingeZ(0.0f, Z_Axis);
|
|
Point3D zero_point(0.0f, 0.0f, 0.0f);
|
|
|
|
for (int i=0; i<jointCount; ++i)
|
|
{
|
|
Joint *current_joint =
|
|
jointSubToAnimate->GetJoint(jointIndices[i]);
|
|
Check(current_joint);
|
|
switch(current_joint->GetJointType())
|
|
{
|
|
case Joint::BallTranslationJointType:
|
|
{
|
|
current_joint->SetRotation(zero_euler);
|
|
current_joint->SetTranslation(zero_point);
|
|
break;
|
|
}
|
|
case Joint::HingeXJointType:
|
|
{
|
|
current_joint->SetHinge(zero_hingeX);
|
|
break;
|
|
}
|
|
case Joint::HingeYJointType:
|
|
{
|
|
current_joint->SetHinge(zero_hingeY);
|
|
break;
|
|
}
|
|
case Joint::HingeZJointType:
|
|
{
|
|
current_joint->SetHinge(zero_hingeZ);
|
|
break;
|
|
}
|
|
case Joint::BallJointType:
|
|
{
|
|
current_joint->SetRotation(zero_euler);
|
|
break;
|
|
}
|
|
case Joint::StaticJointType:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//##########################################################################
|
|
//############## Sketon Notation file utilities ####################
|
|
//##########################################################################
|
|
|
|
|
|
int
|
|
Get_Active_Joint_Count(NotationFile *skl_file)
|
|
{
|
|
NameList *namelist = skl_file->MakePageList("joint");
|
|
Register_Object(namelist);
|
|
NameList::Entry *entry = namelist->GetFirstEntry();
|
|
|
|
int count = 0;
|
|
|
|
while (entry)
|
|
{
|
|
++count;
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
|
|
Unregister_Object(namelist);
|
|
delete namelist;
|
|
|
|
return count;
|
|
}
|
|
|
|
Logical
|
|
JointedMover::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(ClassDerivations);
|
|
}
|
|
|