#include "munga.h" #pragma hdrstop #include "jmover.h" #include "fileutil.h" #include "app.h" #include "notation.h" #include "namelist.h" //############################################################################# //############################ JointedMover ############################# //############################################################################# //############################################################################# // Shared Data Support // Derivation* JointedMover::GetClassDerivations() { static Derivation classDerivations(Mover::GetClassDerivations(), "JointedMover"); return &classDerivations; } JointedMover::SharedData JointedMover::DefaultData( JointedMover::GetClassDerivations(), JointedMover::GetMessageHandlers(), JointedMover::GetAttributeIndex(), 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::GetAttributeIndex() { static JointedMover::AttributeIndexSet attributeIndex(ELEMENTS(JointedMover::AttributePointers), JointedMover::AttributePointers, Mover::GetAttributeIndex() ); return 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> 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> 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> 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_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> child_index; current_segment->AddChildIndex(child_index, jj); } } } skl_resource->Unlock(); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Initialize all the child Pointers for each segment //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // for(ii=0;iiMakeChildIndexTable(); 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" << std::flush; 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" << std::flush; 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" << std::flush; 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" << std::flush; 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" << std::flush; 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"<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"<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" << std::flush; 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" << std::flush; 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" << std::flush; 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<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!"<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;ddGetChar(); int damage_zone_index; damage_zone_index = GetDamageZoneIndex(damage_zone_name, skl_file); if(damage_zone_index == -1) { DEBUG_STREAM<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;ccGetChar(), skl_file); if(child_index == -1) { DEBUG_STREAM<GetName()<<" Not Found!!"<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!"<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!"<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"<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;iiGetJoint(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; iGetJoint(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; iGetJoint(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; iGetJoint(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; iGetJoint(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; iGetJoint(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(*GetClassDerivations()); }