/* ================= idRenderWorldLocal::InitFromMap A NULL or empty name will make a world without a map model, which is still useful for displaying a bare model ================= */ bool idRenderWorldLocal::InitFromMap( const char* name ) { idLexer* src; idToken token; idRenderModel* lastModel; // if this is an empty world, initialize manually if( !name || !name[0] ) { FreeWorld(); mapName.Clear(); ClearWorld(); return true; } // load it idStrStatic< MAX_OSPATH > filename = name; filename.SetFileExtension( PROC_FILE_EXT ); // check for generated file idStrStatic< MAX_OSPATH > generatedFileName = filename; generatedFileName.Insert( "generated/", 0 ); generatedFileName.SetFileExtension( "bproc" ); // if we are reloading the same map, check the timestamp // and try to skip all the work ID_TIME_T currentTimeStamp = fileSystem->GetTimestamp( filename ); if( name == mapName ) { if( fileSystem->InProductionMode() || ( currentTimeStamp != FILE_NOT_FOUND_TIMESTAMP && currentTimeStamp == mapTimeStamp ) ) { common->Printf( "idRenderWorldLocal::InitFromMap: retaining existing map\n" ); FreeDefs(); TouchWorldModels(); AddWorldModelEntities(); ClearPortalStates(); return true; } common->Printf( "idRenderWorldLocal::InitFromMap: timestamp has changed, reloading.\n" ); } FreeWorld(); // see if we have a generated version of this static const byte BPROC_VERSION = 1; static const unsigned int BPROC_MAGIC = ( 'P' << 24 ) | ( 'R' << 16 ) | ( 'O' << 8 ) | BPROC_VERSION; bool loaded = false; idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) ); if( file != NULL ) { int numEntries = 0; int magic = 0; file->ReadBig( magic ); if( magic == BPROC_MAGIC ) { file->ReadBig( numEntries ); file->ReadString( mapName ); file->ReadBig( mapTimeStamp ); loaded = true; for( int i = 0; i < numEntries; i++ ) { idStrStatic< MAX_OSPATH > type; file->ReadString( type ); type.ToLower(); if( type == "model" ) { idRenderModel* lastModel = ReadBinaryModel( file ); if( lastModel == NULL ) { loaded = false; break; } renderModelManager->AddModel( lastModel ); localModels.Append( lastModel ); } else if( type == "shadowmodel" ) { idRenderModel* lastModel = ReadBinaryModel( file ); if( lastModel == NULL ) { loaded = false; break; } renderModelManager->AddModel( lastModel ); localModels.Append( lastModel ); } else if( type == "interareaportals" ) { ReadBinaryAreaPortals( file ); } else if( type == "nodes" ) { ReadBinaryNodes( file ); } else { idLib::Error( "Binary proc file failed, unexpected type %s\n", type.c_str() ); } } } } if( !loaded ) { src = new( TAG_RENDER ) idLexer( filename, LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE ); if( !src->IsLoaded() ) { common->Printf( "idRenderWorldLocal::InitFromMap: %s not found\n", filename.c_str() ); ClearWorld(); return false; } mapName = name; mapTimeStamp = currentTimeStamp; // if we are writing a demo, archive the load command if( common->WriteDemo() ) { WriteLoadMap(); } if( !src->ReadToken( &token ) || token.Icmp( PROC_FILE_ID ) ) { common->Printf( "idRenderWorldLocal::InitFromMap: bad id '%s' instead of '%s'\n", token.c_str(), PROC_FILE_ID ); delete src; return false; } int numEntries = 0; idFileLocal outputFile( fileSystem->OpenFileWrite( generatedFileName, "fs_basepath" ) ); if( outputFile != NULL ) { int magic = BPROC_MAGIC; outputFile->WriteBig( magic ); outputFile->WriteBig( numEntries ); outputFile->WriteString( mapName ); outputFile->WriteBig( mapTimeStamp ); } // parse the file while( 1 ) { if( !src->ReadToken( &token ) ) { break; } common->UpdateLevelLoadPacifier(); if( token == "model" ) { lastModel = ParseModel( src, name, currentTimeStamp, outputFile ); // add it to the model manager list renderModelManager->AddModel( lastModel ); // save it in the list to free when clearing this map localModels.Append( lastModel ); numEntries++; continue; } if( token == "shadowModel" ) { lastModel = ParseShadowModel( src, outputFile ); // add it to the model manager list renderModelManager->AddModel( lastModel ); // save it in the list to free when clearing this map localModels.Append( lastModel ); numEntries++; continue; } if( token == "interAreaPortals" ) { ParseInterAreaPortals( src, outputFile ); numEntries++; continue; } if( token == "nodes" ) { ParseNodes( src, outputFile ); numEntries++; continue; } src->Error( "idRenderWorldLocal::InitFromMap: bad token \"%s\"", token.c_str() ); } delete src; if( outputFile != NULL ) { outputFile->Seek( 0, FS_SEEK_SET ); int magic = BPROC_MAGIC; outputFile->WriteBig( magic ); outputFile->WriteBig( numEntries ); } } // if it was a trivial map without any areas, create a single area if( !numPortalAreas ) { ClearWorld(); } // find the points where we can early-our of reference pushing into the BSP tree CommonChildrenArea_r( &areaNodes[0] ); AddWorldModelEntities(); ClearPortalStates(); // done! return true; }
/* ================= idRenderWorldLocal::InitFromMap A NULL or empty name will make a world without a map model, which is still useful for displaying a bare model ================= */ bool idRenderWorldLocal::InitFromMap( const char *name ) { idLexer * src; idToken token; idStr filename; idRenderModel * lastModel; // if this is an empty world, initialize manually if ( !name || !name[0] ) { FreeWorld(); mapName.Clear(); ClearWorld(); return true; } // load it filename = name; filename.SetFileExtension( PROC_FILE_EXT ); // if we are reloading the same map, check the timestamp // and try to skip all the work ID_TIME_T currentTimeStamp; fileSystem->ReadFile( filename, NULL, ¤tTimeStamp ); if ( name == mapName ) { if ( currentTimeStamp != FILE_NOT_FOUND_TIMESTAMP && currentTimeStamp == mapTimeStamp ) { common->Printf( "idRenderWorldLocal::InitFromMap: retaining existing map\n" ); FreeDefs(); TouchWorldModels(); AddWorldModelEntities(); ClearPortalStates(); return true; } common->Printf( "idRenderWorldLocal::InitFromMap: timestamp has changed, reloading.\n" ); } FreeWorld(); src = new idLexer( filename, LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE ); if ( !src->IsLoaded() ) { common->Printf( "idRenderWorldLocal::InitFromMap: %s not found\n", filename.c_str() ); ClearWorld(); return false; } mapName = name; mapTimeStamp = currentTimeStamp; // if we are writing a demo, archive the load command if ( session->writeDemo ) { WriteLoadMap(); } if ( !src->ReadToken( &token ) || token.Icmp( PROC_FILE_ID ) ) { common->Printf( "idRenderWorldLocal::InitFromMap: bad id '%s' instead of '%s'\n", token.c_str(), PROC_FILE_ID ); delete src; return false; } // parse the file while ( 1 ) { if ( !src->ReadToken( &token ) ) { break; } if ( token == "model" ) { lastModel = ParseModel( src ); // add it to the model manager list renderModelManager->AddModel( lastModel ); // save it in the list to free when clearing this map localModels.Append( lastModel ); continue; } if ( token == "shadowModel" ) { lastModel = ParseShadowModel( src ); // add it to the model manager list renderModelManager->AddModel( lastModel ); // save it in the list to free when clearing this map localModels.Append( lastModel ); continue; } if ( token == "interAreaPortals" ) { ParseInterAreaPortals( src ); continue; } if ( token == "nodes" ) { ParseNodes( src ); continue; } src->Error( "idRenderWorldLocal::InitFromMap: bad token \"%s\"", token.c_str() ); } delete src; // if it was a trivial map without any areas, create a single area if ( !numPortalAreas ) { ClearWorld(); } // find the points where we can early-our of reference pushing into the BSP tree CommonChildrenArea_r( &areaNodes[0] ); AddWorldModelEntities(); ClearPortalStates(); // done! return true; }