#include "munga.h" #pragma hdrstop #include "cammgr.h" #include "mission.h" #include "app.h" #include "notation.h" #include "namelist.h" //########################################################################## //##################### CameraInstanceManager ####################### //########################################################################## //########################################################################## // Construction and Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstanceManager::CameraInstanceManager() : cameraList(NULL) { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Initialize local member data //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cameraIterator = new SChainIteratorOf(cameraList); Register_Object(cameraIterator); InitializeCameraInstances(); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstanceManager::~CameraInstanceManager() { DeleteCameraList(); Unregister_Object(cameraIterator); delete cameraIterator; cameraIterator = NULL; Check_Fpu(); } //########################################################################## // CameraInstance Creation and Deletion Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int CameraInstanceManager::FindUniqueCameraID() { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Finds a cameraID that has been freed up or the next sequential number //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // SChainIteratorOf iterator(cameraList); CameraInstance *camera_instance; int camera_ID = 0; Logical ID_exists = False; while(1) { // //~~~~~~~~~~~~~~~~~~~~ // Reset the iterator //~~~~~~~~~~~~~~~~~~~~ // iterator.First(); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Iterate through the list of all cameraInstances for every ID Chosen //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // while ( (camera_instance = iterator.ReadAndNext()) != NULL) { if(camera_ID == camera_instance->GetCameraID()) { ID_exists = True; break; } } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // If this cameraID not already used return the ID //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if(!ID_exists) { break; } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Otherwise increment the ID and reset the boolean //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ++camera_ID; ID_exists = False; } Check_Fpu(); return camera_ID; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void CameraInstanceManager::SetCamera( const Origin &new_origin, CameraInstance *camera_instance ) { if(!camera_instance) { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // No camera passed as an argument use cameraIterator //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // camera_instance = cameraIterator->GetCurrent(); if(!camera_instance) { CreateCameraInstance(new_origin); } else { camera_instance->SetLocalOrigin(new_origin); } } else { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Camera passed in set its origin //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // camera_instance->SetLocalOrigin(new_origin); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::CreateCameraInstance(const Origin &new_origin) { Check(this); // //~~~~~~~~~~~~~~~~~~~~~~~~ // Find a Unique CameraID //~~~~~~~~~~~~~~~~~~~~~~~~ // int camera_ID; camera_ID = FindUniqueCameraID(); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Create the new cameraInstance //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance *camera_instance = new CameraInstance( camera_ID, new_origin ); Register_Object(camera_instance); AddCameraInstance(camera_instance); Check_Fpu(); return camera_instance; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::AddCameraInstance(CameraInstance *camera_instance) { Check(this); Check(cameraIterator); Check(&cameraList); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Insert the new Camera Instance into the cameraList // & Point the cameraIterator to it //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // if (!cameraIterator->GetCurrent()) { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // If nothing in the cameraList create the first element //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cameraList.Add(camera_instance); cameraIterator->First(); Tell("Created the First Camera Instance \n"); } else { cameraList.Add(camera_instance); cameraIterator->Next(); Tell("Created a Camera Instance \n"); } Check_Fpu(); return camera_instance; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::DeleteCameraInstance() { CameraInstance *camera_instance = cameraIterator->GetCurrent(); if(!camera_instance) { return NULL; } cameraIterator->Remove(); if(!cameraIterator->GetCurrent()) { cameraIterator->First(); } Unregister_Object(camera_instance); delete camera_instance; return GetCurrent(); } //########################################################################## // CameraList Manipulator Functions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void CameraInstanceManager::DeleteCameraList() { while (cameraIterator->GetCurrent() != NULL) { DeleteCameraInstance(); } } //########################################################################## // CameraList Iterator Manipulator Functions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::IncrementIterator() { Check(this); if (cameraIterator->GetCurrent()) { Check(cameraIterator); cameraIterator->ReadAndNext(); if (!cameraIterator->GetCurrent()) { cameraIterator->First(); } } Check_Fpu(); return GetCurrent(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::DecrementIterator() { Check(this); if (cameraIterator->GetCurrent()) { Check(cameraIterator); cameraIterator->ReadAndPrevious(); if (!cameraIterator->GetCurrent()) { cameraIterator->Last(); } } Check_Fpu(); return GetCurrent(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::AdvanceIterator(const CameraInstance &camera_instance) { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Search for the camera_instance in the cameraList // Iterator points to camera_instance upon return //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Check(&camera_instance); Check(&cameraList); Check(cameraIterator); CameraInstance *current_instance; cameraIterator->First(); while((current_instance = cameraIterator->GetCurrent()) != NULL) { if(current_instance == &camera_instance) { Check_Fpu(); return current_instance; } cameraIterator->Next(); } // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // camera_instance not found return NULL //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Check_Fpu(); return NULL; } //########################################################################## // CameraList Searching and Query Functions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance* CameraInstanceManager::FindClosestCamera(const Point3D &point_3D) { // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Use a Simple distance formula to find closest camera //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Check(this); CameraInstance *closest_camera = NULL; Scalar dist_to_goal, min_dist=1e8f; SChainIteratorOf iterator(cameraList); CameraInstance *camera_instance; while ( (camera_instance = iterator.ReadAndNext()) != NULL) { Check(camera_instance); if (camera_instance->CanCameraSee(point_3D)) { Vector3D v; v.Subtract(point_3D, camera_instance->GetPosition()); dist_to_goal = v.LengthSquared(); Check_Fpu(); if (dist_to_goal < min_dist) { min_dist = dist_to_goal; closest_camera = camera_instance; } } } Check_Fpu(); return closest_camera; } //########################################################################## // Test Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical CameraInstanceManager::TestInstance() const { return True; } //########################################################################## // Tool Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void CameraInstanceManager::InitializeCameraInstances() { Check(application); ResourceDescription::ResourceID map_ID; map_ID = application->GetCurrentMission()->GetMapID(); ResourceFile *res_file; res_file = application->GetResourceFile(); Check(res_file); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Create the camera filename from the map name //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ResourceDescription *res = res_file->FindResourceDescription(map_ID); Check(res); Str_Copy( cameraFilename, "cameras\\", sizeof(cameraFilename) ); // // cam name matches map name // Str_Cat( cameraFilename, res->resourceName, sizeof(cameraFilename) ); // // trunc cam name to DOS filename size // int name_length = strlen(cameraFilename); if(name_length > 17) { cameraFilename[17] = '\0'; } // // Add the extension // Str_Cat( cameraFilename, ".cam", sizeof(cameraFilename) ); // //~~~~~~~~~~~~~~~~~~~~~~~~ // See if the file exists //~~~~~~~~~~~~~~~~~~~~~~~~ // std::fstream cam_file; //cam_file.open(cameraFilename, std::ios::nocreate | std::ios::in | std::ios::out); // following alternate line created by Ryan Bunker on 1/6/07 cam_file.open(cameraFilename, std::ios.in); if(cam_file) //NOTE: this appears broken (RB 1/6/07) { cam_file.close(); ReadNotationFile(); } else { cam_file.close(); CreateStreamedCameraInstances(res_file, res->resourceName); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void CameraInstanceManager::ReadNotationFile() { Check(this); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Create a Notation file out of the camera file //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // NotationFile *cam_file = new NotationFile(cameraFilename); Register_Object(cam_file); NameList* camera_namelist = cam_file->MakePageList(); Register_Object(camera_namelist); NameList::Entry *camera_entry = camera_namelist->GetFirstEntry(); char camera_page_name[128]; while (camera_entry) { Str_Copy( camera_page_name, camera_entry->GetName(), sizeof(camera_page_name) ); // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Create a new camera Instance for this page //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CameraInstance *camera_instance; const char *camera_data_entry; int cam_type; if( !cam_file->GetEntry( camera_page_name, "cameraType", &camera_data_entry ) ) { cam_type = CameraInstance::DefaultCameraType; } else { Check_Pointer(camera_data_entry); cam_type = CameraInstance::FindCameraType(camera_data_entry); } switch (cam_type) { case CameraInstance::DefaultCameraType: camera_instance = new CameraInstance(cam_file, camera_page_name); break; case CameraInstance::AlwaysSeesCameraType: camera_instance = new AlwaysSeesCameraInstance(cam_file, camera_page_name); break; } Register_Object(camera_instance); AddCameraInstance(camera_instance); camera_entry = camera_entry->GetNextEntry(); } Unregister_Object(camera_namelist); delete camera_namelist; Unregister_Object(cam_file); delete cam_file; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #define PAGE_NAME_SIZE 128 void CameraInstanceManager::CreateStreamedCameraInstances( ResourceFile *res_file, const char *map_name ) { Check(this); Check_Pointer(res_file); Check_Pointer(map_name); ResourceDescription *res = res_file->FindResourceDescription( map_name, ResourceDescription::CameraStreamResourceType ); if (!res) { Check_Fpu(); return; } res->Lock(); MemoryStream camera_stream(res->resourceAddress, res->resourceSize); int camera_count = *(int*)camera_stream.GetPointer(); camera_stream.AdvancePointer(sizeof(camera_count)); // //-------------------- // Read in each camera //-------------------- // while (camera_count--) { Check(&camera_stream); CameraInstance::StreamedInstance *model = (CameraInstance::StreamedInstance*)camera_stream.GetPointer(); Check_Pointer(model); CameraInstance *camera_instance; switch (model->cameraType) { case CameraInstance::DefaultCameraType: camera_instance = new CameraInstance(model); break; case CameraInstance::AlwaysSeesCameraType: camera_instance = new AlwaysSeesCameraInstance(model); break; } Register_Object(camera_instance); AddCameraInstance(camera_instance); camera_stream.AdvancePointer(model->instanceSize); } res->Unlock(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void CameraInstanceManager::WriteNotationFile() { Check(this); Check(&cameraList); NotationFile *camera_stream = new NotationFile(); Register_Object(camera_stream); if(!camera_stream) { Fail("Error Opening Camera File\n"); } SChainIteratorOf iterator(cameraList); CameraInstance *camera_instance; iterator.First(); while ( (camera_instance = iterator.ReadAndNext()) != NULL) { camera_instance->WriteNotationPage(camera_stream); } camera_stream->WriteFile(cameraFilename); Unregister_Object(camera_stream); delete camera_stream; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #define PAGE_NAME_SIZE 128 ResourceDescription::ResourceID CameraInstanceManager::CreateCameraInstancesStream( ResourceFile *resource_file, const char *camera_name, const ResourceDirectories *directories ) { Check_Pointer(camera_name); Check_Pointer(directories); // //------------------- // Open the .cam file //------------------- // int length = strlen(camera_name) + strlen(directories->mapDirectory)+ 1; char *filename = new char[length]; Register_Pointer(filename); Str_Copy(filename, directories->mapDirectory, length); strncat(filename, camera_name, strlen(camera_name)-3); Str_Cat(filename, "cam", length); NotationFile *camera_notation = new NotationFile(filename); Register_Object(camera_notation); if (camera_notation->PageCount() == 0) { DEBUG_STREAM << "Missing .cam file" << std::endl << std::flush; Dump_And_Die: Unregister_Object(camera_notation); delete camera_notation; Unregister_Pointer(filename); delete[] filename; return ResourceDescription::NullResourceID; } int camera_count = 0; NameList *pagelist = camera_notation->MakePageList(); Register_Object(pagelist); NameList::Entry *entry = pagelist->GetFirstEntry(); char page_name[PAGE_NAME_SIZE]; while (entry) { ++camera_count; entry = entry->GetNextEntry(); } size_t array_size = sizeof(CameraInstance::StreamedInstance) * camera_count * 2; long *camera_array = new long[(array_size+3) >> 2]; Register_Pointer(camera_array); MemoryStream camera_stream(camera_array, array_size); *(int*)camera_stream.GetPointer() = camera_count; camera_stream.AdvancePointer(sizeof(camera_count)); entry = pagelist->GetFirstEntry(); while (entry) { Str_Copy( page_name, entry->GetName(), sizeof(page_name) ); if(strcmp(page_name, "CameraInfo") == 0) { entry = entry->GetNextEntry(); continue; } Check(&camera_stream); CameraInstance::StreamedInstance *model = (CameraInstance::StreamedInstance*)camera_stream.GetPointer(); Check_Pointer(model); if ( !CameraInstance::CreateStreamedInstance( model, camera_notation, page_name ) ) { Unregister_Pointer(camera_array); delete[] camera_array; Unregister_Object(pagelist); delete pagelist; goto Dump_And_Die; } camera_stream.AdvancePointer(model->instanceSize); entry = entry->GetNextEntry(); } // //------------------------------- // Write the stream out to disk. // Str_Copy(filename, camera_name, length); filename[strlen(camera_name)-4] = '\0'; ResourceDescription *new_res = resource_file->AddResource( filename, ResourceDescription::CameraStreamResourceType, 1, ResourceDescription::LoadOnDemandFlag, camera_array, camera_stream.GetBytesUsed() ); Check(new_res); //----------- // Free Mem // Unregister_Pointer(camera_array); delete[] camera_array; Unregister_Pointer(filename); delete[] filename; Unregister_Object(camera_notation); delete camera_notation; Unregister_Object(pagelist); delete pagelist; return new_res->resourceID; }