mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-14 22:50:45 +00:00
Merge branch '679-gltf-map-support2' into 679-gltf-map-support-nvrhi
This commit is contained in:
commit
f22d7f511b
18 changed files with 2281 additions and 406 deletions
|
@ -554,6 +554,8 @@ endif (RAPIDJSON_FOUND)
|
|||
|
||||
add_subdirectory(idlib)
|
||||
|
||||
file(GLOB NATVIS_SOURCES .natvis)
|
||||
|
||||
file(GLOB AAS_INCLUDES aas/*.h)
|
||||
file(GLOB AAS_SOURCES aas/*.cpp)
|
||||
|
||||
|
@ -1473,6 +1475,7 @@ set(RBDOOM3_INCLUDES
|
|||
)
|
||||
|
||||
set(RBDOOM3_SOURCES
|
||||
${NATVIS_SOURCES}
|
||||
${AAS_SOURCES}
|
||||
${CM_SOURCES}
|
||||
${FRAMEWORK_SOURCES}
|
||||
|
|
|
@ -633,7 +633,7 @@ bool idCollisionModelManagerLocal::LoadCollisionModelFile( const char* name, uns
|
|||
int id;
|
||||
idStr tmp;
|
||||
idStr file = fileName;
|
||||
gltfManager::ExtractMeshIdentifier( file, id, tmp );
|
||||
gltfManager::ExtractIdentifier( file, id, tmp );
|
||||
|
||||
currentTimeStamp = fileSystem->GetTimestamp( file );
|
||||
}
|
||||
|
|
|
@ -4573,7 +4573,7 @@ cmHandle_t idCollisionModelManagerLocal::LoadModel( const char* modelName, const
|
|||
int id;
|
||||
idStr tmp;
|
||||
idStr file = modelName;
|
||||
gltfManager::ExtractMeshIdentifier( file, id, tmp );
|
||||
gltfManager::ExtractIdentifier( file, id, tmp );
|
||||
|
||||
sourceTimeStamp = fileSystem->GetTimestamp( file );
|
||||
}
|
||||
|
|
|
@ -283,7 +283,15 @@ void idGameEdit::ParseSpawnArgsToRenderEntity( const idDict* args, renderEntity_
|
|||
|
||||
if( renderEntity->hModel )
|
||||
{
|
||||
renderEntity->bounds = renderEntity->hModel->Bounds( renderEntity );
|
||||
// RB: glTF2 models can be static and cached
|
||||
if( renderEntity->hModel->IsDynamicModel() == DM_STATIC )
|
||||
{
|
||||
renderEntity->bounds = renderEntity->hModel->Bounds( NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
renderEntity->bounds = renderEntity->hModel->Bounds( renderEntity );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -31,6 +31,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
|
||||
#include "../Game_local.h"
|
||||
//should go before release?
|
||||
#include "renderer/Model_gltf.h"
|
||||
|
||||
idCVar binaryLoadAnim( "binaryLoadAnim", "1", 0, "enable binary load/write of idMD5Anim" );
|
||||
|
||||
|
@ -177,18 +179,47 @@ idMD5Anim::LoadAnim
|
|||
*/
|
||||
bool idMD5Anim::LoadAnim( const char* filename )
|
||||
{
|
||||
|
||||
idLexer parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS | LEXFL_NOSTRINGCONCAT );
|
||||
idToken token;
|
||||
idStr extension;
|
||||
idStr filenameStr = idStr( filename );
|
||||
filenameStr.ExtractFileExtension( extension );
|
||||
|
||||
idStr generatedFileName = "generated/anim/";
|
||||
generatedFileName.AppendPath( filename );
|
||||
generatedFileName.SetFileExtension( ".bMD5anim" );
|
||||
|
||||
// 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( filename );
|
||||
idStr gltfFileName = idStr( filename );
|
||||
int gltfAnimId = -1;
|
||||
idStr gltfAnimName;
|
||||
|
||||
|
||||
// Get the timestamp on the original file, if it's newer than what is stored in binary model, regenerate it
|
||||
ID_TIME_T sourceTimeStamp;
|
||||
|
||||
bool isGLTF = ( extension.Icmp( GLTF_GLB_EXT ) == 0 ) || ( extension.Icmp( GLTF_EXT ) == 0 ) ;
|
||||
|
||||
if( isGLTF )
|
||||
{
|
||||
gltfManager::ExtractIdentifier( gltfFileName, gltfAnimId, gltfAnimName );
|
||||
|
||||
sourceTimeStamp = fileSystem->GetTimestamp( gltfFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceTimeStamp = fileSystem->GetTimestamp( filename );
|
||||
}
|
||||
|
||||
idFile* fileptr = fileSystem->OpenFileReadMemory( generatedFileName );
|
||||
bool doWrite = false;
|
||||
if( fileptr == nullptr && isGLTF )
|
||||
{
|
||||
fileptr = idRenderModelGLTF::GetAnimBin( filenameStr , sourceTimeStamp );
|
||||
doWrite = fileptr != nullptr;
|
||||
}
|
||||
|
||||
idFileLocal file( fileptr );
|
||||
|
||||
idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) );
|
||||
if( binaryLoadAnim.GetBool() && LoadBinary( file, sourceTimeStamp ) )
|
||||
{
|
||||
name = filename;
|
||||
|
@ -197,6 +228,14 @@ bool idMD5Anim::LoadAnim( const char* filename )
|
|||
// for resource gathering write this anim to the preload file for this map
|
||||
fileSystem->AddAnimPreload( name );
|
||||
}
|
||||
if( doWrite && binaryLoadAnim.GetBool() )
|
||||
{
|
||||
idLib::Printf( "Writing %s\n", generatedFileName.c_str() );
|
||||
fileptr->Seek( 0, FS_SEEK_SET );
|
||||
idFile_Memory* memFile = static_cast<idFile_Memory*>( fileptr );
|
||||
fileSystem->WriteFile( generatedFileName, memFile->GetDataPtr(), memFile->GetAllocated(), "fs_basepath" );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3361,7 +3361,7 @@ bool idDeclModelDef::Parse( const char* text, const int textLength, bool allowBi
|
|||
|
||||
// get the number of joints
|
||||
num = modelHandle->NumJoints();
|
||||
if( !num )
|
||||
if( !num && !isGltf )
|
||||
{
|
||||
src.Warning( "Model '%s' has no joints", filename.c_str() );
|
||||
}
|
||||
|
@ -3373,7 +3373,7 @@ bool idDeclModelDef::Parse( const char* text, const int textLength, bool allowBi
|
|||
joints.SetNum( num );
|
||||
jointParents.SetNum( num );
|
||||
channelJoints[0].SetNum( num );
|
||||
md5joints = modelHandle->GetJoints( );
|
||||
md5joints = modelHandle->GetJoints();
|
||||
md5joint = md5joints;
|
||||
for( i = 0; i < num; i++, md5joint++ )
|
||||
{
|
||||
|
|
63
neo/idStuff.natvis
Normal file
63
neo/idStuff.natvis
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- natvis file for Visual Studio debugger (you can include this in a project file, or install in visual studio folder) -->
|
||||
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
|
||||
<Type Name="idList<*>">
|
||||
<DisplayString>{{Size={num} Capacity={size}}}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[size]">num</Item>
|
||||
<Item Name="[capacity]">size</Item>
|
||||
<ArrayItems>
|
||||
<Size>num</Size>
|
||||
<ValuePointer>list</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="idVec4">
|
||||
<DisplayString>{{{x,g},{y,g},{z,g},{w,g}}}</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="idVec2">
|
||||
<DisplayString>{{{x},{y}}}</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="idStr">
|
||||
<DisplayString>{data,s}</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="idSWFDictionaryEntry">
|
||||
<DisplayString Condition="name != 0">{name}</DisplayString>
|
||||
<Expand>
|
||||
<Item Condition="type == SWF_DICT_SPRITE" Name=" [ Sprite ]">sprite</Item>
|
||||
<Item Condition="type == SWF_DICT_EDITTEXT" Name=" [ EditText ]">edittext</Item>
|
||||
<Item Condition="type == SWF_DICT_FONT" Name=" [ Font ] ">font</Item>
|
||||
<Item Condition="type == SWF_DICT_TEXT" Name=" [ Text ] ">text</Item>
|
||||
<Item Condition="type == SWF_DICT_IMAGE" Name=" [ Image ]">imageSize</Item>
|
||||
<Item Condition="type == SWF_DICT_NULL" Name=" [ Empty ] ">name</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="idSWFScriptVar">
|
||||
<Expand>
|
||||
<Item Condition="type == SWF_VAR_OBJECT" Name=" [ Object ]">value.object</Item>
|
||||
<Item Condition="type == SWF_VAR_FUNCTION" Name=" [ Function ]">value.function</Item>
|
||||
<Item Condition="type == SWF_VAR_STRING" Name=" [ String ]">value.string</Item>
|
||||
<Item Condition="type == SWF_VAR_FLOAT" Name=" [ Float ]">value.f</Item>
|
||||
<Item Condition="type == SWF_VAR_UNDEF" Name=" [ UNDEFINED ]">value</Item>
|
||||
<Item Condition="type == SWF_VAR_BOOL" Name=" [ Bool ]">value.b</Item>
|
||||
<Item Condition="type == SWF_VAR_INTEGER" Name=" [ Int ]">value.i</Item>
|
||||
<Item Condition="type == SWF_VAR_STRINGID" Name=" [ StrID ]">value.i</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="idSWFScriptObject::swfNamedVar_t">
|
||||
<DisplayString >[{name}]{value}</DisplayString>
|
||||
</Type>
|
||||
|
||||
<Type Name="swfMethod_info">
|
||||
<DisplayString >[{name}]</DisplayString>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
|
@ -5,6 +5,7 @@ Doom 3 BFG Edition GPL Source Code
|
|||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2015-2022 Robert Beckebans
|
||||
Copyright (C) 2020 Admer (id Tech Fox)
|
||||
Copyright (C) 2022 Harrie van Ginneken
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -1673,13 +1674,9 @@ bool idMapFile::Parse( const char* filename, bool ignoreRegion, bool osPath )
|
|||
}
|
||||
else if( isGTLF )
|
||||
{
|
||||
gltfParser->Load( fullName );
|
||||
idMapEntity::GetEntities( gltfParser->currentAsset, entities, 0 );
|
||||
}
|
||||
else if( isGTLF )
|
||||
{
|
||||
gltfParser->Load( fullName );
|
||||
idMapEntity::GetEntities( gltfParser->currentAsset, entities, gltfParser->currentAsset->GetSceneId( gltf_MapSceneName.GetString() ) );
|
||||
GLTF_Parser gltf;
|
||||
gltf.Load( fullName );
|
||||
idMapEntity::GetEntities( gltf.currentAsset, entities, gltf.currentAsset->GetSceneId( gltf_MapSceneName.GetString() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
|
|||
gltfData* data = bv->parent;
|
||||
|
||||
// files import as y-up. Use this transform to change the model to z-up.
|
||||
idMat3 rotation = idAngles( 0.0f, 0.0f, 90.0f ).ToMat3( );
|
||||
idMat3 rotation = idAngles( 0.0f, 0.0f, 90.0f ).ToMat3();
|
||||
idMat4 axisTransform( rotation, vec3_origin );
|
||||
|
||||
gltfMaterial* mat = NULL;
|
||||
|
@ -55,6 +55,8 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
|
|||
idFile_Memory idxBin = idFile_Memory( "gltfChunkIndices",
|
||||
( const char* )( ( data->GetData( bv->buffer ) + bv->byteOffset + accessor->byteOffset ) ), bv->byteLength );
|
||||
|
||||
|
||||
|
||||
for( int i = 0; i < accessor->count; i++ )
|
||||
{
|
||||
idxBin.Read( ( void* )( &indices[i] ), accessor->typeSize );
|
||||
|
@ -64,9 +66,15 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
|
|||
}
|
||||
}
|
||||
|
||||
int polyCount = accessor->count / 3;
|
||||
|
||||
mesh->polygons.AssureSize( polyCount );
|
||||
mesh->polygons.SetNum( polyCount );
|
||||
|
||||
int cnt = 0;
|
||||
for( int i = 0; i < accessor->count; i += 3 )
|
||||
{
|
||||
MapPolygon& polygon = mesh->polygons.Alloc();
|
||||
MapPolygon& polygon = mesh->polygons[cnt++];
|
||||
|
||||
if( mat != NULL )
|
||||
{
|
||||
|
@ -82,6 +90,8 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
|
|||
polygon.AddIndex( indices[i + 0] );
|
||||
}
|
||||
|
||||
assert( cnt == polyCount );
|
||||
|
||||
Mem_Free( indices );
|
||||
bool sizeSet = false;
|
||||
|
||||
|
@ -204,30 +214,72 @@ MapPolygonMesh* MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh_Primitive* p
|
|||
}
|
||||
break;
|
||||
}
|
||||
//case gltfMesh_Primitive_Attribute::Type::Weight:
|
||||
//{
|
||||
// for ( int i = 0; i < attrAcc->count; i++ ) {
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.x ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.y ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.z ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].weight.w ), attrAcc->typeSize );
|
||||
// if ( attrBv->byteStride )
|
||||
// bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
//case gltfMesh_Primitive_Attribute::Type::Indices:
|
||||
//{
|
||||
// for ( int i = 0; i < attrAcc->count; i++ ) {
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.x ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.y ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.z ), attrAcc->typeSize );
|
||||
// bin.Read( ( void * ) ( &vtxData[i].boneIndex.w ), attrAcc->typeSize );
|
||||
// if ( attrBv->byteStride )
|
||||
// bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
case gltfMesh_Primitive_Attribute::Type::Weight:
|
||||
{
|
||||
idVec4 vec;
|
||||
for( int i = 0; i < attrAcc->count; i++ )
|
||||
{
|
||||
bin.Read( ( void* )( &vec.x ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.y ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.z ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec.w ), attrAcc->typeSize );
|
||||
if( attrBv->byteStride )
|
||||
{
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
mesh->verts[i].SetColor2( PackColor( vec ) );
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gltfMesh_Primitive_Attribute::Type::Indices:
|
||||
{
|
||||
if( attrAcc->typeSize == 2 )
|
||||
{
|
||||
uint16_t vec[4];
|
||||
for( int i = 0; i < attrAcc->count; i++ )
|
||||
{
|
||||
bin.Read( ( void* )( &vec[0] ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec[1] ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec[2] ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec[3] ), attrAcc->typeSize );
|
||||
if( attrBv->byteStride )
|
||||
{
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
mesh->verts[i].color[0] = vec[0];
|
||||
mesh->verts[i].color[1] = vec[1];
|
||||
mesh->verts[i].color[2] = vec[2];
|
||||
mesh->verts[i].color[3] = vec[3];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t vec[4];
|
||||
for( int i = 0; i < attrAcc->count; i++ )
|
||||
{
|
||||
assert( sizeof( vec ) == attrAcc->typeSize );
|
||||
|
||||
bin.Read( ( void* )( &vec[0] ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec[1] ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec[2] ), attrAcc->typeSize );
|
||||
bin.Read( ( void* )( &vec[3] ), attrAcc->typeSize );
|
||||
if( attrBv->byteStride )
|
||||
{
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
mesh->verts[i].color[0] = vec[0];
|
||||
mesh->verts[i].color[1] = vec[1];
|
||||
mesh->verts[i].color[2] = vec[2];
|
||||
mesh->verts[i].color[3] = vec[3];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -256,9 +308,9 @@ void ProcessSceneNode( idMapEntity* newEntity, gltfNode* node, idMat4 trans, glt
|
|||
ProcessSceneNode( newEntity, nodeList[child], curTrans, data, isFuncStaticMesh );
|
||||
}
|
||||
|
||||
if( isFuncStaticMesh && node->mesh != -1 )
|
||||
if( node->mesh != -1 )
|
||||
{
|
||||
for( auto prim : data->MeshList()[node->mesh]->primitives )
|
||||
for( auto* prim : data->MeshList()[node->mesh]->primitives )
|
||||
{
|
||||
newEntity->AddPrimitive( MapPolygonMesh::ConvertFromMeshGltf( prim, data , curTrans ) );
|
||||
}
|
||||
|
@ -284,7 +336,7 @@ void ProcessSceneNode( idMapEntity* newEntity, gltfNode* node, idMat4 trans, glt
|
|||
origin.z = node->translation.z;
|
||||
|
||||
// files import as y-up. Use this transform to change the model to z-up.
|
||||
idMat3 rotation = idAngles( 0.0f, 0.0f, 90.0f ).ToMat3( );
|
||||
idMat3 rotation = idAngles( 0.0f, 0.0f, 90.0f ).ToMat3();
|
||||
idMat4 axisTransform( rotation, vec3_origin );
|
||||
|
||||
origin *= axisTransform;
|
||||
|
@ -299,7 +351,7 @@ void Map_AddMeshes( idMapEntity* _Entity, gltfNode* _Node, idMat4& _Trans, gltfD
|
|||
|
||||
if( _Node->mesh != -1 )
|
||||
{
|
||||
for( auto prim : _Data->MeshList( )[_Node->mesh]->primitives )
|
||||
for( auto prim : _Data->MeshList()[_Node->mesh]->primitives )
|
||||
{
|
||||
_Entity->AddPrimitive( MapPolygonMesh::ConvertFromMeshGltf( prim, _Data, curTrans ) );
|
||||
}
|
||||
|
@ -307,7 +359,7 @@ void Map_AddMeshes( idMapEntity* _Entity, gltfNode* _Node, idMat4& _Trans, gltfD
|
|||
|
||||
for( auto& child : _Node->children )
|
||||
{
|
||||
Map_AddMeshes( _Entity, _Data->NodeList( )[child], curTrans, _Data );
|
||||
Map_AddMeshes( _Entity, _Data->NodeList()[child], curTrans, _Data );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1135,8 +1135,14 @@ void gltfItem_texture_info_extensions::parse( idToken& token )
|
|||
|
||||
void GLTF_Parser::Shutdown()
|
||||
{
|
||||
parser.FreeSource();
|
||||
currentFile.FreeData();
|
||||
if( currentAsset )
|
||||
{
|
||||
delete currentAsset;
|
||||
}
|
||||
currentAsset = nullptr;
|
||||
buffersDone = false;
|
||||
bufferViewsDone = false;
|
||||
}
|
||||
GLTF_Parser::GLTF_Parser()
|
||||
: parser( LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES ) , buffersDone( false ), bufferViewsDone( false ) { }
|
||||
|
@ -1914,6 +1920,12 @@ gltfProperty GLTF_Parser::ResolveProp( idToken& token )
|
|||
|
||||
bool GLTF_Parser::loadGLB( idStr filename )
|
||||
{
|
||||
if( fileSystem->GetFileLength( filename ) <= 0 )
|
||||
{
|
||||
common->Warning( " %s does not exist!", filename.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
idFile* file = fileSystem->OpenFileRead( filename );
|
||||
|
||||
if( file->Length() < 20 )
|
||||
|
@ -1948,7 +1960,7 @@ bool GLTF_Parser::loadGLB( idStr filename )
|
|||
unsigned int chunk_type = 0; // 4 bytes
|
||||
unsigned int chunk_length = 0; // 4 bytes
|
||||
byte* data = nullptr;
|
||||
gltfData* dataCache = gltfData::Data( filename );
|
||||
gltfData* dataCache = gltfData::Data( filename, true );
|
||||
currentAsset = dataCache;
|
||||
|
||||
int chunkCount = 0;
|
||||
|
@ -1959,7 +1971,6 @@ bool GLTF_Parser::loadGLB( idStr filename )
|
|||
length -= file->ReadUnsignedInt( chunk_type );
|
||||
|
||||
data = dataCache->AddData( chunk_length );
|
||||
dataCache->FileName( filename );
|
||||
|
||||
int read = file->Read( ( void* )data, chunk_length );
|
||||
if( read != chunk_length )
|
||||
|
@ -2074,21 +2085,18 @@ bool GLTF_Parser::Parse()
|
|||
|
||||
bool GLTF_Parser::Load( idStr filename )
|
||||
{
|
||||
//seriously fix this; proper gltf data cache.
|
||||
//.. and destroy it properly too!!
|
||||
static idStr lastFile = "";
|
||||
|
||||
//next line still has to be fixed.
|
||||
//gfx is not updated on command
|
||||
common->SetRefreshOnPrint( true );
|
||||
|
||||
if( lastFile == filename )
|
||||
//.. and destroy data !!
|
||||
gltfData* data = gltfData::Data( filename );
|
||||
currentFile = filename;
|
||||
if( data != nullptr )
|
||||
{
|
||||
common->Warning( "Did not parse %s again", filename.c_str() );
|
||||
currentAsset = data;
|
||||
parser.FreeSource();
|
||||
return true;
|
||||
}
|
||||
lastFile = filename;
|
||||
currentFile = filename;
|
||||
|
||||
common->SetRefreshOnPrint( true );
|
||||
if( filename.CheckExtension( ".glb" ) )
|
||||
{
|
||||
if( !loadGLB( filename ) )
|
||||
|
@ -2104,8 +2112,7 @@ bool GLTF_Parser::Load( idStr filename )
|
|||
common->FatalError( "Failed to read file" );
|
||||
}
|
||||
|
||||
gltfData* data = gltfData::Data( filename );
|
||||
data->FileName( filename );
|
||||
data = gltfData::Data( filename , true );
|
||||
byte* dataBuff = data->AddData( length );
|
||||
currentAsset = data;
|
||||
|
||||
|
@ -2137,18 +2144,29 @@ bool GLTF_Parser::Load( idStr filename )
|
|||
//fix up node hierarchy
|
||||
auto& nodeList = currentAsset->NodeList();
|
||||
for( auto& scene : currentAsset->SceneList() )
|
||||
{
|
||||
for( auto& node : scene->nodes )
|
||||
{
|
||||
SetNodeParent( nodeList[node] );
|
||||
}
|
||||
}
|
||||
|
||||
//set skeleton ID's
|
||||
for( auto* skin : currentAsset->SkinList() )
|
||||
{
|
||||
if( skin->skeleton == -1 )
|
||||
{
|
||||
skin->skeleton = currentAsset->GetNodeIndex( currentAsset->GetNode( skin->name ) );
|
||||
}
|
||||
}
|
||||
//prefix with id
|
||||
if( gltfParser_PrefixNodeWithID.GetBool() )
|
||||
{
|
||||
for( int i = 0; i < nodeList.Num(); i++ )
|
||||
{
|
||||
nodeList[i]->name = "[" + idStr( i ) + "]" + nodeList[i]->name;
|
||||
}
|
||||
|
||||
}
|
||||
//CreateBgfxData();
|
||||
return true;
|
||||
}
|
||||
|
@ -2287,20 +2305,45 @@ idList<idQuat*>& gltfData::GetAccessorView( gltfAccessor* accessor )
|
|||
|
||||
gltfData::~gltfData()
|
||||
{
|
||||
//hvg_todo
|
||||
//delete data, not only pointer
|
||||
common->Warning( "GLTF DATA NOT FREED" );
|
||||
|
||||
if( data )
|
||||
{
|
||||
delete[] data;
|
||||
while( totalChunks )
|
||||
{
|
||||
Mem_Free( data[--totalChunks] );
|
||||
}
|
||||
Mem_Free( data );
|
||||
}
|
||||
|
||||
//delete cameraManager;
|
||||
if( json )
|
||||
{
|
||||
Mem_Free( json );
|
||||
}
|
||||
|
||||
data = nullptr;
|
||||
json = nullptr;
|
||||
ClearData( fileName );
|
||||
|
||||
}
|
||||
|
||||
void gltfData::ClearData( idStr& fileName )
|
||||
{
|
||||
int key = fileDataHash.GenerateKey( fileName );
|
||||
int index = fileDataHash.GetFirst( key );
|
||||
|
||||
if( index != -1 )
|
||||
{
|
||||
dataList.RemoveIndex( index );
|
||||
dataList.Condense();
|
||||
fileDataHash.RemoveIndex( key, index );
|
||||
}
|
||||
else
|
||||
{
|
||||
common->DWarning( " tried to clear GLTF data while no data was loaded for %s", fileName.c_str() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GLTF_Parser localGltfParser;
|
||||
GLTF_Parser* gltfParser = &localGltfParser;
|
||||
|
||||
#undef GLTFARRAYITEM
|
||||
#undef GLTFARRAYITEMREF
|
||||
|
@ -2310,7 +2353,8 @@ CONSOLE_COMMAND_COMPILE( LoadGLTF, "Loads an .gltf or .glb file", idCmdSystem::A
|
|||
|
||||
if( args.Argc() > 1 )
|
||||
{
|
||||
gltfParser->Load( args.Argv( 1 ) );
|
||||
GLTF_Parser gltf;
|
||||
gltf.Load( args.Argv( 1 ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2318,39 +2362,39 @@ CONSOLE_COMMAND_COMPILE( LoadGLTF, "Loads an .gltf or .glb file", idCmdSystem::A
|
|||
|
||||
|
||||
// not dots allowed in [%s]!
|
||||
// [filename].[%i|%s].[gltf/glb]
|
||||
bool gltfManager::ExtractMeshIdentifier( idStr& filename, int& meshId, idStr& meshName )
|
||||
// [filename].[%i|%s].[gltf|glb]
|
||||
bool gltfManager::ExtractIdentifier( idStr& filename, int& id, idStr& name )
|
||||
{
|
||||
idStr extension;
|
||||
idStr meshStr;
|
||||
idStr targetStr;
|
||||
filename.ExtractFileExtension( extension );
|
||||
idStr file = filename;
|
||||
file = file.StripFileExtension();
|
||||
file.ExtractFileExtension( meshStr );
|
||||
file.ExtractFileExtension( targetStr );
|
||||
|
||||
if( !extension.Length() )
|
||||
{
|
||||
idLib::Warning( "no gltf mesh identifier" );
|
||||
idLib::Warning( "no gltf identifier" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( meshStr.Length() )
|
||||
if( targetStr.Length() )
|
||||
{
|
||||
filename = file.Left( file.Length() - meshStr.Length() - 1 ) + "." + extension;
|
||||
filename = file.Left( file.Length() - targetStr.Length() - 1 ) + "." + extension;
|
||||
|
||||
idParser parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
|
||||
parser.LoadMemory( meshStr.c_str(), meshStr.Size(), "model:GltfmeshID" );
|
||||
parser.LoadMemory( targetStr.c_str(), targetStr.Size(), "model:GltfID" );
|
||||
|
||||
idToken token;
|
||||
if( parser.ExpectAnyToken( &token ) )
|
||||
{
|
||||
if( ( token.type == TT_NUMBER ) && ( token.subtype & TT_INTEGER ) )
|
||||
{
|
||||
meshId = token.GetIntValue();
|
||||
id = token.GetIntValue();
|
||||
}
|
||||
else if( token.type == TT_NAME )
|
||||
{
|
||||
meshName = token;
|
||||
name = token;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -303,6 +303,10 @@ private:
|
|||
class GLTF_Parser
|
||||
{
|
||||
public:
|
||||
~GLTF_Parser()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
GLTF_Parser();
|
||||
void Shutdown();
|
||||
bool Parse();
|
||||
|
@ -349,7 +353,5 @@ private:
|
|||
class gltfManager
|
||||
{
|
||||
public:
|
||||
static bool ExtractMeshIdentifier( idStr& filename , int& meshId, idStr& meshName );
|
||||
};
|
||||
|
||||
extern GLTF_Parser* gltfParser;
|
||||
static bool ExtractIdentifier( idStr& filename , int& id, idStr& name );
|
||||
};
|
|
@ -134,6 +134,11 @@ public:
|
|||
gltfNode() : camera( -1 ), skin( -1 ), matrix( mat4_zero ),
|
||||
mesh( -1 ), rotation( 0.f, 0.f, 0.f, 1.f ), scale( 1.f, 1.f, 1.f ),
|
||||
translation( vec3_zero ), parent( nullptr ), dirty( true ) { }
|
||||
//Only checks name!
|
||||
bool operator == ( const gltfNode& rhs )
|
||||
{
|
||||
return name == rhs.name;
|
||||
}
|
||||
int camera;
|
||||
idList<int> children;
|
||||
int skin;
|
||||
|
@ -760,7 +765,7 @@ const inline idList<gltf##name*> & ##name##List() { return target; }
|
|||
class gltfData
|
||||
{
|
||||
public:
|
||||
gltfData() : fileNameHash( 0 ), json( nullptr ), data( nullptr ), totalChunks( -1 ) { };
|
||||
gltfData() : fileName( "" ), fileNameHash( 0 ), json( nullptr ), data( nullptr ), totalChunks( -1 ) { };
|
||||
~gltfData();
|
||||
byte* AddData( int size, int* bufferID = nullptr );
|
||||
byte* GetJsonData( int& size )
|
||||
|
@ -772,10 +777,10 @@ public:
|
|||
{
|
||||
return data[index];
|
||||
}
|
||||
void FileName( const idStr& file )
|
||||
void FileName( const idStr& file, int hash )
|
||||
{
|
||||
fileName = file;
|
||||
fileNameHash = fileDataHash.GenerateKey( file.c_str() );
|
||||
fileNameHash = hash;
|
||||
}
|
||||
int FileNameHash()
|
||||
{
|
||||
|
@ -788,27 +793,39 @@ public:
|
|||
|
||||
static idHashIndex fileDataHash;
|
||||
static idList<gltfData*> dataList;
|
||||
//add data from filename
|
||||
static gltfData* Data( idStr& fileName )
|
||||
//add data for filename
|
||||
static gltfData* Data( idStr& fileName, bool create = false )
|
||||
{
|
||||
dataList.AssureSizeAlloc( dataList.Num() + 1, idListNewElement<gltfData> );
|
||||
dataList[dataList.Num() - 1]->FileName( fileName );
|
||||
fileDataHash.Add( fileDataHash.GenerateKey( fileName ), dataList.Num() - 1 );
|
||||
return dataList[dataList.Num() - 1];
|
||||
}
|
||||
//find data;
|
||||
static gltfData* Data( const char* filename )
|
||||
{
|
||||
return dataList[fileDataHash.First( fileDataHash.GenerateKey( filename ) )];
|
||||
static bool intialized = false;
|
||||
if( ! intialized )
|
||||
{
|
||||
dataList.SetGranularity( 1 );
|
||||
intialized = true;
|
||||
}
|
||||
int key = fileDataHash.GenerateKey( fileName );
|
||||
int index = fileDataHash.GetFirst( key );
|
||||
|
||||
if( create && index == -1 )
|
||||
{
|
||||
index = dataList.Num();
|
||||
dataList.AssureSizeAlloc( index + 1, idListNewElement<gltfData> );
|
||||
dataList[index]->FileName( fileName, key );
|
||||
fileDataHash.Add( key , index );
|
||||
}
|
||||
|
||||
if( !create && index < 0 )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return dataList[index];
|
||||
}
|
||||
static const idList<gltfData*>& DataList()
|
||||
{
|
||||
return dataList;
|
||||
}
|
||||
static void ClearData()
|
||||
{
|
||||
idLib::Warning( "TODO! DATA NOT FREED" );
|
||||
}
|
||||
|
||||
static void ClearData( idStr& fileName );
|
||||
|
||||
//return the GLTF nodes that control the given camera
|
||||
//return TRUE if the camera uses 2 nodes (like when blender exports gltfs with +Y..)
|
||||
|
@ -866,27 +883,10 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
gltfNode* GetNode( gltfScene* scene, idStr name )
|
||||
{
|
||||
assert( scene );
|
||||
assert( name[0] );
|
||||
|
||||
auto& nodeList = scene->nodes;
|
||||
for( auto& nodeId : nodeList )
|
||||
{
|
||||
if( nodes[nodeId]->name == name )
|
||||
{
|
||||
return nodes[nodeId];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gltfNode* GetNode( idStr sceneName, int id, idStr* name = nullptr )
|
||||
{
|
||||
int sceneId = GetSceneId( sceneName );
|
||||
if( sceneId < 0 || sceneId > scenes.Num( ) )
|
||||
if( sceneId < 0 || sceneId > scenes.Num() )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -913,7 +913,30 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
gltfNode* GetNode( idStr sceneName, idStr name , int* id = nullptr )
|
||||
gltfNode* GetNode( idStr name, int* id = nullptr, bool caseSensitive = false )
|
||||
{
|
||||
assert( name[0] );
|
||||
|
||||
auto& nodeList = NodeList();
|
||||
for( auto* node : nodes )
|
||||
{
|
||||
int nodeId = GetNodeIndex( node );
|
||||
if( caseSensitive ? nodes[nodeId]->name.Cmp( name ) : nodes[nodeId]->name.Icmp( name ) == 0 )
|
||||
{
|
||||
if( id != nullptr )
|
||||
{
|
||||
*id = nodeId;
|
||||
}
|
||||
|
||||
return nodes[nodeId];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
gltfNode* GetNode( idStr sceneName, idStr name , int* id = nullptr , bool caseSensitive = false )
|
||||
{
|
||||
int sceneId = GetSceneId( sceneName );
|
||||
if( sceneId < 0 || sceneId > scenes.Num() )
|
||||
|
@ -927,9 +950,9 @@ public:
|
|||
assert( name[0] );
|
||||
|
||||
auto& nodeList = scene->nodes;
|
||||
for( auto& nodeId : nodeList )
|
||||
for( auto nodeId : nodeList )
|
||||
{
|
||||
if( nodes[nodeId]->name.Icmp( name ) == 0 )
|
||||
if( caseSensitive ? nodes[nodeId]->name.Cmp( name ) : nodes[nodeId]->name.Icmp( name ) == 0 )
|
||||
{
|
||||
if( id != nullptr )
|
||||
{
|
||||
|
@ -943,6 +966,20 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
int GetNodeIndex( gltfNode* node )
|
||||
{
|
||||
int index = -1;
|
||||
for( auto& it : nodes )
|
||||
{
|
||||
index++;
|
||||
if( it == node )
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool HasAnimation( int nodeID )
|
||||
{
|
||||
for( auto anim : animations )
|
||||
|
@ -958,18 +995,142 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
int GetSceneId( idStr sceneName ) const
|
||||
gltfAnimation* GetAnimation( idStr animName, int target )
|
||||
{
|
||||
for( auto* anim : animations )
|
||||
{
|
||||
if( anim->name == animName )
|
||||
{
|
||||
bool hasTarget = false;
|
||||
for( auto* channel : anim->channels )
|
||||
{
|
||||
if( channel->target.node == target )
|
||||
{
|
||||
hasTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( hasTarget )
|
||||
{
|
||||
return anim;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int GetSceneId( idStr sceneName , gltfScene* result = nullptr ) const
|
||||
{
|
||||
for( int i = 0; i < scenes.Num(); i++ )
|
||||
{
|
||||
if( scenes[i]->name == sceneName )
|
||||
{
|
||||
if( result != nullptr )
|
||||
{
|
||||
result = scenes[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GetAllMeshes( gltfNode* node, idList<int>& meshIds )
|
||||
{
|
||||
if( node->mesh != -1 )
|
||||
{
|
||||
meshIds.Append( GetNodeIndex( node ) );
|
||||
}
|
||||
|
||||
for( auto child : node->children )
|
||||
{
|
||||
GetAllMeshes( nodes[child], meshIds );
|
||||
}
|
||||
}
|
||||
|
||||
gltfSkin* GetSkin( int boneNodeId )
|
||||
{
|
||||
for( auto skin : skins )
|
||||
{
|
||||
if( skin->joints.Find( boneNodeId ) )
|
||||
{
|
||||
return skin;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gltfSkin* GetSkin( gltfAnimation* anim )
|
||||
{
|
||||
auto animTargets = GetAnimTargets( anim );
|
||||
|
||||
if( !animTargets.Num() )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for( int nodeID : animTargets )
|
||||
{
|
||||
gltfSkin* foundSkin = GetSkin( nodeID );
|
||||
if( foundSkin != nullptr )
|
||||
{
|
||||
return foundSkin;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
idList<int> GetAnimTargets( gltfAnimation* anim ) const
|
||||
{
|
||||
idList<int> result;
|
||||
for( auto channel : anim->channels )
|
||||
{
|
||||
result.AddUnique( channel->target.node );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
idList<int> GetChannelIds( gltfAnimation* anim , gltfNode* node ) const
|
||||
{
|
||||
idList<int> result;
|
||||
int channelIdx = 0;
|
||||
for( auto channel : anim->channels )
|
||||
{
|
||||
if( channel->target.node >= 0 && nodes[channel->target.node] == node )
|
||||
{
|
||||
result.Append( channelIdx );
|
||||
break;
|
||||
}
|
||||
channelIdx++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int GetAnimationIds( gltfNode* node , idList<int>& result )
|
||||
{
|
||||
|
||||
int animIdx = 0;
|
||||
for( auto anim : animations )
|
||||
{
|
||||
for( auto channel : anim->channels )
|
||||
{
|
||||
if( channel->target.node >= 0 && nodes[channel->target.node] == node )
|
||||
{
|
||||
result.AddUnique( animIdx );
|
||||
}
|
||||
}
|
||||
animIdx++;
|
||||
}
|
||||
for( int nodeId : node->children )
|
||||
{
|
||||
GetAnimationIds( nodes[nodeId], result );
|
||||
}
|
||||
return result.Num();
|
||||
}
|
||||
|
||||
idMat4 GetViewMatrix( int camId ) const
|
||||
{
|
||||
//if (cameraManager->HasOverideID(camId) )
|
||||
|
|
|
@ -360,6 +360,8 @@ public:
|
|||
|
||||
static void Init();
|
||||
|
||||
static float RSqrt( float x ); // reciprocal square root, returns huge number when x == 0.0
|
||||
|
||||
static float InvSqrt( float x ); // inverse square root with 32 bits precision, returns huge number when x == 0.0
|
||||
static float InvSqrt16( float x ); // inverse square root with 16 bits precision, returns huge number when x == 0.0
|
||||
|
||||
|
@ -502,6 +504,21 @@ ID_INLINE byte CLAMP_BYTE( int x )
|
|||
return ( ( x ) < 0 ? ( 0 ) : ( ( x ) > 255 ? 255 : ( byte )( x ) ) );
|
||||
}
|
||||
|
||||
|
||||
ID_INLINE float idMath::RSqrt( float x )
|
||||
{
|
||||
int i;
|
||||
float y, r;
|
||||
|
||||
y = x * 0.5f;
|
||||
i = *reinterpret_cast< int* >( &x );
|
||||
i = 0x5f3759df - ( i >> 1 );
|
||||
r = *reinterpret_cast< float* >( &i );
|
||||
r = r * ( 1.5f - r * r * y );
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
idMath::InvSqrt
|
||||
|
|
|
@ -280,4 +280,258 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//===============================================================
|
||||
//
|
||||
// idVec4i - 4D vector
|
||||
//
|
||||
//===============================================================
|
||||
|
||||
class idVec4i
|
||||
{
|
||||
public:
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 z;
|
||||
uint8 w;
|
||||
|
||||
idVec4i( void );
|
||||
explicit idVec4i( const uint8 x )
|
||||
{
|
||||
Set( x, x, x, x );
|
||||
}
|
||||
explicit idVec4i( const uint8 x, const uint8 y, const uint8 z, const uint8 w );
|
||||
|
||||
void Set( const uint8 x, const uint8 y, const uint8 z, const uint8 w );
|
||||
void Zero( void );
|
||||
|
||||
int operator[]( const int index ) const;
|
||||
uint8& operator[]( const int index );
|
||||
idVec4i operator-() const;
|
||||
uint8 operator*( const idVec4i& a ) const;
|
||||
idVec4i operator*( const uint8 a ) const;
|
||||
idVec4i operator/( const uint8 a ) const;
|
||||
idVec4i operator+( const idVec4i& a ) const;
|
||||
idVec4i operator-( const idVec4i& a ) const;
|
||||
idVec4i& operator+=( const idVec4i& a );
|
||||
idVec4i& operator-=( const idVec4i& a );
|
||||
idVec4i& operator/=( const idVec4i& a );
|
||||
idVec4i& operator/=( const uint8 a );
|
||||
idVec4i& operator*=( const uint8 a );
|
||||
|
||||
friend idVec4i operator*( const uint8 a, const idVec4i b );
|
||||
|
||||
idVec4i Multiply( const idVec4i& a ) const;
|
||||
bool Compare( const idVec4i& a ) const; // exact compare, no epsilon
|
||||
|
||||
bool operator==( const idVec4i& a ) const; // exact compare, no epsilon
|
||||
bool operator!=( const idVec4i& a ) const; // exact compare, no epsilon
|
||||
|
||||
float Length( void ) const;
|
||||
float LengthSqr( void ) const;
|
||||
float Normalize( void ); // returns length
|
||||
float NormalizeFast( void ); // returns length
|
||||
|
||||
int GetDimension( void ) const;
|
||||
|
||||
const uint8* ToIntPtr( void ) const;
|
||||
uint8* ToIntPtr( void );
|
||||
const char* ToString( int precision = 2 ) const;
|
||||
|
||||
void Lerp( const idVec4i& v1, const idVec4i& v2, const float l );
|
||||
};
|
||||
|
||||
|
||||
ID_INLINE idVec4i::idVec4i( void ) { }
|
||||
|
||||
ID_INLINE idVec4i::idVec4i( const uint8 x, const uint8 y, const uint8 z, const uint8 w )
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
ID_INLINE void idVec4i::Set( const uint8 x, const uint8 y, const uint8 z, const uint8 w )
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
ID_INLINE void idVec4i::Zero( void )
|
||||
{
|
||||
x = y = z = w = 0.0f;
|
||||
}
|
||||
|
||||
ID_INLINE int idVec4i::operator[]( int index ) const
|
||||
{
|
||||
return ( &x )[index];
|
||||
}
|
||||
|
||||
ID_INLINE uint8& idVec4i::operator[]( int index )
|
||||
{
|
||||
return ( &x )[index];
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i idVec4i::operator-() const
|
||||
{
|
||||
return idVec4i( -x, -y, -z, -w );
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i idVec4i::operator-( const idVec4i& a ) const
|
||||
{
|
||||
return idVec4i( x - a.x, y - a.y, z - a.z, w - a.w );
|
||||
}
|
||||
|
||||
ID_INLINE uint8 idVec4i::operator*( const idVec4i& a ) const
|
||||
{
|
||||
return x * a.x + y * a.y + z * a.z + w * a.w;
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i idVec4i::operator*( const uint8 a ) const
|
||||
{
|
||||
return idVec4i( x * a, y * a, z * a, w * a );
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i idVec4i::operator/( const uint8 a ) const
|
||||
{
|
||||
float inva = 1.0f / a;
|
||||
return idVec4i( x * inva, y * inva, z * inva, w * inva );
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i operator*( const int a, const idVec4i b )
|
||||
{
|
||||
return idVec4i( b.x * a, b.y * a, b.z * a, b.w * a );
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i idVec4i::operator+( const idVec4i& a ) const
|
||||
{
|
||||
return idVec4i( x + a.x, y + a.y, z + a.z, w + a.w );
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i& idVec4i::operator+=( const idVec4i& a )
|
||||
{
|
||||
x += a.x;
|
||||
y += a.y;
|
||||
z += a.z;
|
||||
w += a.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i& idVec4i::operator/=( const idVec4i& a )
|
||||
{
|
||||
x /= a.x;
|
||||
y /= a.y;
|
||||
z /= a.z;
|
||||
w /= a.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i& idVec4i::operator/=( const uint8 a )
|
||||
{
|
||||
float inva = 1.0f / a;
|
||||
x *= inva;
|
||||
y *= inva;
|
||||
z *= inva;
|
||||
w *= inva;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i& idVec4i::operator-=( const idVec4i& a )
|
||||
{
|
||||
x -= a.x;
|
||||
y -= a.y;
|
||||
z -= a.z;
|
||||
w -= a.w;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i& idVec4i::operator*=( const uint8 a )
|
||||
{
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
w *= a;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idVec4i idVec4i::Multiply( const idVec4i& a ) const
|
||||
{
|
||||
return idVec4i( x * a.x, y * a.y, z * a.z, w * a.w );
|
||||
}
|
||||
|
||||
ID_INLINE bool idVec4i::Compare( const idVec4i& a ) const
|
||||
{
|
||||
return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) && w == a.w );
|
||||
}
|
||||
|
||||
ID_INLINE bool idVec4i::operator==( const idVec4i& a ) const
|
||||
{
|
||||
return Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE bool idVec4i::operator!=( const idVec4i& a ) const
|
||||
{
|
||||
return !Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE float idVec4i::Length( void ) const
|
||||
{
|
||||
return ( float ) idMath::Sqrt( x * x + y * y + z * z + w * w );
|
||||
}
|
||||
|
||||
ID_INLINE float idVec4i::LengthSqr( void ) const
|
||||
{
|
||||
return ( x * x + y * y + z * z + w * w );
|
||||
}
|
||||
|
||||
ID_INLINE float idVec4i::Normalize( void )
|
||||
{
|
||||
float sqrLength, invLength;
|
||||
|
||||
sqrLength = x * x + y * y + z * z + w * w;
|
||||
invLength = idMath::InvSqrt( sqrLength );
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
z *= invLength;
|
||||
w *= invLength;
|
||||
return invLength * sqrLength;
|
||||
}
|
||||
|
||||
ID_INLINE float idVec4i::NormalizeFast( void )
|
||||
{
|
||||
float sqrLength, invLength;
|
||||
|
||||
sqrLength = x * x + y * y + z * z + w * w;
|
||||
invLength = idMath::RSqrt( sqrLength );
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
z *= invLength;
|
||||
w *= invLength;
|
||||
return invLength * sqrLength;
|
||||
}
|
||||
|
||||
ID_INLINE int idVec4i::GetDimension( void ) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
ID_INLINE const uint8* idVec4i::ToIntPtr( void ) const
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
ID_INLINE uint8* idVec4i::ToIntPtr( void )
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,19 +29,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#pragma once
|
||||
#include "Model_local.h"
|
||||
|
||||
|
||||
|
||||
class idGltfMesh
|
||||
{
|
||||
public:
|
||||
idGltfMesh( ) {};
|
||||
idGltfMesh( gltfMesh* _mesh, gltfData* _data );
|
||||
private:
|
||||
gltfMesh* mesh;
|
||||
gltfData* data;
|
||||
idMD5Mesh md5Mesh;
|
||||
};
|
||||
|
||||
class idRenderModelGLTF : public idRenderModelStatic
|
||||
{
|
||||
public:
|
||||
|
@ -67,20 +54,28 @@ public:
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MakeMD5Mesh() ;
|
||||
static idFile_Memory* GetAnimBin( idStr animName, const ID_TIME_T sourceTimeStamp );
|
||||
int rootID;
|
||||
private:
|
||||
void ProcessNode( gltfNode* modelNode, idMat4 trans, gltfData* data );
|
||||
void UpdateSurface( const struct renderEntity_s* ent, idMat4 trans, modelSurface_t* surf );
|
||||
int rootID;
|
||||
|
||||
void UpdateSurface( const struct renderEntity_s* ent, const idJointMat* entJoints, const idJointMat* entJointsInverted, modelSurface_t* surf, const modelSurface_t& sourceSurf );
|
||||
void UpdateMd5Joints();
|
||||
gltfData* data;
|
||||
gltfNode* root;
|
||||
bool fileExclusive;
|
||||
bool hasAnimations;
|
||||
idList<int> animIds;
|
||||
idList<idGltfMesh, TAG_MODEL> meshes;
|
||||
|
||||
float maxJointVertDist; // maximum distance a vertex is separated from a joint
|
||||
idList<int, TAG_MODEL> animIds;
|
||||
idList<int, TAG_MODEL> bones;
|
||||
idList<int, TAG_MODEL> MeshNodeIds;
|
||||
dynamicModel_t model_state;
|
||||
idMat4 prevTrans;
|
||||
idList<gltfNode*, TAG_MODEL> SkeletonNodes;
|
||||
idStr meshName;
|
||||
|
||||
idList<idMD5Joint, TAG_MODEL> md5joints;
|
||||
idList<idJointQuat, TAG_MODEL> defaultPose;
|
||||
idList<idJointMat, TAG_MODEL> invertedDefaultPose;
|
||||
gltfSkin* currentSkin;
|
||||
private:
|
||||
void DrawJoints( const struct renderEntity_s* ent, const viewDef_t* view );
|
||||
};
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2022 Harrie van Ginneken
|
||||
Copyright (C) 2022 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
|
@ -417,6 +419,115 @@ idBrushList idAASBuild::AddBrushesForMapBrush( const idMapBrush* mapBrush, const
|
|||
|
||||
return brushList;
|
||||
}
|
||||
/*
|
||||
============
|
||||
idAASBuild::AddBrushesForMapPolygonMesh
|
||||
============
|
||||
*/
|
||||
|
||||
idBrushList idAASBuild::AddBrushesForMapPolygonMesh( const MapPolygonMesh* mapMesh, const idVec3& origin, const idMat3& axis, int entityNum, int primitiveNum, idBrushList brushList )
|
||||
{
|
||||
int contents = 0;
|
||||
int validBrushes = 0;
|
||||
|
||||
idFixedWinding w;
|
||||
idPlane plane;
|
||||
idVec3 d1, d2;
|
||||
idBrush* brush;
|
||||
const idMaterial* mat;
|
||||
|
||||
//per map polygon
|
||||
for( int p = 0 ; p < mapMesh->GetNumPolygons(); p++ )
|
||||
{
|
||||
const MapPolygon& face = mapMesh->GetFace( p );
|
||||
|
||||
mat = declManager->FindMaterial( face.GetMaterial() );
|
||||
contents = ContentsForAAS( mat->GetContentFlags() );
|
||||
|
||||
if( !contents )
|
||||
{
|
||||
return brushList;
|
||||
}
|
||||
|
||||
const idList<idDrawVert>& verts = mapMesh->GetDrawVerts();
|
||||
const idList<int>& indices = face.GetIndexes();
|
||||
|
||||
idVec3 triNormal;
|
||||
int v1 = 0;
|
||||
int v2 = 1;
|
||||
int v3 = 2;
|
||||
|
||||
//create brush with 2 triangles
|
||||
// 1 frontface from the mappoly verts
|
||||
// 1 backface, offset in direction off frontface normal at unit distance
|
||||
|
||||
//Front face
|
||||
d1 = verts[indices[1]].xyz - verts[indices[0]].xyz;
|
||||
d2 = verts[indices[2]].xyz - verts[indices[0]].xyz;
|
||||
plane.SetNormal( d1.Cross( d2 ) );
|
||||
if( plane.Normalize() != 0.0f )
|
||||
{
|
||||
plane.FitThroughPoint( verts[indices[2]].xyz );
|
||||
|
||||
w.Clear();
|
||||
w += verts[indices[0]].xyz;
|
||||
w += verts[indices[1]].xyz;
|
||||
w += verts[indices[2]].xyz;
|
||||
|
||||
brush = new idBrush();
|
||||
brush->SetContents( contents );
|
||||
if( brush->FromWinding( w, plane ) )
|
||||
{
|
||||
brush->SetEntityNum( entityNum );
|
||||
brush->SetPrimitiveNum( primitiveNum );
|
||||
brush->SetFlag( BFL_PATCH );
|
||||
brush->Transform( origin, axis );
|
||||
brushList.AddToTail( brush );
|
||||
validBrushes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete brush;
|
||||
}
|
||||
}
|
||||
|
||||
//Back face
|
||||
triNormal = plane.Normal();
|
||||
plane.SetNormal( d2.Cross( d1 ) );
|
||||
if( plane.Normalize() != 0.0f )
|
||||
{
|
||||
plane.FitThroughPoint( verts[indices[0]].xyz );
|
||||
|
||||
w.Clear();
|
||||
w += verts[indices[2]].xyz + triNormal;
|
||||
w += verts[indices[1]].xyz + triNormal;
|
||||
w += verts[indices[0]].xyz + triNormal;
|
||||
|
||||
brush = new idBrush();
|
||||
brush->SetContents( contents );
|
||||
if( brush->FromWinding( w, plane ) )
|
||||
{
|
||||
brush->SetEntityNum( entityNum );
|
||||
brush->SetPrimitiveNum( primitiveNum );
|
||||
brush->SetFlag( BFL_PATCH );
|
||||
brush->Transform( origin, axis );
|
||||
brushList.AddToTail( brush );
|
||||
validBrushes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete brush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !validBrushes )
|
||||
{
|
||||
common->Warning( "map polygon primitive %d on entity %d is completely degenerate", primitiveNum, entityNum );
|
||||
}
|
||||
|
||||
return brushList;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
|
@ -613,6 +724,11 @@ idBrushList idAASBuild::AddBrushesForMapEntity( const idMapEntity* mapEnt, int e
|
|||
}
|
||||
continue;
|
||||
}
|
||||
//HVG: Map polygon mesh support
|
||||
if( mapPrim->GetType() == idMapPrimitive::TYPE_MESH )
|
||||
{
|
||||
brushList = AddBrushesForMapPolygonMesh( static_cast< MapPolygonMesh* >( mapPrim ), origin, axis, entityNum, i, brushList );
|
||||
}
|
||||
}
|
||||
|
||||
return brushList;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2022 Harrie van Ginneken
|
||||
Copyright (C) 2022 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
|
@ -104,6 +106,7 @@ private: // map loading
|
|||
int ContentsForAAS( int contents );
|
||||
idBrushList AddBrushesForMapBrush( const idMapBrush* mapBrush, const idVec3& origin, const idMat3& axis, int entityNum, int primitiveNum, idBrushList brushList );
|
||||
idBrushList AddBrushesForMapPatch( const idMapPatch* mapPatch, const idVec3& origin, const idMat3& axis, int entityNum, int primitiveNum, idBrushList brushList );
|
||||
idBrushList AddBrushesForMapPolygonMesh( const MapPolygonMesh* mapMesh, const idVec3& origin, const idMat3& axis, int entityNum, int primitiveNum, idBrushList brushList );
|
||||
idBrushList AddBrushesForMapEntity( const idMapEntity* mapEnt, int entityNum, idBrushList brushList );
|
||||
idBrushList AddBrushesForMapFile( const idMapFile* mapFile, idBrushList brushList );
|
||||
bool CheckForEntities( const idMapFile* mapFile, idStrList& entityClassNames ) const;
|
||||
|
|
Loading…
Reference in a new issue