mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-13 22:22:05 +00:00
Allow static glTF2 models to be inlined in dmap and kicked unused Collada DAE support
This commit is contained in:
parent
aab5a4844f
commit
c035a5b867
13 changed files with 183 additions and 5054 deletions
|
@ -37,7 +37,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "Model_ase.h"
|
||||
#include "Model_lwo.h"
|
||||
#include "Model_ma.h"
|
||||
#include "Model_ColladaParser.h"
|
||||
#include "Model_obj.h"
|
||||
|
||||
idCVar idRenderModelStatic::r_mergeModelSurfaces( "r_mergeModelSurfaces", "1", CVAR_BOOL | CVAR_RENDERER, "combine model surfaces with the same material" );
|
||||
|
@ -266,7 +265,11 @@ void idRenderModelStatic::MakeDefaultModel()
|
|||
|
||||
srfTriangles_t* tri = R_AllocStaticTriSurf();
|
||||
|
||||
#if defined( DMAP )
|
||||
surf.shader = declManager->FindMaterial( "_default", false );
|
||||
#else
|
||||
surf.shader = tr.defaultMaterial;
|
||||
#endif
|
||||
surf.geometry = tri;
|
||||
|
||||
R_AllocStaticTriSurfVerts( tri, 24 );
|
||||
|
@ -323,12 +326,6 @@ void idRenderModelStatic::InitFromFile( const char* fileName, const idImportOpti
|
|||
loaded = LoadASE( name, &sourceTimeStamp );
|
||||
reloadable = true;
|
||||
}
|
||||
// RB: Collada DAE and Wavefront OBJ
|
||||
else if( extension.Icmp( "dae" ) == 0 )
|
||||
{
|
||||
loaded = LoadDAE( name, &sourceTimeStamp );
|
||||
reloadable = true;
|
||||
}
|
||||
else if( extension.Icmp( "obj" ) == 0 )
|
||||
{
|
||||
loaded = LoadOBJ( name, &sourceTimeStamp );
|
||||
|
@ -1332,474 +1329,6 @@ typedef struct matchVert_s
|
|||
idVec3 normal;
|
||||
} matchVert_t;
|
||||
|
||||
bool idRenderModelStatic::ConvertDAEToModelSurfaces( const ColladaParser* dae )
|
||||
{
|
||||
Collada::Node** object;
|
||||
Collada::Mesh** mesh;
|
||||
Collada::MeshInstance* meshInstance;
|
||||
// Collada::Material** material;
|
||||
const idMaterial* im1, *im2;
|
||||
srfTriangles_t* tri;
|
||||
int objectNum;
|
||||
int i, j, k;
|
||||
int index, v, tv;
|
||||
int* vRemap;
|
||||
int* tvRemap;
|
||||
matchVert_t* mvTable; // all of the match verts
|
||||
matchVert_t** mvHash; // points inside mvTable for each xyz index
|
||||
matchVert_t* lastmv;
|
||||
matchVert_t* mv;
|
||||
idVec3 normal;
|
||||
int* mergeTo;
|
||||
byte* color;
|
||||
static byte identityColor[4] = { 255, 255, 255, 255 };
|
||||
modelSurface_t surf, *modelSurf;
|
||||
|
||||
|
||||
if( dae->mNodeLibrary.Num() < 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
timeStamp = dae->mReader->getTimestamp();
|
||||
|
||||
// the modeling programs can save out multiple surfaces with a common
|
||||
// material, but we would like to mege them together where possible
|
||||
// meaning that this->NumSurfaces() <= ase->objects.currentElements
|
||||
mergeTo = ( int* )_alloca( dae->mNodeLibrary.Num() * sizeof( *mergeTo ) );
|
||||
surf.geometry = NULL;
|
||||
|
||||
if( dae->mMaterialLibrary.Num() == 0 )
|
||||
{
|
||||
// if we don't have any materials, dump everything into a single surface
|
||||
surf.shader = tr.defaultMaterial;
|
||||
surf.id = 0;
|
||||
this->AddSurface( surf );
|
||||
for( i = 0 ; i < dae->mNodeLibrary.Num() ; i++ )
|
||||
{
|
||||
mergeTo[i] = 0;
|
||||
}
|
||||
}
|
||||
else if( !r_mergeModelSurfaces.GetBool() )
|
||||
{
|
||||
// don't merge any
|
||||
for( i = 0; i < dae->mNodeLibrary.Num(); i++ )
|
||||
{
|
||||
mergeTo[i] = i;
|
||||
object = dae->mNodeLibrary.GetIndex( i ); //object = ase->objects[i];
|
||||
|
||||
if( ( *object )->mMeshes.Num() <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
meshInstance = &( *object )->mMeshes[0]; //mesh = &object->mesh;
|
||||
|
||||
idStr matName = "_default";
|
||||
if( meshInstance->mMaterials.Num() > 0 )
|
||||
{
|
||||
matName = meshInstance->mMaterials[ 0 ]; //material = ase->materials[object->materialRef];
|
||||
|
||||
matName.Replace( "_", "/" );
|
||||
matName.StripTrailingOnce( "-material" );
|
||||
}
|
||||
|
||||
surf.shader = declManager->FindMaterial( matName );
|
||||
surf.id = this->NumSurfaces();
|
||||
this->AddSurface( surf );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// search for material matches
|
||||
for( i = 0 ; i < dae->mNodeLibrary.Num() ; i++ )
|
||||
{
|
||||
object = dae->mNodeLibrary.GetIndex( i );
|
||||
|
||||
if( ( *object )->mMeshes.Num() <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
meshInstance = &( *object )->mMeshes[0]; //mesh = &object->mesh;
|
||||
|
||||
idStr matName = "_default";
|
||||
if( meshInstance->mMaterials.Num() > 0 )
|
||||
{
|
||||
matName = meshInstance->mMaterials[ 0 ]; //material = ase->materials[object->materialRef];
|
||||
|
||||
matName.Replace( "_", "/" );
|
||||
matName.StripTrailingOnce( "-material" );
|
||||
}
|
||||
|
||||
im1 = declManager->FindMaterial( matName );
|
||||
if( im1->IsDiscrete() )
|
||||
{
|
||||
// flares, autosprites, etc
|
||||
j = this->NumSurfaces();
|
||||
}
|
||||
else
|
||||
{
|
||||
for( j = 0 ; j < this->NumSurfaces() ; j++ )
|
||||
{
|
||||
modelSurf = &this->surfaces[j];
|
||||
im2 = modelSurf->shader;
|
||||
if( im1 == im2 )
|
||||
{
|
||||
// merge this
|
||||
mergeTo[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( j == this->NumSurfaces() )
|
||||
{
|
||||
// didn't merge
|
||||
mergeTo[i] = j;
|
||||
surf.shader = im1;
|
||||
surf.id = this->NumSurfaces();
|
||||
this->AddSurface( surf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idVectorSubset<idVec3, 3> vertexSubset;
|
||||
idVectorSubset<idVec2, 2> texCoordSubset;
|
||||
|
||||
// build the surfaces
|
||||
for( objectNum = 0; objectNum < dae->mNodeLibrary.Num(); objectNum++ )
|
||||
{
|
||||
object = ( dae->mNodeLibrary.GetIndex( objectNum ) ); //object = ase->objects[objectNum];
|
||||
|
||||
if( ( *object )->mMeshes.Num() <= 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
meshInstance = &( *object )->mMeshes[0]; //mesh = &object->mesh;
|
||||
|
||||
idStr matName = "_default";
|
||||
#if 0
|
||||
if( meshInstance->mMaterials.Num() )
|
||||
{
|
||||
const Collada::SemanticMappingTable* mappingTable = meshInstance->mMaterials.GetIndex( 0 );
|
||||
idStr materialId = mappingTable->mMatName;
|
||||
|
||||
if( dae->mMaterialLibrary.Get( materialId, &material ) )
|
||||
{
|
||||
matName = ( *material )->mEffect;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if( meshInstance->mMaterials.Num() > 0 )
|
||||
{
|
||||
matName = meshInstance->mMaterials[ 0 ]; //material = ase->materials[object->materialRef];
|
||||
|
||||
matName.Replace( "_", "/" );
|
||||
matName.StripTrailingOnce( "-material" );
|
||||
}
|
||||
|
||||
#endif
|
||||
im1 = declManager->FindMaterial( matName );
|
||||
|
||||
// It seems like the tools our artists are using often generate
|
||||
// verts and texcoords slightly separated that should be merged
|
||||
// note that we really should combine the surfaces with common materials
|
||||
// before doing this operation, because we can miss a slop combination
|
||||
// if they are in different surfaces
|
||||
|
||||
idStr meshId = ( meshInstance )->mMeshOrController;
|
||||
dae->mMeshLibrary.Get( meshId, &mesh );
|
||||
|
||||
bool normalsParsed = ( * mesh )->mNormals.Num() > 0; //mesh->normalsParsed;
|
||||
|
||||
// completely ignore any explict normals on surfaces with a renderbump command
|
||||
// which will guarantee the best contours and least vertexes.
|
||||
const char* rb = im1->GetRenderBump();
|
||||
if( rb && rb[0] )
|
||||
{
|
||||
normalsParsed = false;
|
||||
}
|
||||
|
||||
|
||||
// TODO calculate nodeTransforms recursively using the scene hierarchy
|
||||
|
||||
// transform vertex positions and normals
|
||||
idMat4 nodeTransform = dae->CalculateResultTransform( ( *object )->mTransforms );
|
||||
|
||||
// reset origin to zero for root node
|
||||
if( objectNum == 0 )
|
||||
{
|
||||
nodeTransform[0][3] = 0;
|
||||
nodeTransform[1][3] = 0;
|
||||
nodeTransform[2][3] = 0;
|
||||
}
|
||||
|
||||
|
||||
for( j = 0; j < ( *mesh )->mPositions.Num(); j++ )
|
||||
{
|
||||
const idVec3& p = ( *mesh )->mPositions[j];
|
||||
|
||||
( *mesh )->mPositions[ j ] = nodeTransform * p;
|
||||
}
|
||||
|
||||
for( j = 0; j < ( *mesh )->mNormals.Num(); j++ )
|
||||
{
|
||||
const idVec3& n = ( *mesh )->mNormals[j];
|
||||
|
||||
idVec4 n2( n.x, n.y, n.z, 0 );
|
||||
n2 = nodeTransform * n2;
|
||||
n2.Normalize();
|
||||
|
||||
( *mesh )->mNormals[ j ] = n2.ToVec3();
|
||||
}
|
||||
|
||||
|
||||
vRemap = ( int* )R_StaticAlloc( ( *mesh )->mPositions.Num() * sizeof( vRemap[0] ) );
|
||||
|
||||
#if 0
|
||||
for( j = 0; j < ( *mesh )->mPositions.Num(); j++ )
|
||||
{
|
||||
vRemap[j] = j;
|
||||
}
|
||||
#else
|
||||
if( fastLoad )
|
||||
{
|
||||
// renderbump doesn't care about vertex count
|
||||
for( j = 0; j < ( *mesh )->mPositions.Num(); j++ )
|
||||
{
|
||||
vRemap[j] = j;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float vertexEpsilon = r_slopVertex.GetFloat();
|
||||
float expand = 2 * 32 * vertexEpsilon;
|
||||
idVec3 mins, maxs;
|
||||
|
||||
SIMDProcessor->MinMax( mins, maxs, &( *mesh )->mPositions[0], ( *mesh )->mPositions.Num() );
|
||||
mins -= idVec3( expand, expand, expand );
|
||||
maxs += idVec3( expand, expand, expand );
|
||||
vertexSubset.Init( mins, maxs, 32, 1024 );
|
||||
for( j = 0; j < ( *mesh )->mPositions.Num(); j++ )
|
||||
{
|
||||
vRemap[j] = vertexSubset.FindVector( &( *mesh )->mPositions[0], j, vertexEpsilon );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
tvRemap = ( int* )R_StaticAlloc( ( *mesh )->mTexCoords.Num() * sizeof( tvRemap[0] ) );
|
||||
|
||||
#if 0
|
||||
for( j = 0; j < ( *mesh )->mTexCoords.Num(); j++ )
|
||||
{
|
||||
tvRemap[j] = j;
|
||||
}
|
||||
#else
|
||||
if( fastLoad )
|
||||
{
|
||||
// renderbump doesn't care about vertex count
|
||||
for( j = 0; j < ( *mesh )->mTexCoords.Num(); j++ )
|
||||
{
|
||||
tvRemap[j] = j;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float texCoordEpsilon = r_slopTexCoord.GetFloat();
|
||||
float expand = 2 * 32 * texCoordEpsilon;
|
||||
idVec2 mins, maxs;
|
||||
|
||||
SIMDProcessor->MinMax( mins, maxs, &( *mesh )->mTexCoords[0], ( *mesh )->mTexCoords.Num() );
|
||||
mins -= idVec2( expand, expand );
|
||||
maxs += idVec2( expand, expand );
|
||||
texCoordSubset.Init( mins, maxs, 32, 1024 );
|
||||
for( j = 0; j < ( *mesh )->mTexCoords.Num(); j++ )
|
||||
{
|
||||
tvRemap[j] = texCoordSubset.FindVector( &( *mesh )->mTexCoords[0], j, texCoordEpsilon );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// we need to find out how many unique vertex / texcoord combinations
|
||||
// there are, because ASE tracks them separately but we need them unified
|
||||
|
||||
// the maximum possible number of combined vertexes is the number of indexes
|
||||
mvTable = ( matchVert_t* )R_ClearedStaticAlloc( ( *mesh )->mFacePosIndices.Num() * sizeof( mvTable[0] ) );
|
||||
|
||||
// we will have a hash chain based on the xyz values
|
||||
mvHash = ( matchVert_t** )R_ClearedStaticAlloc( ( *mesh )->mPositions.Num() * sizeof( mvHash[0] ) );
|
||||
|
||||
// allocate triangle surface
|
||||
tri = R_AllocStaticTriSurf();
|
||||
tri->numVerts = 0;
|
||||
tri->numIndexes = 0;
|
||||
R_AllocStaticTriSurfIndexes( tri, ( *mesh )->mFacePosIndices.Num() ); //mesh->numFaces * 3 );
|
||||
tri->generateNormals = !normalsParsed;
|
||||
|
||||
// init default normal, color and tex coord index
|
||||
normal.Zero();
|
||||
color = identityColor;
|
||||
tv = 0;
|
||||
|
||||
// find all the unique combinations
|
||||
float normalEpsilon = 1.0f - r_slopNormal.GetFloat();
|
||||
|
||||
for( j = 0; j < ( ( *mesh )->mFacePosIndices.Num() / 3 ); j++ )
|
||||
//for( j = 0; j < ( *mesh )->mFacePosIndices.Num(); j++ )
|
||||
{
|
||||
// construct triangles in reverse order
|
||||
for( k = 2; k >= 0; k-- )
|
||||
//for( k = 0; k < 3; k++ )
|
||||
{
|
||||
//v = mesh->faces[j].vertexNum[k];
|
||||
|
||||
//v = ( *mesh )->mFacePosIndices[j];
|
||||
index = j * 3 + k;
|
||||
|
||||
if( index < 0 || index >= ( *mesh )->mPositions.Num() )
|
||||
{
|
||||
common->Error( "ConvertDAEToModelSurfaces: bad vertex index in DAE file %s", name.c_str() );
|
||||
}
|
||||
|
||||
// collapse the position if it was slightly offset
|
||||
v = vRemap[ index ];
|
||||
|
||||
#if 1
|
||||
// we may or may not have texcoords to compare
|
||||
//if( mesh->numTVFaces == mesh->numFaces && mesh->numTVertexes != 0 )
|
||||
if( ( *mesh )->mTexCoords.Num() )
|
||||
{
|
||||
tv = index; //tv = mesh->faces[j].tVertexNum[k];
|
||||
|
||||
if( tv < 0 || tv >= ( *mesh )->mTexCoords.Num() )
|
||||
{
|
||||
common->Error( "ConvertDAEToModelSurfaces: bad tex coord index in DAE file %s", name.c_str() );
|
||||
}
|
||||
|
||||
// collapse the tex coord if it was slightly offset
|
||||
tv = tvRemap[tv];
|
||||
}
|
||||
|
||||
|
||||
// we may or may not have normals to compare
|
||||
if( normalsParsed )
|
||||
{
|
||||
normal = ( *mesh )->mNormals[ index ]; //mesh->faces[j].vertexNormals[k];
|
||||
}
|
||||
|
||||
// we may or may not have colors to compare
|
||||
if( ( *mesh )->mColors.Num() > 0 )
|
||||
{
|
||||
color = ( byte* ) & ( *mesh )->mColors[ index ]; //mesh->faces[j].vertexColors[k];
|
||||
}
|
||||
#endif
|
||||
// find a matching vert
|
||||
for( lastmv = NULL, mv = mvHash[v]; mv != NULL; lastmv = mv, mv = mv->next )
|
||||
{
|
||||
#if 1
|
||||
if( mv->tv != tv )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( *( unsigned* )mv->color != *( unsigned* )color )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !normalsParsed )
|
||||
{
|
||||
// if we are going to create the normals, just
|
||||
// matching texcoords is enough
|
||||
break;
|
||||
}
|
||||
|
||||
if( mv->normal * normal > normalEpsilon )
|
||||
{
|
||||
break; // we already have this one
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( !mv )
|
||||
{
|
||||
// allocate a new match vert and link to hash chain
|
||||
mv = &mvTable[ tri->numVerts ];
|
||||
mv->v = v;
|
||||
mv->tv = tv;
|
||||
mv->normal = normal;
|
||||
*( unsigned* )mv->color = *( unsigned* )color;
|
||||
mv->next = NULL;
|
||||
|
||||
if( lastmv )
|
||||
{
|
||||
lastmv->next = mv;
|
||||
}
|
||||
else
|
||||
{
|
||||
mvHash[v] = mv;
|
||||
}
|
||||
tri->numVerts++;
|
||||
}
|
||||
|
||||
tri->indexes[tri->numIndexes] = mv - mvTable;
|
||||
tri->numIndexes++;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate space for the indexes and copy them
|
||||
if( tri->numIndexes > ( *mesh )->mFacePosIndices.Num() )// mesh->numFaces * 3 )
|
||||
{
|
||||
common->FatalError( "ConvertDAEToModelSurfaces: index miscount in DAE file %s", name.c_str() );
|
||||
}
|
||||
if( tri->numVerts > ( *mesh )->mFacePosIndices.Num() ) //mesh->numFaces * 3 )
|
||||
{
|
||||
common->FatalError( "ConvertDAEToModelSurfaces: vertex miscount in DAE file %s", name.c_str() );
|
||||
}
|
||||
|
||||
// now allocate and generate the combined vertexes
|
||||
R_AllocStaticTriSurfVerts( tri, tri->numVerts );
|
||||
for( j = 0; j < tri->numVerts; j++ )
|
||||
{
|
||||
mv = &mvTable[j];
|
||||
tri->verts[ j ].Clear();
|
||||
tri->verts[ j ].xyz = ( *mesh )->mPositions[ mv->v ];
|
||||
tri->verts[ j ].SetNormal( mv->normal );
|
||||
*( unsigned* )tri->verts[j].color = *( unsigned* )mv->color;
|
||||
|
||||
if( ( *mesh )->mTexCoords.Num() > 0 )
|
||||
{
|
||||
const idVec2& tv = ( *mesh )->mTexCoords[ mv->tv ];
|
||||
float u = tv.x;
|
||||
float v = tv.y;
|
||||
tri->verts[ j ].SetTexCoord( u, v );
|
||||
}
|
||||
}
|
||||
|
||||
R_StaticFree( mvTable );
|
||||
R_StaticFree( mvHash );
|
||||
R_StaticFree( tvRemap );
|
||||
R_StaticFree( vRemap );
|
||||
|
||||
// see if we need to merge with a previous surface of the same material
|
||||
modelSurf = &this->surfaces[mergeTo[ objectNum ]];
|
||||
srfTriangles_t* mergeTri = modelSurf->geometry;
|
||||
if( !mergeTri )
|
||||
{
|
||||
modelSurf->geometry = tri;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelSurf->geometry = R_MergeTriangles( mergeTri, tri );
|
||||
R_FreeStaticTriSurf( tri );
|
||||
R_FreeStaticTriSurf( mergeTri );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idRenderModelStatic::ConvertOBJToModelSurfaces
|
||||
|
@ -2206,7 +1735,11 @@ bool idRenderModelStatic::ConvertASEToModelSurfaces( const struct aseModel_s* as
|
|||
if( ase->materials.Num() == 0 )
|
||||
{
|
||||
// if we don't have any materials, dump everything into a single surface
|
||||
#if defined( DMAP )
|
||||
surf.shader = declManager->FindMaterial( "_default", false );
|
||||
#else
|
||||
surf.shader = tr.defaultMaterial;
|
||||
#endif
|
||||
surf.id = 0;
|
||||
this->AddSurface( surf );
|
||||
for( i = 0; i < ase->objects.Num(); i++ )
|
||||
|
@ -3193,7 +2726,11 @@ bool idRenderModelStatic::ConvertMAToModelSurfaces( const struct maModel_s* ma )
|
|||
if( ma->materials.Num() == 0 )
|
||||
{
|
||||
// if we don't have any materials, dump everything into a single surface
|
||||
#if defined( DMAP )
|
||||
surf.shader = declManager->FindMaterial( "_default", false );
|
||||
#else
|
||||
surf.shader = tr.defaultMaterial;
|
||||
#endif
|
||||
surf.id = 0;
|
||||
this->AddSurface( surf );
|
||||
for( i = 0; i < ma->objects.Num(); i++ )
|
||||
|
@ -3215,7 +2752,11 @@ bool idRenderModelStatic::ConvertMAToModelSurfaces( const struct maModel_s* ma )
|
|||
}
|
||||
else
|
||||
{
|
||||
#if defined( DMAP )
|
||||
surf.shader = declManager->FindMaterial( "_default", false );
|
||||
#else
|
||||
surf.shader = tr.defaultMaterial;
|
||||
#endif
|
||||
}
|
||||
surf.id = this->NumSurfaces();
|
||||
this->AddSurface( surf );
|
||||
|
@ -3234,7 +2775,11 @@ bool idRenderModelStatic::ConvertMAToModelSurfaces( const struct maModel_s* ma )
|
|||
}
|
||||
else
|
||||
{
|
||||
#if defined( DMAP )
|
||||
im1 = declManager->FindMaterial( "_default", false );
|
||||
#else
|
||||
im1 = tr.defaultMaterial;
|
||||
#endif
|
||||
}
|
||||
if( im1->IsDiscrete() )
|
||||
{
|
||||
|
@ -3281,7 +2826,11 @@ bool idRenderModelStatic::ConvertMAToModelSurfaces( const struct maModel_s* ma )
|
|||
}
|
||||
else
|
||||
{
|
||||
#if defined( DMAP )
|
||||
im1 = declManager->FindMaterial( "_default", false );
|
||||
#else
|
||||
im1 = tr.defaultMaterial;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool normalsParsed = mesh->normalsParsed;
|
||||
|
@ -3608,36 +3157,6 @@ bool idRenderModelStatic::LoadMA( const char* fileName, ID_TIME_T* sourceTimeSta
|
|||
return true;
|
||||
}
|
||||
|
||||
// RB: added COLLADA support
|
||||
bool idRenderModelStatic::LoadDAE( const char* fileName, ID_TIME_T* sourceTimeStamp )
|
||||
{
|
||||
bool loaded = false;
|
||||
|
||||
#if defined(USE_EXCEPTIONS)
|
||||
try
|
||||
#endif
|
||||
{
|
||||
idTimer timer;
|
||||
timer.Start();
|
||||
|
||||
ColladaParser parser( fileName, sourceTimeStamp );
|
||||
|
||||
loaded = ConvertDAEToModelSurfaces( &parser );
|
||||
|
||||
timer.Stop();
|
||||
|
||||
common->Printf( "...loaded '%s' in %5.2f seconds\n", fileName, timer.Milliseconds() / 1000.0 );
|
||||
}
|
||||
#if defined(USE_EXCEPTIONS)
|
||||
catch( idException& e )
|
||||
{
|
||||
common->Warning( "%s", e.GetError() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idRenderModelStatic::LoadOBJ
|
||||
|
|
|
@ -30,13 +30,16 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "Model_gltf.h"
|
||||
#include "Model_local.h"
|
||||
#include "RenderCommon.h" // just for R_FreeWorldInteractions and R_CreateWorldInteractions
|
||||
|
||||
#include <sys/DeviceManager.h>
|
||||
#if !defined( DMAP )
|
||||
#include <sys/DeviceManager.h>
|
||||
extern DeviceManager* deviceManager;
|
||||
#endif
|
||||
|
||||
extern DeviceManager* deviceManager;
|
||||
extern idCVar r_vkUploadBufferSizeMB;
|
||||
|
||||
idCVar binaryLoadRenderModels( "binaryLoadRenderModels", "1", 0, "enable binary load/write of render models" );
|
||||
|
@ -241,6 +244,7 @@ idRenderModelManagerLocal::Init
|
|||
*/
|
||||
void idRenderModelManagerLocal::Init()
|
||||
{
|
||||
#if !defined( DMAP )
|
||||
if( !commandList )
|
||||
{
|
||||
nvrhi::CommandListParameters params = {};
|
||||
|
@ -253,6 +257,7 @@ void idRenderModelManagerLocal::Init()
|
|||
}
|
||||
commandList = deviceManager->GetDevice()->createCommandList( params );
|
||||
}
|
||||
#endif
|
||||
|
||||
cmdSystem->AddCommand( "listModels", ListModels_f, CMD_FL_RENDERER, "lists all models" );
|
||||
cmdSystem->AddCommand( "printModel", PrintModel_f, CMD_FL_RENDERER, "prints model info", idCmdSystem::ArgCompletion_ModelName );
|
||||
|
@ -269,6 +274,7 @@ void idRenderModelManagerLocal::Init()
|
|||
defaultModel = model;
|
||||
AddModel( model );
|
||||
|
||||
#if !defined( DMAP )
|
||||
// create the beam model
|
||||
idRenderModelStatic* beam = new( TAG_MODEL ) idRenderModelBeam;
|
||||
beam->InitEmpty( "_BEAM" );
|
||||
|
@ -281,6 +287,7 @@ void idRenderModelManagerLocal::Init()
|
|||
sprite->SetLevelLoadReferenced( true );
|
||||
spriteModel = sprite;
|
||||
AddModel( sprite );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -399,13 +406,14 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
model = new( TAG_MODEL ) idRenderModelGLTF;
|
||||
isGLTF = true;
|
||||
}
|
||||
// RB: Collada DAE and Wavefront OBJ
|
||||
else if( ( extension.Icmp( "dae" ) == 0 ) || ( extension.Icmp( "obj" ) == 0 )
|
||||
// RB: Wavefront OBJ
|
||||
else if( ( extension.Icmp( "obj" ) == 0 )
|
||||
|| ( extension.Icmp( "ase" ) == 0 ) || ( extension.Icmp( "lwo" ) == 0 )
|
||||
|| ( extension.Icmp( "flt" ) == 0 ) || ( extension.Icmp( "ma" ) == 0 ) )
|
||||
{
|
||||
model = new( TAG_MODEL ) idRenderModelStatic;
|
||||
}
|
||||
#if !defined( DMAP )
|
||||
else if( extension.Icmp( MD5_MESH_EXT ) == 0 )
|
||||
{
|
||||
model = new( TAG_MODEL ) idRenderModelMD5;
|
||||
|
@ -422,6 +430,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
{
|
||||
model = new( TAG_MODEL ) idRenderModelLiquid;
|
||||
}
|
||||
#endif
|
||||
|
||||
idStrStatic< MAX_OSPATH > generatedFileName;
|
||||
|
||||
|
@ -477,7 +486,6 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
// Not one of the known formats
|
||||
if( model == NULL )
|
||||
{
|
||||
|
||||
if( extension.Length() )
|
||||
{
|
||||
common->Warning( "unknown model type '%s'", canonical.c_str() );
|
||||
|
@ -515,6 +523,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
}
|
||||
|
||||
// RB begin
|
||||
#if !defined( DMAP )
|
||||
if( postLoadExportModels.GetBool() && ( model != defaultModel && model != beamModel && model != spriteModel ) )
|
||||
{
|
||||
idStrStatic< MAX_OSPATH > exportedFileName;
|
||||
|
@ -545,6 +554,7 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
model->ExportOBJ( objFile, mtlFile );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// RB end
|
||||
|
||||
AddModel( model );
|
||||
|
@ -661,6 +671,7 @@ idRenderModelManagerLocal::ReloadModels
|
|||
*/
|
||||
void idRenderModelManagerLocal::ReloadModels( bool forceAll )
|
||||
{
|
||||
#if !defined( DMAP )
|
||||
if( forceAll )
|
||||
{
|
||||
common->Printf( "Reloading all model files...\n" );
|
||||
|
@ -719,12 +730,12 @@ void idRenderModelManagerLocal::ReloadModels( bool forceAll )
|
|||
{
|
||||
model->LoadModel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// we must force the world to regenerate, because models may
|
||||
// have changed size, making their references invalid
|
||||
R_ReCreateWorldReferences();
|
||||
#endif
|
||||
}
|
||||
|
||||
void idRenderModelManagerLocal::CreateMeshBuffers( nvrhi::ICommandList* commandList )
|
||||
|
@ -775,7 +786,9 @@ void idRenderModelManagerLocal::BeginLevelLoad()
|
|||
model->SetLevelLoadReferenced( false );
|
||||
}
|
||||
|
||||
#if !defined( DMAP )
|
||||
vertexCache.FreeStaticData();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -908,6 +921,7 @@ void idRenderModelManagerLocal::EndLevelLoad()
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined( DMAP )
|
||||
commandList->open();
|
||||
|
||||
for( int i = 0; i < models.Num(); i++ )
|
||||
|
@ -931,6 +945,7 @@ void idRenderModelManagerLocal::EndLevelLoad()
|
|||
|
||||
commandList->close();
|
||||
deviceManager->GetDevice()->executeCommandList( commandList );
|
||||
#endif
|
||||
|
||||
// _D3XP added this
|
||||
int end = Sys_Milliseconds();
|
||||
|
|
|
@ -1,623 +0,0 @@
|
|||
/** Helper structures for the Collada loader */
|
||||
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2012, assimp team
|
||||
Copyright (C) 2012 Robert Beckebans (id Tech 4 integration)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef __MODEL_COLLADAHELPER_H__
|
||||
#define __MODEL_COLLADAHELPER_H__
|
||||
|
||||
namespace Collada
|
||||
{
|
||||
|
||||
/** Collada file versions which evolved during the years ... */
|
||||
enum FormatVersion
|
||||
{
|
||||
FV_1_5_n,
|
||||
FV_1_4_n,
|
||||
FV_1_3_n
|
||||
};
|
||||
|
||||
|
||||
/** Transformation types that can be applied to a node */
|
||||
enum TransformType
|
||||
{
|
||||
TF_LOOKAT,
|
||||
TF_ROTATE,
|
||||
TF_TRANSLATE,
|
||||
TF_SCALE,
|
||||
TF_SKEW,
|
||||
TF_MATRIX
|
||||
};
|
||||
|
||||
/** Different types of input data to a vertex or face */
|
||||
enum InputType
|
||||
{
|
||||
IT_Invalid,
|
||||
IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
|
||||
IT_Position,
|
||||
IT_Normal,
|
||||
IT_Texcoord,
|
||||
IT_Color,
|
||||
IT_Tangent,
|
||||
IT_Bitangent
|
||||
};
|
||||
|
||||
/** Contains all data for one of the different transformation types */
|
||||
struct Transform
|
||||
{
|
||||
idStr mID; ///< SID of the transform step, by which anim channels address their target node
|
||||
TransformType mType;
|
||||
float f[16]; ///< Interpretation of data depends on the type of the transformation
|
||||
};
|
||||
|
||||
/** A collada camera. */
|
||||
struct Camera
|
||||
{
|
||||
Camera()
|
||||
: mOrtho( false )
|
||||
, mHorFov( 10e10f )
|
||||
, mVerFov( 10e10f )
|
||||
, mAspect( 10e10f )
|
||||
, mZNear( 0.1f )
|
||||
, mZFar( 1000.f )
|
||||
{}
|
||||
|
||||
// Name of camera
|
||||
idStr mName;
|
||||
|
||||
// True if it is an orthografic camera
|
||||
bool mOrtho;
|
||||
|
||||
//! Horizontal field of view in degrees
|
||||
float mHorFov;
|
||||
|
||||
//! Vertical field of view in degrees
|
||||
float mVerFov;
|
||||
|
||||
//! Screen aspect
|
||||
float mAspect;
|
||||
|
||||
//! Near& far z
|
||||
float mZNear, mZFar;
|
||||
};
|
||||
|
||||
#define aiLightSource_AMBIENT 0xdeaddead
|
||||
|
||||
/** A collada light source. */
|
||||
struct Light
|
||||
{
|
||||
Light()
|
||||
: mAttConstant( 1.f )
|
||||
, mAttLinear( 0.f )
|
||||
, mAttQuadratic( 0.f )
|
||||
, mFalloffAngle( 180.f )
|
||||
, mFalloffExponent( 0.f )
|
||||
, mPenumbraAngle( 10e10f )
|
||||
, mOuterAngle( 10e10f )
|
||||
, mIntensity( 1.f )
|
||||
{}
|
||||
|
||||
//! Type of the light source aiLightSourceType + ambient
|
||||
unsigned int mType;
|
||||
|
||||
//! Color of the light
|
||||
idVec3 mColor;
|
||||
|
||||
//! Light attenuation
|
||||
float mAttConstant, mAttLinear, mAttQuadratic;
|
||||
|
||||
//! Spot light falloff
|
||||
float mFalloffAngle;
|
||||
float mFalloffExponent;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// FCOLLADA extension from here
|
||||
|
||||
//! ... related stuff from maja and max extensions
|
||||
float mPenumbraAngle;
|
||||
float mOuterAngle;
|
||||
|
||||
//! Common light intensity
|
||||
float mIntensity;
|
||||
};
|
||||
|
||||
/** Short vertex index description */
|
||||
struct InputSemanticMapEntry
|
||||
{
|
||||
InputSemanticMapEntry()
|
||||
: mSet( 0 )
|
||||
{}
|
||||
|
||||
//! Index of set, optional
|
||||
unsigned int mSet;
|
||||
|
||||
//! Name of referenced vertex input
|
||||
InputType mType;
|
||||
};
|
||||
|
||||
/** Table to map from effect to vertex input semantics */
|
||||
struct SemanticMappingTable
|
||||
{
|
||||
//! Name of material
|
||||
idStr mMatName;
|
||||
|
||||
//! List of semantic map commands, grouped by effect semantic name
|
||||
idHashTable<InputSemanticMapEntry> mMap;
|
||||
|
||||
//! For std::find
|
||||
bool operator == ( const idStr& s ) const
|
||||
{
|
||||
return s == mMatName;
|
||||
}
|
||||
};
|
||||
|
||||
/** A reference to a mesh inside a node, including materials assigned to the various subgroups.
|
||||
* The ID refers to either a mesh or a controller which specifies the mesh
|
||||
*/
|
||||
struct MeshInstance
|
||||
{
|
||||
///< ID of the mesh or controller to be instanced
|
||||
idStr mMeshOrController;
|
||||
|
||||
///< Map of materials by the subgroup ID they're applied to
|
||||
//idHashTable<SemanticMappingTable> mMaterials;
|
||||
idStrList mMaterials;
|
||||
};
|
||||
|
||||
/** A reference to a camera inside a node*/
|
||||
struct CameraInstance
|
||||
{
|
||||
///< ID of the camera
|
||||
idStr mCamera;
|
||||
};
|
||||
|
||||
/** A reference to a light inside a node*/
|
||||
struct LightInstance
|
||||
{
|
||||
///< ID of the camera
|
||||
idStr mLight;
|
||||
};
|
||||
|
||||
/** A reference to a node inside a node*/
|
||||
struct NodeInstance
|
||||
{
|
||||
///< ID of the node
|
||||
idStr mNode;
|
||||
};
|
||||
|
||||
/** A node in a scene hierarchy */
|
||||
struct Node
|
||||
{
|
||||
idStr mName;
|
||||
idStr mID;
|
||||
idStr mSID;
|
||||
Node* mParent;
|
||||
idList<Node*> mChildren;
|
||||
|
||||
/** Operations in order to calculate the resulting transformation to parent. */
|
||||
idList<Transform> mTransforms;
|
||||
|
||||
/** Meshes at this node */
|
||||
idList<MeshInstance> mMeshes;
|
||||
|
||||
/** Lights at this node */
|
||||
idList<LightInstance> mLights;
|
||||
|
||||
/** Cameras at this node */
|
||||
idList<CameraInstance> mCameras;
|
||||
|
||||
/** Node instances at this node */
|
||||
idList<NodeInstance> mNodeInstances;
|
||||
|
||||
/** Rootnodes: Name of primary camera, if any */
|
||||
idStr mPrimaryCamera;
|
||||
|
||||
//! Constructor. Begin with a zero parent
|
||||
Node()
|
||||
{
|
||||
mParent = NULL;
|
||||
}
|
||||
|
||||
//! Destructor: delete all children subsequently
|
||||
~Node()
|
||||
{
|
||||
//mChildren.DeleteContents( false );
|
||||
}
|
||||
};
|
||||
|
||||
/** Data source array: either floats or strings */
|
||||
struct Data
|
||||
{
|
||||
bool mIsStringArray;
|
||||
idList<float> mValues;
|
||||
idList<idStr> mStrings;
|
||||
};
|
||||
|
||||
/** Accessor to a data array */
|
||||
struct Accessor
|
||||
{
|
||||
size_t mCount; // in number of objects
|
||||
size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
|
||||
size_t mOffset; // in number of values
|
||||
size_t mStride; // Stride in number of values
|
||||
idList<idStr> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
|
||||
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
|
||||
// For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
|
||||
idStr mSource; // URL of the source array
|
||||
mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
|
||||
|
||||
Accessor()
|
||||
{
|
||||
mCount = 0;
|
||||
mSize = 0;
|
||||
mOffset = 0;
|
||||
mStride = 0;
|
||||
mData = NULL;
|
||||
mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/** A single face in a mesh */
|
||||
struct Face
|
||||
{
|
||||
idList<size_t> mIndices;
|
||||
};
|
||||
|
||||
/** An input channel for mesh data, referring to a single accessor */
|
||||
struct InputChannel
|
||||
{
|
||||
InputType mType; // Type of the data
|
||||
size_t mIndex; // Optional index, if multiple sets of the same data type are given
|
||||
size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
|
||||
idStr mAccessor; // ID of the accessor where to read the actual values from.
|
||||
mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
|
||||
|
||||
InputChannel()
|
||||
{
|
||||
mType = IT_Invalid;
|
||||
mIndex = 0;
|
||||
mOffset = 0;
|
||||
mResolved = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/** Subset of a mesh with a certain material */
|
||||
struct SubMesh
|
||||
{
|
||||
idStr mMaterial; ///< subgroup identifier
|
||||
size_t mNumFaces; ///< number of faces in this submesh
|
||||
};
|
||||
|
||||
/** Contains data for a single mesh */
|
||||
struct Mesh
|
||||
{
|
||||
Mesh()
|
||||
{
|
||||
//for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
// mNumUVComponents[i] = 2;
|
||||
}
|
||||
|
||||
// just to check if there's some sophisticated addressing involved...
|
||||
// which we don't support, and therefore should warn about.
|
||||
idStr mVertexID;
|
||||
|
||||
// Vertex data addressed by vertex indices
|
||||
idList<InputChannel> mPerVertexData;
|
||||
|
||||
// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
|
||||
idList<idVec3> mPositions;
|
||||
idList<idVec3> mNormals;
|
||||
idList<idVec3> mTangents;
|
||||
idList<idVec3> mBitangents;
|
||||
idList<idVec2> mTexCoords;
|
||||
idList<dword> mColors;
|
||||
|
||||
//unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
|
||||
// Faces. Stored are only the number of vertices for each face.
|
||||
// 1 == point, 2 == line, 3 == triangle, 4+ == poly
|
||||
idList<int> mFaceSize;
|
||||
|
||||
// Position indices for all faces in the sequence given in mFaceSize -
|
||||
// necessary for bone weight assignment
|
||||
idList<int> mFacePosIndices;
|
||||
|
||||
// Submeshes in this mesh, each with a given material
|
||||
idList<SubMesh> mSubMeshes;
|
||||
};
|
||||
|
||||
/** Which type of primitives the ReadPrimitives() function is going to read */
|
||||
enum PrimitiveType
|
||||
{
|
||||
Prim_Invalid,
|
||||
Prim_Lines,
|
||||
Prim_LineStrip,
|
||||
Prim_Triangles,
|
||||
Prim_TriStrips,
|
||||
Prim_TriFans,
|
||||
Prim_Polylist,
|
||||
Prim_Polygon
|
||||
};
|
||||
|
||||
struct WeightPair
|
||||
{
|
||||
size_t jointIndex;
|
||||
size_t weightIndex;
|
||||
};
|
||||
|
||||
/** A skeleton controller to deform a mesh with the use of joints */
|
||||
struct Controller
|
||||
{
|
||||
// the URL of the mesh deformed by the controller.
|
||||
idStr mMeshId;
|
||||
|
||||
// accessor URL of the joint names
|
||||
idStr mJointNameSource;
|
||||
|
||||
///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases
|
||||
float mBindShapeMatrix[16];
|
||||
|
||||
// accessor URL of the joint inverse bind matrices
|
||||
idStr mJointOffsetMatrixSource;
|
||||
|
||||
// input channel: joint names.
|
||||
InputChannel mWeightInputJoints;
|
||||
// input channel: joint weights
|
||||
InputChannel mWeightInputWeights;
|
||||
|
||||
// Number of weights per vertex.
|
||||
idList<size_t> mWeightCounts;
|
||||
|
||||
// JointIndex-WeightIndex pairs for all vertices
|
||||
idList< WeightPair > mWeights;
|
||||
};
|
||||
|
||||
/** A collada material. Pretty much the only member is a reference to an effect. */
|
||||
struct Material
|
||||
{
|
||||
idStr mEffect;
|
||||
};
|
||||
|
||||
/** Type of the effect param */
|
||||
enum ParamType
|
||||
{
|
||||
Param_Sampler,
|
||||
Param_Surface
|
||||
};
|
||||
|
||||
/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
|
||||
struct EffectParam
|
||||
{
|
||||
ParamType mType;
|
||||
idStr mReference; // to which other thing the param is referring to.
|
||||
};
|
||||
|
||||
/** Shading type supported by the standard effect spec of Collada */
|
||||
enum ShadeType
|
||||
{
|
||||
Shade_Invalid,
|
||||
Shade_Constant,
|
||||
Shade_Lambert,
|
||||
Shade_Phong,
|
||||
Shade_Blinn
|
||||
};
|
||||
|
||||
/** Represents a texture sampler in collada */
|
||||
struct Sampler
|
||||
{
|
||||
Sampler()
|
||||
: mWrapU( true )
|
||||
, mWrapV( true )
|
||||
, mMirrorU()
|
||||
, mMirrorV()
|
||||
//, mOp( aiTextureOp_Multiply )
|
||||
//, mUVId( UINT_MAX )
|
||||
, mWeighting( 1.f )
|
||||
, mMixWithPrevious( 1.f )
|
||||
{}
|
||||
|
||||
/** Name of image reference
|
||||
*/
|
||||
idStr mName;
|
||||
|
||||
/** Wrap U?
|
||||
*/
|
||||
bool mWrapU;
|
||||
|
||||
/** Wrap V?
|
||||
*/
|
||||
bool mWrapV;
|
||||
|
||||
/** Mirror U?
|
||||
*/
|
||||
bool mMirrorU;
|
||||
|
||||
/** Mirror V?
|
||||
*/
|
||||
bool mMirrorV;
|
||||
|
||||
/** Blend mode
|
||||
*/
|
||||
//aiTextureOp mOp;
|
||||
|
||||
/** UV transformation
|
||||
*/
|
||||
//aiUVTransform mTransform;
|
||||
|
||||
/** Name of source UV channel
|
||||
*/
|
||||
//idStr mUVChannel;
|
||||
|
||||
/** Resolved UV channel index or UINT_MAX if not known
|
||||
*/
|
||||
unsigned int mUVId;
|
||||
|
||||
// OKINO/MAX3D extensions from here
|
||||
// -------------------------------------------------------
|
||||
|
||||
/** Weighting factor
|
||||
*/
|
||||
float mWeighting;
|
||||
|
||||
/** Mixing factor from OKINO
|
||||
*/
|
||||
float mMixWithPrevious;
|
||||
};
|
||||
|
||||
/** A collada effect. Can contain about anything according to the Collada spec,
|
||||
but we limit our version to a reasonable subset. */
|
||||
struct Effect
|
||||
{
|
||||
// Shading mode
|
||||
ShadeType mShadeType;
|
||||
|
||||
// Colors
|
||||
idVec4 mEmissive, mAmbient, mDiffuse, mSpecular,
|
||||
mTransparent, mReflective;
|
||||
|
||||
// Textures
|
||||
Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
|
||||
mTexTransparent, mTexBump, mTexReflective;
|
||||
|
||||
// Scalar factory
|
||||
float mShininess, mRefractIndex, mReflectivity;
|
||||
float mTransparency;
|
||||
|
||||
// local params referring to each other by their SID
|
||||
typedef idHashTable<Collada::EffectParam> ParamLibrary;
|
||||
ParamLibrary mParams;
|
||||
|
||||
// MAX3D extensions
|
||||
// ---------------------------------------------------------
|
||||
// Double-sided?
|
||||
bool mDoubleSided, mWireframe, mFaceted;
|
||||
|
||||
Effect()
|
||||
: mShadeType( Shade_Phong )
|
||||
, mEmissive( 0, 0, 0, 1 )
|
||||
, mAmbient( 0.1f, 0.1f, 0.1f, 1 )
|
||||
, mDiffuse( 0.6f, 0.6f, 0.6f, 1 )
|
||||
, mSpecular( 0.4f, 0.4f, 0.4f, 1 )
|
||||
, mTransparent( 0, 0, 0, 1 )
|
||||
, mShininess( 10.0f )
|
||||
, mRefractIndex( 1.f )
|
||||
, mReflectivity( 1.f )
|
||||
, mTransparency( 0.f )
|
||||
, mDoubleSided( false )
|
||||
, mWireframe( false )
|
||||
, mFaceted( false )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/** An image, meaning texture */
|
||||
struct Image
|
||||
{
|
||||
idStr mFileName;
|
||||
|
||||
/** If image file name is zero, embedded image data
|
||||
*/
|
||||
idList<uint8_t> mImageData;
|
||||
|
||||
/** If image file name is zero, file format of
|
||||
* embedded image data.
|
||||
*/
|
||||
idStr mEmbeddedFormat;
|
||||
|
||||
};
|
||||
|
||||
/** An animation channel. */
|
||||
struct AnimationChannel
|
||||
{
|
||||
/** URL of the data to animate. Could be about anything, but we support only the
|
||||
* "NodeID/TransformID.SubElement" notation
|
||||
*/
|
||||
idStr mTarget;
|
||||
|
||||
/** Source URL of the time values. Collada calls them "input". Meh. */
|
||||
idStr mSourceTimes;
|
||||
/** Source URL of the value values. Collada calls them "output". */
|
||||
idStr mSourceValues;
|
||||
};
|
||||
|
||||
/** An animation. Container for 0-x animation channels or 0-x animations */
|
||||
struct Animation
|
||||
{
|
||||
/** Anim name */
|
||||
idStr mName;
|
||||
|
||||
/** the animation channels, if any */
|
||||
idList<AnimationChannel> mChannels;
|
||||
|
||||
/** the sub-animations, if any */
|
||||
idList<Animation*> mSubAnims;
|
||||
|
||||
/** Destructor */
|
||||
~Animation()
|
||||
{
|
||||
mSubAnims.DeleteContents( false );
|
||||
}
|
||||
};
|
||||
|
||||
/** Description of a collada animation channel which has been determined to affect the current node */
|
||||
struct ChannelEntry
|
||||
{
|
||||
const Collada::AnimationChannel* mChannel; ///> the source channel
|
||||
idStr mTransformId; // the ID of the transformation step of the node which is influenced
|
||||
size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
|
||||
size_t mSubElement; // starting index inside the transform data
|
||||
|
||||
// resolved data references
|
||||
const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values
|
||||
const Collada::Data* mTimeData; ///> Source data array for the time values
|
||||
const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values
|
||||
const Collada::Data* mValueData; ///> Source datat array for the key value values
|
||||
|
||||
ChannelEntry()
|
||||
{
|
||||
mChannel = NULL;
|
||||
mSubElement = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // end of namespace Collada
|
||||
|
||||
#endif // __MODEL_COLLADAHELPER_H__
|
File diff suppressed because it is too large
Load diff
|
@ -1,357 +0,0 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2012, assimp team
|
||||
Copyright (C) 2012 Robert Beckebans (id Tech 4 integration)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file ColladaParser.h
|
||||
* @brief Defines the parser helper class for the collada loader
|
||||
*/
|
||||
|
||||
#ifndef __MODEL_COLLADAPARSER_H__
|
||||
#define __MODEL_COLLADAPARSER_H__
|
||||
|
||||
#include "../libs/irrxml/src/irrXML.h"
|
||||
#include "Model_ColladaHelper.h"
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
/** Parser helper class for the Collada loader.
|
||||
*
|
||||
* Does all the XML reading and builds internal data structures from it,
|
||||
* but leaves the resolving of all the references to the loader.
|
||||
*/
|
||||
class ColladaParser
|
||||
{
|
||||
friend class ColladaLoader;
|
||||
friend class idRenderModelStatic;
|
||||
|
||||
protected:
|
||||
/** Constructor from XML file */
|
||||
ColladaParser( const char* pFile, ID_TIME_T* sourceTimeStamp );
|
||||
|
||||
/** Destructor */
|
||||
~ColladaParser();
|
||||
|
||||
/** Reads the contents of the file */
|
||||
void ReadContents();
|
||||
|
||||
/** Reads the structure of the file */
|
||||
void ReadStructure();
|
||||
|
||||
/** Reads asset informations such as coordinate system informations and legal blah */
|
||||
void ReadAssetInfo();
|
||||
|
||||
/** Reads the animation library */
|
||||
// void ReadAnimationLibrary();
|
||||
|
||||
/** Reads an animation into the given parent structure */
|
||||
// void ReadAnimation( Collada::Animation* pParent );
|
||||
|
||||
/** Reads an animation sampler into the given anim channel */
|
||||
// void ReadAnimationSampler( Collada::AnimationChannel& pChannel );
|
||||
|
||||
/** Reads the skeleton controller library */
|
||||
// void ReadControllerLibrary();
|
||||
|
||||
/** Reads a controller into the given mesh structure */
|
||||
// void ReadController( Collada::Controller& pController );
|
||||
|
||||
/** Reads the joint definitions for the given controller */
|
||||
// void ReadControllerJoints( Collada::Controller& pController );
|
||||
|
||||
/** Reads the joint weights for the given controller */
|
||||
// void ReadControllerWeights( Collada::Controller& pController );
|
||||
|
||||
/** Reads the image library contents */
|
||||
// void ReadImageLibrary();
|
||||
|
||||
/** Reads an image entry into the given image */
|
||||
// void ReadImage( Collada::Image& pImage );
|
||||
|
||||
/** Reads the material library */
|
||||
void ReadMaterialLibrary();
|
||||
|
||||
/** Reads a material entry into the given material */
|
||||
void ReadMaterial( Collada::Material& pMaterial );
|
||||
|
||||
/** Reads the camera library */
|
||||
// void ReadCameraLibrary();
|
||||
|
||||
/** Reads a camera entry into the given camera */
|
||||
// void ReadCamera( Collada::Camera& pCamera );
|
||||
|
||||
/** Reads the light library */
|
||||
// void ReadLightLibrary();
|
||||
|
||||
/** Reads a light entry into the given light */
|
||||
// void ReadLight( Collada::Light& pLight );
|
||||
|
||||
/** Reads the effect library */
|
||||
// void ReadEffectLibrary();
|
||||
|
||||
/** Reads an effect entry into the given effect*/
|
||||
// void ReadEffect( Collada::Effect& pEffect );
|
||||
|
||||
/** Reads an COMMON effect profile */
|
||||
// void ReadEffectProfileCommon( Collada::Effect& pEffect );
|
||||
|
||||
/** Read sampler properties */
|
||||
// void ReadSamplerProperties( Collada::Sampler& pSampler );
|
||||
|
||||
/** Reads an effect entry containing a color or a texture defining that color */
|
||||
// void ReadEffectColor( idVec4& pColor, Collada::Sampler& pSampler );
|
||||
|
||||
/** Reads an effect entry containing a float */
|
||||
// void ReadEffectFloat( float& pFloat );
|
||||
|
||||
/** Reads an effect parameter specification of any kind */
|
||||
// void ReadEffectParam( Collada::EffectParam& pParam );
|
||||
|
||||
/** Reads the geometry library contents */
|
||||
void ReadGeometryLibrary();
|
||||
|
||||
/** Reads a geometry from the geometry library. */
|
||||
void ReadGeometry( Collada::Mesh* pMesh );
|
||||
|
||||
/** Reads a mesh from the geometry library */
|
||||
void ReadMesh( Collada::Mesh* pMesh );
|
||||
|
||||
/** Reads a source element - a combination of raw data and an accessor defining
|
||||
* things that should not be redefinable. Yes, that's another rant.
|
||||
*/
|
||||
void ReadSource();
|
||||
|
||||
/** Reads a data array holding a number of elements, and stores it in the global library.
|
||||
* Currently supported are array of floats and arrays of strings.
|
||||
*/
|
||||
void ReadDataArray();
|
||||
|
||||
/** Reads an accessor and stores it in the global library under the given ID -
|
||||
* accessors use the ID of the parent <source> element
|
||||
*/
|
||||
void ReadAccessor( const idStr& pID );
|
||||
|
||||
/** Reads input declarations of per-vertex mesh data into the given mesh */
|
||||
void ReadVertexData( Collada::Mesh* pMesh );
|
||||
|
||||
/** Reads input declarations of per-index mesh data into the given mesh */
|
||||
void ReadIndexData( Collada::Mesh* pMesh );
|
||||
|
||||
/** Reads a single input channel element and stores it in the given array, if valid */
|
||||
void ReadInputChannel( idList<Collada::InputChannel>& poChannels );
|
||||
|
||||
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
|
||||
void ReadPrimitives( Collada::Mesh* pMesh, idList<Collada::InputChannel>& pPerIndexChannels,
|
||||
size_t pNumPrimitives, const idList<size_t>& pVCount, Collada::PrimitiveType pPrimType );
|
||||
|
||||
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
|
||||
void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh );
|
||||
|
||||
/** Reads the library of node hierarchies and scene parts */
|
||||
void ReadSceneLibrary();
|
||||
|
||||
/** Reads a scene node's contents including children and stores it in the given node */
|
||||
void ReadSceneNode( Collada::Node* pNode );
|
||||
|
||||
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
|
||||
void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType );
|
||||
|
||||
/** Reads a mesh reference in a node and adds it to the node's mesh list */
|
||||
void ReadNodeGeometry( Collada::Node* pNode );
|
||||
|
||||
/** Reads the collada scene */
|
||||
void ReadScene();
|
||||
|
||||
// Processes bind_vertex_input and bind elements
|
||||
void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl );
|
||||
|
||||
protected:
|
||||
/** Aborts the file reading with an exception */
|
||||
void ThrowException( const idStr& pError ) const;
|
||||
|
||||
/** Skips all data until the end node of the current element */
|
||||
void SkipElement();
|
||||
|
||||
/** Skips all data until the end node of the given element */
|
||||
void SkipElement( const char* pElement );
|
||||
|
||||
bool SkipSpacesAndLineEnd( const char* in, const char** out );
|
||||
|
||||
/** Compares the current xml element name to the given string and returns true if equal */
|
||||
bool IsElement( const char* pName ) const;
|
||||
|
||||
/** Tests for the opening tag of the given element, throws an exception if not found */
|
||||
void TestOpening( const char* pName );
|
||||
|
||||
/** Tests for the closing tag of the given element, throws an exception if not found */
|
||||
void TestClosing( const char* pName );
|
||||
|
||||
/** Checks the present element for the presence of the attribute, returns its index
|
||||
or throws an exception if not found */
|
||||
int GetAttribute( const char* pAttr ) const;
|
||||
|
||||
/** Returns the index of the named attribute or -1 if not found. Does not throw,
|
||||
therefore useful for optional attributes */
|
||||
int TestAttribute( const char* pAttr ) const;
|
||||
|
||||
/** Reads the text contents of an element, throws an exception if not given.
|
||||
Skips leading whitespace. */
|
||||
const char* GetTextContent();
|
||||
|
||||
/** Reads the text contents of an element, returns NULL if not given.
|
||||
Skips leading whitespace. */
|
||||
const char* TestTextContent();
|
||||
|
||||
/** Reads a single bool from current text content */
|
||||
bool ReadBoolFromTextContent();
|
||||
|
||||
/** Reads a single float from current text content */
|
||||
float ReadFloatFromTextContent();
|
||||
|
||||
/** Calculates the resulting transformation from all the given transform steps */
|
||||
idMat4 CalculateResultTransform( const idList<Collada::Transform>& pTransforms ) const;
|
||||
|
||||
/** Determines the input data type for the given semantic string */
|
||||
Collada::InputType GetTypeForSemantic( const idStr& pSemantic );
|
||||
|
||||
/** Finds the item in the given library by its reference, throws if not found */
|
||||
template <typename Type> const Type* ResolveLibraryReference(
|
||||
const idHashTable<Type>& pLibrary, const idStr& pURL ) const;
|
||||
|
||||
protected:
|
||||
/** Filename, for a verbose error message */
|
||||
idStr mFileName;
|
||||
|
||||
/** XML reader, member for everyday use */
|
||||
irr::io::IrrXMLReader* mReader;
|
||||
|
||||
/** All data arrays found in the file by ID. Might be referred to by actually
|
||||
everyone. Collada, you are a steaming pile of indirection. */
|
||||
typedef idHashTable<Collada::Data*> DataLibrary;
|
||||
DataLibrary mDataLibrary;
|
||||
|
||||
/** Same for accessors which define how the data in a data array is accessed. */
|
||||
typedef idHashTable<Collada::Accessor*> AccessorLibrary;
|
||||
AccessorLibrary mAccessorLibrary;
|
||||
|
||||
/** Mesh library: mesh by ID */
|
||||
typedef idHashTable<Collada::Mesh*> MeshLibrary;
|
||||
MeshLibrary mMeshLibrary;
|
||||
|
||||
/** node library: root node of the hierarchy part by ID */
|
||||
typedef idHashTable<Collada::Node*> NodeLibrary;
|
||||
NodeLibrary mNodeLibrary;
|
||||
|
||||
/** Image library: stores texture properties by ID */
|
||||
typedef idHashTable<Collada::Image*> ImageLibrary;
|
||||
ImageLibrary mImageLibrary;
|
||||
|
||||
/** Effect library: surface attributes by ID */
|
||||
typedef idHashTable<Collada::Effect*> EffectLibrary;
|
||||
EffectLibrary mEffectLibrary;
|
||||
|
||||
/** Material library: surface material by ID */
|
||||
typedef idHashTable<Collada::Material*> MaterialLibrary;
|
||||
MaterialLibrary mMaterialLibrary;
|
||||
|
||||
/** Light library: surface light by ID */
|
||||
typedef idHashTable<Collada::Light*> LightLibrary;
|
||||
LightLibrary mLightLibrary;
|
||||
|
||||
/** Camera library: surface material by ID */
|
||||
typedef idHashTable<Collada::Camera*> CameraLibrary;
|
||||
CameraLibrary mCameraLibrary;
|
||||
|
||||
/** Controller library: joint controllers by ID */
|
||||
typedef idHashTable<Collada::Controller*> ControllerLibrary;
|
||||
ControllerLibrary mControllerLibrary;
|
||||
|
||||
/** Pointer to the root node. Don't delete, it just points to one of
|
||||
the nodes in the node library. */
|
||||
Collada::Node* mRootNode;
|
||||
|
||||
/** Root animation container */
|
||||
Collada::Animation mAnims;
|
||||
|
||||
/** Size unit: how large compared to a meter */
|
||||
float mUnitSize;
|
||||
|
||||
/** Which is the up vector */
|
||||
enum { UP_X, UP_Y, UP_Z } mUpDirection;
|
||||
|
||||
/** Collada file format version */
|
||||
Collada::FormatVersion mFormat;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Check for element match
|
||||
inline bool ColladaParser::IsElement( const char* pName ) const
|
||||
{
|
||||
assert( mReader->getNodeType() == irr::io::EXN_ELEMENT );
|
||||
return idStr::Cmp( mReader->getNodeName(), pName ) == 0;
|
||||
}
|
||||
|
||||
inline bool ColladaParser::SkipSpacesAndLineEnd( const char* in, const char** out )
|
||||
{
|
||||
while( *in == ' ' || *in == '\t' || *in == '\r' || *in == '\n' )
|
||||
{
|
||||
in++;
|
||||
}
|
||||
*out = in;
|
||||
return *in != '\0';
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Finds the item in the given library by its reference, throws if not found
|
||||
template <typename Type>
|
||||
const Type* ColladaParser::ResolveLibraryReference( const idHashTable<Type>& pLibrary, const idStr& pURL ) const
|
||||
{
|
||||
Type* element = NULL;
|
||||
|
||||
if( !pLibrary.Get( pURL, &element ) )
|
||||
{
|
||||
ThrowException( va( "Unable to resolve library reference \"%s\".", pURL.c_str() ) );
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
#endif // __MODEL_COLLADAPARSER_H__
|
|
@ -36,8 +36,12 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "RenderCommon.h"
|
||||
|
||||
// HVG_TODO: this has to be moved out before release
|
||||
#include "d3xp/anim/Anim.h"
|
||||
#include "d3xp/Game_local.h"
|
||||
#if !defined( DMAP )
|
||||
#include "d3xp/anim/Anim.h"
|
||||
#include "d3xp/Game_local.h"
|
||||
#endif
|
||||
|
||||
idCVar r_useCachedDynamicModels( "r_useCachedDynamicModels", "1", CVAR_RENDERER | CVAR_BOOL, "cache snapshots of dynamic models" );
|
||||
|
||||
idCVar gltf_ForceBspMeshTexture( "gltf_ForceBspMeshTexture", "0", CVAR_SYSTEM | CVAR_BOOL, "all world geometry has the same forced texture" );
|
||||
idCVar gltf_ModelSceneName( "gltf_ModelSceneName", "Scene", CVAR_SYSTEM , "Scene to use when loading specific models" );
|
||||
|
@ -875,6 +879,7 @@ void idRenderModelGLTF::UpdateMd5Joints()
|
|||
|
||||
void idRenderModelGLTF::DrawJoints( const struct renderEntity_s* ent, const viewDef_t* view )
|
||||
{
|
||||
#if !defined( DMAP )
|
||||
int i;
|
||||
int num;
|
||||
idVec3 pos;
|
||||
|
@ -918,78 +923,7 @@ void idRenderModelGLTF::DrawJoints( const struct renderEntity_s* ent, const view
|
|||
common->RW()->DrawText( md5joints[i].name, pos + offset, scale, colorWhite, view->renderView.viewaxis, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool GatherBoneInfo( gltfData* data, gltfAnimation* gltfAnim, idList<int, TAG_MODEL>& bones, idList<jointAnimInfo_t, TAG_MD5_ANIM>& jointInfo , gltfSkin* skin, const idImportOptions* options )
|
||||
{
|
||||
bool boneLess = false;
|
||||
int targetNode = lastMeshFromFile->GetRootID();
|
||||
|
||||
auto targets = data->GetAnimTargets( gltfAnim );
|
||||
auto& nodeList = data->NodeList();
|
||||
if( skin == nullptr )
|
||||
{
|
||||
boneLess = true;
|
||||
}
|
||||
|
||||
// we cant be sure channels are sorted by bone?
|
||||
if( !boneLess )
|
||||
{
|
||||
if( skin == nullptr )
|
||||
{
|
||||
skin = data->GetSkin( targetNode );
|
||||
}
|
||||
assert( skin );
|
||||
|
||||
// armature node is origin/root bone
|
||||
//bones.Append( skin->skeleton );
|
||||
|
||||
// skeleton bones
|
||||
bones.Append( skin->joints );
|
||||
}
|
||||
else
|
||||
{
|
||||
bones.Append( targetNode );
|
||||
}
|
||||
|
||||
if( options )
|
||||
{
|
||||
if( options->keepjoints.Num() )
|
||||
{
|
||||
KeepNodes( data, options->keepjoints, bones );
|
||||
}
|
||||
|
||||
if( options->addOrigin )
|
||||
{
|
||||
gltfNode* armatureNode = data->NodeList()[bones[0]]->parent;
|
||||
AddOriginBone( data, bones, armatureNode );
|
||||
}
|
||||
|
||||
if( options->remapjoints.Num() )
|
||||
{
|
||||
RemapNodes( data, options->remapjoints, bones );
|
||||
}
|
||||
|
||||
if( options->renamejoints.Num() )
|
||||
{
|
||||
RenameNodes( data, options->renamejoints, bones );
|
||||
}
|
||||
}
|
||||
|
||||
// create jointInfo
|
||||
jointInfo.SetGranularity( 1 );
|
||||
jointInfo.SetNum( bones.Num() );
|
||||
int idx = 0;
|
||||
for( auto& joint : jointInfo )
|
||||
{
|
||||
joint.animBits = ~63;
|
||||
joint.firstComponent = -1;
|
||||
|
||||
const char* name = nodeList[bones[idx++]]->name.c_str();
|
||||
joint.nameIndex = animationLib.JointIndex( name );
|
||||
}
|
||||
|
||||
return boneLess;
|
||||
#endif
|
||||
}
|
||||
|
||||
static idList<idJointQuat> GetPose( idList<gltfNode>& bones, idJointMat* poseMat, const idMat4& globalTransform )
|
||||
|
@ -1071,6 +1005,80 @@ static int CopyBones( gltfData* data, const idList<int>& bones, idList<gltfNode>
|
|||
return out.Num();
|
||||
}
|
||||
|
||||
#if !defined( DMAP )
|
||||
|
||||
static bool GatherBoneInfo( gltfData* data, gltfAnimation* gltfAnim, idList<int, TAG_MODEL>& bones, idList<jointAnimInfo_t, TAG_MD5_ANIM>& jointInfo , gltfSkin* skin, const idImportOptions* options )
|
||||
{
|
||||
bool boneLess = false;
|
||||
int targetNode = lastMeshFromFile->GetRootID();
|
||||
|
||||
auto targets = data->GetAnimTargets( gltfAnim );
|
||||
auto& nodeList = data->NodeList();
|
||||
if( skin == nullptr )
|
||||
{
|
||||
boneLess = true;
|
||||
}
|
||||
|
||||
// we cant be sure channels are sorted by bone?
|
||||
if( !boneLess )
|
||||
{
|
||||
if( skin == nullptr )
|
||||
{
|
||||
skin = data->GetSkin( targetNode );
|
||||
}
|
||||
assert( skin );
|
||||
|
||||
// armature node is origin/root bone
|
||||
//bones.Append( skin->skeleton );
|
||||
|
||||
// skeleton bones
|
||||
bones.Append( skin->joints );
|
||||
}
|
||||
else
|
||||
{
|
||||
bones.Append( targetNode );
|
||||
}
|
||||
|
||||
if( options )
|
||||
{
|
||||
if( options->keepjoints.Num() )
|
||||
{
|
||||
KeepNodes( data, options->keepjoints, bones );
|
||||
}
|
||||
|
||||
if( options->addOrigin )
|
||||
{
|
||||
gltfNode* armatureNode = data->NodeList()[bones[0]]->parent;
|
||||
AddOriginBone( data, bones, armatureNode );
|
||||
}
|
||||
|
||||
if( options->remapjoints.Num() )
|
||||
{
|
||||
RemapNodes( data, options->remapjoints, bones );
|
||||
}
|
||||
|
||||
if( options->renamejoints.Num() )
|
||||
{
|
||||
RenameNodes( data, options->renamejoints, bones );
|
||||
}
|
||||
}
|
||||
|
||||
// create jointInfo
|
||||
jointInfo.SetGranularity( 1 );
|
||||
jointInfo.SetNum( bones.Num() );
|
||||
int idx = 0;
|
||||
for( auto& joint : jointInfo )
|
||||
{
|
||||
joint.animBits = ~63;
|
||||
joint.firstComponent = -1;
|
||||
|
||||
const char* name = nodeList[bones[idx++]]->name.c_str();
|
||||
joint.nameIndex = animationLib.JointIndex( name );
|
||||
}
|
||||
|
||||
return boneLess;
|
||||
}
|
||||
|
||||
idFile_Memory* idRenderModelGLTF::GetAnimBin( const idStr& animName, const ID_TIME_T sourceTimeStamp, const idImportOptions* options )
|
||||
{
|
||||
assert( lastMeshFromFile );
|
||||
|
@ -1620,6 +1628,8 @@ idFile_Memory* idRenderModelGLTF::GetAnimBin( const idStr& animName, const ID_TI
|
|||
return file;
|
||||
}
|
||||
|
||||
#endif // #if !defined( DMAP )
|
||||
|
||||
void idRenderModelGLTF::WriteBinaryModel( idFile* file, ID_TIME_T* _timeStamp /*= NULL */ ) const
|
||||
{
|
||||
idRenderModelStatic::WriteBinaryModel( file , _timeStamp );
|
||||
|
@ -1881,6 +1891,7 @@ void idRenderModelGLTF::UpdateSurface( const struct renderEntity_s* ent, const i
|
|||
|
||||
idList<int> jointIds;
|
||||
|
||||
#if !defined( DMAP )
|
||||
if( r_useGPUSkinning.GetBool() )
|
||||
{
|
||||
if( tri->verts != NULL && tri->verts != verts )
|
||||
|
@ -1892,6 +1903,7 @@ void idRenderModelGLTF::UpdateSurface( const struct renderEntity_s* ent, const i
|
|||
tri->referencedVerts = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if( tri->verts == NULL || tri->verts == verts )
|
||||
{
|
||||
|
@ -2058,6 +2070,9 @@ static void TransformJointsFast( idJointMat* __restrict outJoints, const int num
|
|||
|
||||
idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEntity_s* ent, const viewDef_t* view, idRenderModel* cachedModel )
|
||||
{
|
||||
#if defined( DMAP )
|
||||
return NULL;
|
||||
#else
|
||||
if( cachedModel != NULL && !r_useCachedDynamicModels.GetBool() )
|
||||
{
|
||||
delete cachedModel;
|
||||
|
@ -2099,6 +2114,7 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn
|
|||
|
||||
staticModel->bounds.Clear();
|
||||
|
||||
#if !defined( DMAP )
|
||||
if( r_showSkel.GetInteger() )
|
||||
{
|
||||
if( ( view != NULL ) && ( !r_skipSuppress.GetBool() || !ent->suppressSurfaceInViewID || ( ent->suppressSurfaceInViewID != view->renderView.viewID ) ) )
|
||||
|
@ -2114,6 +2130,7 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn
|
|||
return staticModel;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// update the GPU joints array
|
||||
const int numInvertedJoints = SIMD_ROUND_JOINTS( md5joints.Num() );
|
||||
|
@ -2160,6 +2177,7 @@ idRenderModel* idRenderModelGLTF::InstantiateDynamicModel( const struct renderEn
|
|||
}
|
||||
|
||||
return staticModel;
|
||||
#endif
|
||||
}
|
||||
|
||||
int idRenderModelGLTF::NumJoints() const
|
||||
|
|
|
@ -120,10 +120,8 @@ public:
|
|||
bool LoadASE( const char* fileName, ID_TIME_T* sourceTimeStamp );
|
||||
bool LoadLWO( const char* fileName, ID_TIME_T* sourceTimeStamp );
|
||||
bool LoadMA( const char* filename, ID_TIME_T* sourceTimeStamp );
|
||||
bool LoadDAE( const char* fileName, ID_TIME_T* sourceTimeStamp ); // RB
|
||||
bool LoadOBJ( const char* fileName, ID_TIME_T* sourceTimeStamp ); // RB
|
||||
|
||||
bool ConvertDAEToModelSurfaces( const ColladaParser* dae ); // RB
|
||||
bool ConvertOBJToModelSurfaces( const objModel_t* obj ); // RB
|
||||
bool ConvertASEToModelSurfaces( const struct aseModel_s* ase );
|
||||
bool ConvertLWOToModelSurfaces( const struct st_lwObject* lwo );
|
||||
|
@ -168,6 +166,9 @@ protected:
|
|||
static idCVar r_slopNormal; // merge normals that dot less than this
|
||||
};
|
||||
|
||||
|
||||
#if !defined( DMAP )
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
@ -558,4 +559,6 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
#endif // #if !defined( DMAP )
|
||||
|
||||
#endif /* !__MODEL_LOCAL_H__ */
|
||||
|
|
|
@ -99,7 +99,7 @@ idCVar r_checkBounds( "r_checkBounds", "0", CVAR_RENDERER | CVAR_BOOL, "compare
|
|||
|
||||
idCVar r_useNodeCommonChildren( "r_useNodeCommonChildren", "1", CVAR_RENDERER | CVAR_BOOL, "stop pushing reference bounds early when possible" );
|
||||
idCVar r_useShadowSurfaceScissor( "r_useShadowSurfaceScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor shadows by the scissor rect of the interaction surfaces" );
|
||||
idCVar r_useCachedDynamicModels( "r_useCachedDynamicModels", "1", CVAR_RENDERER | CVAR_BOOL, "cache snapshots of dynamic models" );
|
||||
|
||||
idCVar r_maxAnisotropicFiltering( "r_maxAnisotropicFiltering", "8", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "limit aniso filtering" );
|
||||
idCVar r_useTrilinearFiltering( "r_useTrilinearFiltering", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Extra quality filtering" );
|
||||
// RB: not used anymore
|
||||
|
|
|
@ -2604,7 +2604,6 @@ R_RemapShaderBySkin
|
|||
*/
|
||||
const idMaterial* R_RemapShaderBySkin( const idMaterial* shader, const idDeclSkin* skin, const idMaterial* customShader )
|
||||
{
|
||||
|
||||
if( !shader )
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
@ -47,7 +47,14 @@ set(BSPT_RENDERER_INCLUDES
|
|||
../../renderer/Color/ColorSpace.h
|
||||
../../renderer/Image.h
|
||||
../../renderer/Material.h
|
||||
../../renderer/VertexCache.h
|
||||
#../../renderer/VertexCache.h
|
||||
../../renderer/ModelManager.h
|
||||
../../renderer/Model.h
|
||||
../../renderer/Model_gltf.h
|
||||
../../renderer/Model_ase.h
|
||||
../../renderer/Model_lwo.h
|
||||
../../renderer/Model_ma.h
|
||||
../../renderer/Model_obj.h
|
||||
)
|
||||
set(BSPT_RENDERER_SOURCES
|
||||
../../renderer/BinaryImage.cpp
|
||||
|
@ -65,6 +72,14 @@ set(BSPT_RENDERER_SOURCES
|
|||
../../renderer/Material.cpp
|
||||
../../renderer/tr_trisurf.cpp
|
||||
#../../renderer/VertexCache.cpp
|
||||
../../renderer/ModelManager.cpp
|
||||
../../renderer/Model.cpp
|
||||
../../renderer/Model_gltf.cpp
|
||||
#../../renderer/Model_md5.cpp
|
||||
../../renderer/Model_ase.cpp
|
||||
../../renderer/Model_lwo.cpp
|
||||
../../renderer/Model_ma.cpp
|
||||
../../renderer/Model_obj.cpp
|
||||
)
|
||||
|
||||
file(GLOB MIKKTSPACE_INCLUDES ../../libs/mikktspace/*.h)
|
||||
|
|
|
@ -30,7 +30,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "../../../renderer/RenderCommon.h"
|
||||
|
||||
// DMAP TODO
|
||||
#define DMAP_INLINE_MODELS 0
|
||||
#define DMAP_INLINE_MODELS 1
|
||||
|
||||
typedef struct primitive_s
|
||||
{
|
||||
|
|
|
@ -342,5 +342,15 @@ void R_FreeLightDefDerivedData( idRenderLightLocal* ldef )
|
|||
ldef->references = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
R_CheckForEntityDefsUsingModel
|
||||
===================
|
||||
*/
|
||||
void R_CheckForEntityDefsUsingModel( idRenderModel* model )
|
||||
{
|
||||
// STUB
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -675,14 +675,23 @@ void FixGlobalTjunctions( uEntity_t* e )
|
|||
{
|
||||
continue;
|
||||
}
|
||||
const char* modelName = entity->mapEntity->epairs.GetString( "model" );
|
||||
if( !modelName )
|
||||
idStrStatic< MAX_OSPATH > modelName = entity->mapEntity->epairs.GetString( "model" );
|
||||
if( modelName.IsEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// RB: DAE and OBJ support
|
||||
if( !strstr( modelName, ".lwo" ) && !strstr( modelName, ".ase" ) && !strstr( modelName, ".ma" ) && !strstr( modelName, ".dae" ) && !strstr( modelName, ".obj" ) )
|
||||
idStrStatic< MAX_OSPATH > extension;
|
||||
modelName.ExtractFileExtension( extension );
|
||||
|
||||
// RB: glTF2 and OBJ support
|
||||
bool isGLTF = false;
|
||||
if( ( extension.Icmp( GLTF_GLB_EXT ) == 0 ) || ( extension.Icmp( GLTF_EXT ) == 0 ) )
|
||||
{
|
||||
isGLTF = true;
|
||||
}
|
||||
|
||||
if( !isGLTF && !strstr( modelName, ".lwo" ) && !strstr( modelName, ".ase" ) && !strstr( modelName, ".ma" ) && !strstr( modelName, ".obj" ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue