mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-15 07:00:58 +00:00
Save rendermodels as OBJ if postLoadExportModels is set
This commit is contained in:
parent
95de9c62a5
commit
c664c9e940
5 changed files with 166 additions and 6 deletions
|
@ -714,6 +714,127 @@ void idRenderModelStatic::WriteBinaryModel( idFile* file, ID_TIME_T* _timeStamp
|
|||
file->WriteBig( hasShadowCastingSurfaces );
|
||||
}
|
||||
|
||||
// RB begin
|
||||
void idRenderModelStatic::ExportOBJ( idFile* objFile, idFile* mtlFile, ID_TIME_T* _timeStamp ) const
|
||||
{
|
||||
if( objFile == NULL || mtlFile == NULL )
|
||||
{
|
||||
common->Printf( "Failed to ExportOBJ\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
//objFile->Printf( "// generated by %s\n//\n\n", ENGINE_VERSION );
|
||||
|
||||
int numVerts = 0;
|
||||
idList< const idMaterial* > materials;
|
||||
|
||||
for( int i = 0; i < surfaces.Num(); i++ )
|
||||
{
|
||||
// shadow models use numVerts but have no verts
|
||||
if( ( surfaces[i].geometry != NULL ) && ( surfaces[i].geometry->numVerts > 0 ) && ( surfaces[i].geometry->numIndexes > 0 ) && ( surfaces[i].geometry->verts != NULL ) )
|
||||
{
|
||||
objFile->Printf( "o Geometry.%i\n", surfaces[i].id );
|
||||
|
||||
srfTriangles_t& tri = *surfaces[i].geometry;
|
||||
|
||||
//file->WriteVec3( tri.bounds[0] );
|
||||
//file->WriteVec3( tri.bounds[1] );
|
||||
|
||||
// TODO print additional info ?
|
||||
|
||||
//file->WriteBig( tri.generateNormals );
|
||||
//file->WriteBig( tri.tangentsCalculated );
|
||||
//file->WriteBig( tri.perfectHull );
|
||||
//file->WriteBig( tri.referencedIndexes );
|
||||
|
||||
if( tri.numVerts > 0 && tri.verts != NULL )
|
||||
{
|
||||
for( int j = 0; j < tri.numVerts; j++ )
|
||||
{
|
||||
objFile->Printf( "v %1.6f %1.6f %1.6f\n", tri.verts[j].xyz.x, tri.verts[j].xyz.y, tri.verts[j].xyz.z );
|
||||
}
|
||||
|
||||
for( int j = 0; j < tri.numVerts; j++ )
|
||||
{
|
||||
const idVec2 vST = tri.verts[j].GetTexCoord();
|
||||
|
||||
objFile->Printf( "vt %1.6f %1.6f\n", vST.x, 1.0f - vST.y );
|
||||
}
|
||||
|
||||
for( int j = 0; j < tri.numVerts; j++ )
|
||||
{
|
||||
const idVec3 n = tri.verts[j].GetNormalRaw();
|
||||
|
||||
objFile->Printf( "vn %1.6f %1.6f %1.6f\n", n.x, n.y, n.z );
|
||||
}
|
||||
|
||||
//file->WriteBigArray( tri.verts[j].st, 2 );
|
||||
//file->WriteBigArray( tri.verts[j].normal, 4 );
|
||||
//file->WriteBigArray( tri.verts[j].tangent, 4 );
|
||||
//file->WriteBigArray( tri.verts[j].color, sizeof( tri.verts[j].color ) / sizeof( tri.verts[j].color[0] ) );
|
||||
//file->WriteBigArray( tri.verts[j].color2, sizeof( tri.verts[j].color2 ) / sizeof( tri.verts[j].color2[0] ) );
|
||||
}
|
||||
|
||||
if( surfaces[i].shader != NULL && surfaces[i].shader->GetName() != NULL )
|
||||
{
|
||||
objFile->Printf( "usemtl %s\n", surfaces[i].shader->GetName() );
|
||||
|
||||
materials.AddUnique( surfaces[i].shader );
|
||||
}
|
||||
|
||||
objFile->Printf( "s 1\n" );
|
||||
|
||||
for( int j = 0; j < tri.numIndexes; j += 3 )
|
||||
{
|
||||
objFile->Printf( "f %i/%i/%i %i/%i/%i %i/%i/%i\n",
|
||||
tri.indexes[j + 2] + 1 + numVerts,
|
||||
tri.indexes[j + 2] + 1 + numVerts,
|
||||
tri.indexes[j + 2] + 1 + numVerts,
|
||||
|
||||
tri.indexes[j + 1] + 1 + numVerts,
|
||||
tri.indexes[j + 1] + 1 + numVerts,
|
||||
tri.indexes[j + 1] + 1 + numVerts,
|
||||
|
||||
tri.indexes[j + 0] + 1 + numVerts,
|
||||
tri.indexes[j + 0] + 1 + numVerts,
|
||||
tri.indexes[j + 0] + 1 + numVerts );
|
||||
}
|
||||
|
||||
objFile->Printf( "\n" );
|
||||
|
||||
numVerts += tri.numVerts;
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = 0; i < materials.Num(); i++ )
|
||||
{
|
||||
const idMaterial* material = materials[i];
|
||||
|
||||
mtlFile->Printf( "newmtl %s\n", material->GetName() );
|
||||
|
||||
if( material->GetFastPathDiffuseImage() )
|
||||
{
|
||||
idStr path = material->GetFastPathDiffuseImage()->GetName();
|
||||
path.SlashesToBackSlashes();
|
||||
path.DefaultFileExtension( ".tga" );
|
||||
|
||||
mtlFile->Printf( "\tmap_Kd //..\\..\\..\\%s\n", path.c_str() );
|
||||
}
|
||||
else if( material->GetEditorImage() )
|
||||
{
|
||||
idStr path = material->GetEditorImage()->GetName();
|
||||
path.SlashesToBackSlashes();
|
||||
path.DefaultFileExtension( ".tga" );
|
||||
|
||||
mtlFile->Printf( "\tmap_Kd //..\\..\\..\\%s\n", path.c_str() );
|
||||
}
|
||||
|
||||
|
||||
mtlFile->Printf( "\n" );
|
||||
}
|
||||
}
|
||||
// RB end
|
||||
|
||||
/*
|
||||
================
|
||||
idRenderModelStatic::LoadModel
|
||||
|
|
|
@ -172,6 +172,10 @@ public:
|
|||
virtual void WriteBinaryModel( idFile* file, ID_TIME_T* _timeStamp = NULL ) const = 0;
|
||||
virtual bool SupportsBinaryModel() = 0;
|
||||
|
||||
// RB begin
|
||||
virtual void ExportOBJ( idFile* objFile, idFile* mtlFile, ID_TIME_T* _timeStamp = NULL ) const = 0;
|
||||
// RB end
|
||||
|
||||
// renderBump uses this to load the very high poly count models, skipping the
|
||||
// shadow and tangent generation, along with some surface cleanup to make it load faster
|
||||
virtual void PartialInitFromFile( const char* fileName ) = 0;
|
||||
|
|
|
@ -32,9 +32,13 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "Model_local.h"
|
||||
#include "tr_local.h" // just for R_FreeWorldInteractions and R_CreateWorldInteractions
|
||||
|
||||
idCVar r_binaryLoadRenderModels( "r_binaryLoadRenderModels", "1", 0, "enable binary load/write of render models" );
|
||||
idCVar binaryLoadRenderModels( "binaryLoadRenderModels", "1", 0, "enable binary load/write of render models" );
|
||||
idCVar preload_MapModels( "preload_MapModels", "1", CVAR_SYSTEM | CVAR_BOOL, "preload models during begin or end levelload" );
|
||||
|
||||
// RB begin
|
||||
idCVar postLoadExportModels( "postLoadExportModels", "0", CVAR_BOOL | CVAR_RENDERER, "export models after loading to OBJ model format" );
|
||||
// RB end
|
||||
|
||||
class idRenderModelManagerLocal : public idRenderModelManager
|
||||
{
|
||||
public:
|
||||
|
@ -305,7 +309,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
// Get the timestamp on the original file, if it's newer than what is stored in binary model, regenerate it
|
||||
ID_TIME_T sourceTimeStamp = fileSystem->GetTimestamp( canonical );
|
||||
|
||||
if( model->SupportsBinaryModel() && r_binaryLoadRenderModels.GetBool() )
|
||||
if( model->SupportsBinaryModel() && binaryLoadRenderModels.GetBool() )
|
||||
{
|
||||
idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) );
|
||||
model->PurgeModel();
|
||||
|
@ -372,7 +376,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
|
||||
idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) );
|
||||
|
||||
if( !model->SupportsBinaryModel() || !r_binaryLoadRenderModels.GetBool() )
|
||||
if( !model->SupportsBinaryModel() || !binaryLoadRenderModels.GetBool() )
|
||||
{
|
||||
model->InitFromFile( canonical );
|
||||
}
|
||||
|
@ -436,6 +440,33 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
fileSystem->AddModelPreload( model->Name() );
|
||||
}
|
||||
|
||||
// RB begin
|
||||
if( postLoadExportModels.GetBool() && ( model != defaultModel && model != beamModel && model != spriteModel ) )
|
||||
{
|
||||
idStrStatic< MAX_OSPATH > exportedFileName;
|
||||
|
||||
exportedFileName = "exported/rendermodels/";
|
||||
exportedFileName.AppendPath( canonical );
|
||||
exportedFileName.SetFileExtension( ".obj" );
|
||||
|
||||
ID_TIME_T sourceTimeStamp = fileSystem->GetTimestamp( canonical );
|
||||
ID_TIME_T timeStamp = fileSystem->GetTimestamp( exportedFileName );
|
||||
|
||||
// TODO only update if generated has changed
|
||||
|
||||
//if( timeStamp == FILE_NOT_FOUND_TIMESTAMP )
|
||||
{
|
||||
idFileLocal objFile( fileSystem->OpenFileWrite( exportedFileName, "fs_basepath" ) );
|
||||
idLib::Printf( "Writing %s\n", exportedFileName.c_str() );
|
||||
|
||||
exportedFileName.SetFileExtension( ".mtl" );
|
||||
idFileLocal mtlFile( fileSystem->OpenFileWrite( exportedFileName, "fs_basepath" ) );
|
||||
|
||||
model->ExportOBJ( objFile, mtlFile );
|
||||
}
|
||||
}
|
||||
// RB end
|
||||
|
||||
AddModel( model );
|
||||
|
||||
return model;
|
||||
|
|
|
@ -57,6 +57,10 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
// RB begin
|
||||
virtual void ExportOBJ( idFile* objFile, idFile* mtlFile, ID_TIME_T* _timeStamp = NULL ) const;
|
||||
// RB end
|
||||
|
||||
virtual void PartialInitFromFile( const char* fileName );
|
||||
virtual void PurgeModel();
|
||||
virtual void Reset() {};
|
||||
|
|
|
@ -134,7 +134,7 @@ idRenderModel* idRenderWorldLocal::ReadBinaryModel( idFile* fileIn )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
extern idCVar r_binaryLoadRenderModels;
|
||||
extern idCVar binaryLoadRenderModels;
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -298,7 +298,7 @@ idRenderModel* idRenderWorldLocal::ParseModel( idLexer* src, const char* mapName
|
|||
|
||||
model->FinishSurfaces();
|
||||
|
||||
if( fileOut != NULL && model->SupportsBinaryModel() && r_binaryLoadRenderModels.GetBool() )
|
||||
if( fileOut != NULL && model->SupportsBinaryModel() && binaryLoadRenderModels.GetBool() )
|
||||
{
|
||||
model->WriteBinaryModel( fileOut, &mapTimeStamp );
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ idRenderModel* idRenderWorldLocal::ParseShadowModel( idLexer* src, idFile* fileO
|
|||
|
||||
// NOTE: we do NOT do a model->FinishSurfaceces, because we don't need sil edges, planes, tangents, etc.
|
||||
|
||||
if( fileOut != NULL && model->SupportsBinaryModel() && r_binaryLoadRenderModels.GetBool() )
|
||||
if( fileOut != NULL && model->SupportsBinaryModel() && binaryLoadRenderModels.GetBool() )
|
||||
{
|
||||
model->WriteBinaryModel( fileOut, &mapTimeStamp );
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue