0
0
Fork 0
mirror of https://github.com/id-Software/DOOM-3-BFG.git synced 2025-03-15 23:21:35 +00:00
doom3-bfg/neo/idlib/gltfProperties.h
HarrievG ab7fefcadc - Added possibility to use Focal Length / FOV animation with GLTF Camera animations.
- Added blenderPy script which shows howto set lenscurves as a custom prop float array containing all evaluated fov values
- minor cleanup to gltfparser and gltfExtras.
- gltfExtra key value pairs can now contain a bracket enclosed string as value

# Conflicts:
#	neo/idlib/gltfProperties.h
2023-04-29 12:43:54 +02:00

1577 lines
No EOL
31 KiB
C++

/*
===========================================================================
Doom 3 BFG Edition GPL Source Code
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").
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#pragma once
#include "containers/StrList.h"
#include <functional>
#include "math/Quat.h"
#include "Lib.h"
#include "containers/List.h"
enum gltfProperty
{
INVALID,
ASSET,
ACCESSOR,
CAMERAS,
SCENE,
SCENES,
NODES,
MATERIALS,
MESHES,
TEXTURES,
IMAGES,
ACCESSORS,
BUFFERVIEWS,
SAMPLERS,
BUFFERS,
ANIMATIONS,
SKINS,
EXTENSIONS,
EXTENSIONS_USED,
EXTENSIONS_REQUIRED
};
class gltfData;
struct gltf_accessor_component
{
enum Type
{
_byte,
_uByte,
_short,
_uShort,
_uInt,
_float,
_double,
Count
};
};
template< class T >
struct gltf_accessor_component_type_map
{
idStr stringID;
int id;
T type;
uint sizeInBytes;//single element
};
class gltfExtra
{
public:
gltfExtra() { }
//entire extra json scope
idStr json;
//str:str pairs of each item
idDict strPairs;
};
class gltfExt_KHR_lights_punctual;
class gltfExtensions
{
public:
gltfExtensions() { }
idList<gltfExt_KHR_lights_punctual*> KHR_lights_punctual;
};
class gltfNode_KHR_lights_punctual
{
public:
int light;
};
class gltfNode_Extensions
{
public:
gltfNode_Extensions() :
KHR_lights_punctual( nullptr ) { }
gltfNode_KHR_lights_punctual* KHR_lights_punctual;
};
class gltfExt_KHR_materials_pbrSpecularGlossiness;
class gltfMaterial_Extensions
{
public:
gltfMaterial_Extensions() :
KHR_materials_pbrSpecularGlossiness( nullptr ) { }
gltfExt_KHR_materials_pbrSpecularGlossiness* KHR_materials_pbrSpecularGlossiness;
};
class gltfNode
{
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;
idMat4 matrix;
int mesh;
idQuat rotation;
idVec3 scale;
idVec3 translation;
idList<double> weights;
idStr name;
gltfNode_Extensions extensions;
gltfExtra extras;
//
gltfNode* parent;
bool dirty;
};
struct gltfCameraNodePtrs
{
gltfNode* translationNode = nullptr;
gltfNode* orientationNode = nullptr;
};
class gltfScene
{
public:
gltfScene() { }
idList<int> nodes;
idStr name;
idStr extensions;
gltfExtra extras;
};
class gltfMesh_Primitive_Attribute
{
public:
enum Type
{
Position,
Normal,
Tangent,
TexCoord0,
TexCoord1,
TexCoord2,
TexCoord3,
TexCoord4,
TexCoord5,
TexCoord6,
TexCoord7,
Color0,
Color1,
Color2,
Color3,
Weight,
Joints, // joint indices
Count
};
gltfMesh_Primitive_Attribute() : accessorIndex( -1 ), elementSize( 0 ), type( gltfMesh_Primitive_Attribute::Type::Count ) { }
idStr attributeSemantic;
int accessorIndex;
uint elementSize;
Type type;
};
struct gltf_mesh_attribute_map
{
idStr stringID;
gltfMesh_Primitive_Attribute::Type attib;
uint elementSize;
};
class gltfMesh_Primitive
{
public:
gltfMesh_Primitive() : indices( -1 ), material( -1 ), mode( -1 ) { }
idList<gltfMesh_Primitive_Attribute*> attributes;
int indices;
int material;
int mode;
idStr target;
idStr extensions;
gltfExtra extras;
};
class gltfMesh
{
public:
gltfMesh() { };
idList<gltfMesh_Primitive*> primitives; // gltfMesh_Primitive[1,*]
idList<double> weights; // number[1,*]
idStr name;
idStr extensions;
gltfExtra extras;
};
class gltfCamera_Orthographic
{
public:
gltfCamera_Orthographic() : xmag( 0.0f ), ymag( 0.0f ), zfar( 0.0f ), znear( 0.0f ) { };
float xmag;
float ymag;
float zfar;
float znear;
idStr extensions;
gltfExtra extras;
};
class gltfCamera_Perspective
{
public:
gltfCamera_Perspective() : aspectRatio( 0.0f ), yfov( 0.0f ), zfar( 0.0f ), znear( 0.0f ) { };
float aspectRatio;
float yfov;
float zfar;
float znear;
idStr extensions;
gltfExtra extras;
};
class gltfCamera
{
public:
gltfCamera() { };
gltfCamera_Orthographic orthographic;
gltfCamera_Perspective perspective;
idStr type;
idStr name;
idStr extensions;
gltfExtra extras;
};
class gltfAnimation_Channel_Target
{
public:
gltfAnimation_Channel_Target() : node( -1 ), TRS( gltfTRS::count ) { };
int node;
idStr path;
idStr extensions;
gltfExtra extras;
enum gltfTRS
{
none,
rotation,
translation,
scale,
weights,
count
};
gltfTRS TRS;
static gltfTRS resolveType( idStr type )
{
if( type == "translation" )
{
return gltfTRS::translation;
}
else if( type == "rotation" )
{
return gltfTRS::rotation;
}
else if( type == "scale" )
{
return gltfTRS::scale;
}
else if( type == "weights" )
{
return gltfTRS::weights;
}
return gltfTRS::count;
}
};
class gltfAnimation_Channel
{
public:
gltfAnimation_Channel() : sampler( -1 ) { };
int sampler;
gltfAnimation_Channel_Target target;
idStr extensions;
gltfExtra extras;
};
class gltfAnimation_Sampler
{
public:
gltfAnimation_Sampler() : input( -1 ), interpolation( "LINEAR" ), output( -1 ), intType( gltfInterpType::count ) { };
int input;
idStr interpolation;
int output;
idStr extensions;
gltfExtra extras;
enum gltfInterpType
{
linear,
step,
cubicSpline,
count
};
gltfInterpType intType;
static gltfInterpType resolveType( idStr type )
{
if( type == "LINEAR" )
{
return gltfInterpType::linear;
}
else if( type == "STEP" )
{
return gltfInterpType::step;
}
else if( type == "CUBICSPLINE" )
{
return gltfInterpType::cubicSpline;
}
return gltfInterpType::count;
}
};
class gltfAnimation
{
public:
gltfAnimation() : maxTime( 0.0f ), numFrames( 0 ) { };
idList<gltfAnimation_Channel*> channels;
idList<gltfAnimation_Sampler*> samplers;
idStr name;
idStr extensions;
gltfExtra extras;
float maxTime;
//id specific
mutable int ref_count;
int numFrames;
void DecreaseRefs() const
{
ref_count--;
};
void IncreaseRefs() const
{
ref_count++;
};
bool GetBounds( idBounds& bnds, int time, int cyclecount ) const
{
return false;
}
bool GetOriginRotation( idQuat& rotation, int time, int cyclecount ) const
{
return false;
}
bool GetOrigin( idVec3& offset, int time, int cyclecount ) const
{
return false;
}
int NumFrames() const
{
return numFrames;
}
};
class gltfAccessor_Sparse_Values
{
public:
gltfAccessor_Sparse_Values() : bufferView( -1 ), byteOffset( -1 ) { };
int bufferView;
int byteOffset;
idStr extensions;
gltfExtra extras;
};
class gltfAccessor_Sparse_Indices
{
public:
gltfAccessor_Sparse_Indices() : bufferView( -1 ), byteOffset( -1 ), componentType( -1 ) { };
int bufferView;
int byteOffset;
int componentType;
idStr extensions;
gltfExtra extras;
};
class gltfAccessor_Sparse
{
public:
gltfAccessor_Sparse() : count( -1 ) { };
int count;
gltfAccessor_Sparse_Indices indices;
gltfAccessor_Sparse_Values values;
idStr extensions;
gltfExtra extras;
};
class gltfAccessor
{
public:
gltfAccessor() : bufferView( -1 ), byteOffset( 0 ), componentType( -1 ), normalized( false ), count( -1 ) ,
floatView( nullptr ), vecView( nullptr ), quatView( nullptr ), matView( nullptr ) { }
int bufferView;
int byteOffset;
int componentType;
bool normalized;
int count;
idStr type;
idList<double> max;
idList<double> min;
gltfAccessor_Sparse sparse;
idStr name;
idStr extensions;
gltfExtra extras;
uint typeSize;
idList<float>* floatView;
idList<idVec3*>* vecView;
idList<idQuat*>* quatView;
idList<idMat4>* matView;
};
class gltfBufferView
{
public:
gltfBufferView() : buffer( -1 ), byteLength( -1 ), byteStride( 0 ), byteOffset( 0 ), target( -1 ) { };
int buffer;
int byteLength;
int byteStride;
int byteOffset;
int target;
idStr name;
idStr extensions;
gltfExtra extras;
//
gltfData* parent;
};
class gltfBuffer
{
public:
gltfBuffer() : byteLength( -1 ), parent( nullptr ) { };
idStr uri;
int byteLength;
idStr name;
idStr extensions;
gltfExtra extras;
//
gltfData* parent;
};
class gltfSampler
{
public:
gltfSampler() : magFilter( 0 ), minFilter( 0 ), wrapS( 10497 ), wrapT( 10497 ) { };
int magFilter;
int minFilter;
int wrapS;
int wrapT;
idStr name;
idStr extensions;
gltfExtra extras;
//
uint bgfxSamplerFlags;
};
class gltfImage
{
public:
gltfImage() : bufferView( -1 ) { }
idStr uri;
idStr mimeType;
int bufferView;
idStr name;
idStr extensions;
gltfExtra extras;
};
class gltfSkin
{
public:
gltfSkin() : inverseBindMatrices( -1 ), skeleton( -1 ), name( "unnamedSkin" ) { };
int inverseBindMatrices;
int skeleton; // node ID
idList<int> joints; // integer[1,*]
idStr name;
idStr extensions;
gltfExtra extras;
};
class gltfExt_KHR_texture_transform;
class gltfTexture_Info_Extensions
{
public:
gltfTexture_Info_Extensions() :
KHR_texture_transform( nullptr ) { }
gltfExt_KHR_texture_transform* KHR_texture_transform;
};
class gltfOcclusionTexture_Info
{
public:
gltfOcclusionTexture_Info() : index( -1 ), texCoord( 0 ), strength( 1.0f ) { }
int index;
int texCoord;
float strength;
gltfTexture_Info_Extensions extensions;
gltfExtra extras;
};
class gltfNormalTexture_Info
{
public:
gltfNormalTexture_Info() : index( -1 ), texCoord( 0 ), scale( 1.0f ) { }
int index;
int texCoord;
float scale;
gltfTexture_Info_Extensions extensions;
gltfExtra extras;
};
class gltfTexture_Info
{
public:
gltfTexture_Info() : index( -1 ), texCoord( 0 ) { }
int index;
int texCoord;
gltfTexture_Info_Extensions extensions;
gltfExtra extras;
};
class gltfTexture
{
public:
gltfTexture() : sampler( -1 ), source( -1 ) { }
int sampler;
int source;
idStr name;
gltfTexture_Info_Extensions extensions;
gltfExtra extras;
};
class gltfMaterial_pbrMetallicRoughness
{
public:
gltfMaterial_pbrMetallicRoughness() : baseColorFactor( vec4_one ), metallicFactor( 1.0f ), roughnessFactor( 1.0f ) { }
idVec4 baseColorFactor;
gltfTexture_Info baseColorTexture;
float metallicFactor;
float roughnessFactor;
gltfTexture_Info metallicRoughnessTexture;
idStr extensions;
gltfExtra extras;
};
class gltfMaterial
{
public:
enum gltfAlphaMode
{
gltfOPAQUE,
gltfMASK,
gltfBLEND,
count
};
gltfMaterial() : emissiveFactor( vec3_zero ), alphaMode( "OPAQUE" ), alphaCutoff( 0.5f ), doubleSided( false ) { }
gltfMaterial_pbrMetallicRoughness pbrMetallicRoughness;
gltfNormalTexture_Info normalTexture;
gltfOcclusionTexture_Info occlusionTexture;
gltfTexture_Info emissiveTexture;
idVec3 emissiveFactor;
idStr alphaMode;
float alphaCutoff;
bool doubleSided;
idStr name;
gltfMaterial_Extensions extensions;
gltfExtra extras;
gltfAlphaMode intType;
static gltfAlphaMode resolveAlphaMode( idStr type )
{
if( type == "OPAQUE" )
{
return gltfAlphaMode::gltfOPAQUE;
}
else if( type == "MASK" )
{
return gltfAlphaMode::gltfMASK;
}
else if( type == "BLEND" )
{
return gltfAlphaMode::gltfBLEND;
}
return gltfAlphaMode::count;
}
};
class gltfAsset
{
public:
gltfAsset() { }
idStr copyright;
idStr generator;
idStr version;
idStr minVersion;
idStr extensions;
gltfExtra extras;
};
//this is not used.
//if an extension is found, it _will_ be used. (if implemented)
class gltfExtensionsUsed
{
public:
gltfExtensionsUsed() { }
idStr extension;
};
//ARCHIVED?
//https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
class gltfExt_KHR_materials_pbrSpecularGlossiness
{
public:
gltfExt_KHR_materials_pbrSpecularGlossiness() { }
idVec4 diffuseFactor;
gltfTexture_Info diffuseTexture;
idVec3 specularFactor;
float glossinessFactor;
gltfTexture_Info specularGlossinessTexture;
idStr extensions;
gltfExtra extras;
};
//KHR_lights_punctual_spot
//https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual/schema/light.spot.schema.json
class gltfExt_KHR_lights_punctual_spot
{
public:
gltfExt_KHR_lights_punctual_spot() : innerConeAngle( 0.0f ), outerConeAngle( idMath::ONEFOURTH_PI ) { }
float innerConeAngle;
float outerConeAngle;
idStr extensions;
gltfExtra extras;
};
//KHR_lights_punctual
//https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual/schema/light.schema.json
class gltfExt_KHR_lights_punctual
{
public:
enum Type
{
Directional,
Point,
Spot,
count
};
gltfExt_KHR_lights_punctual() : color( vec3_one ), intensity( 1.0f ), range( -1.0f ), intType( -1 ) { }
idVec3 color;
float intensity;
gltfExt_KHR_lights_punctual_spot spot;
idStr type; //directional=0,point=1,spot=2
float range;
idStr name;
idStr extensions;
gltfExtra extras;
int intType;
static Type resolveType( idStr type )
{
if( type == "directional" )
{
return Type::Directional;
}
else if( type == "point" )
{
return Type::Point;
}
else if( type == "spot" )
{
return Type::Spot;
}
return Type::count;
}
};
//KHR_texture_transform
//https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_transform/schema/KHR_texture_transform.textureInfo.schema.json
class gltfExt_KHR_texture_transform
{
public:
gltfExt_KHR_texture_transform() : offset( vec2_zero ), rotation( 0.0f ), scale( vec2_one ), texCoord( -1 ), index( 0 ), resolved( false ) { }
idVec2 offset;
float rotation;
idVec2 scale;
int texCoord;
idStr extensions;
gltfExtra extras;
//for shader
uint index;
bool resolved;
};
/////////////////////////////////////////////////////////////////////////////
//// For these to function you need to add an private idList<gltf{name}*> {target}
//#define GLTFCACHEITEM(name,target) \
//gltf##name * name () { target.AssureSizeAlloc( target.Num()+1,idListNewElement<gltf##name>); return target[target.Num()-1];} \
//const inline idList<gltf##name*> & ##name##List() { return target; }
// URI's are resolved during parsing so that
// all data should be layed out like an GLB with multiple bin chunks
// EACH URI will have an unique chunk
// JSON chunk MUST be the first one to be allocated/added
class gltfData
{
public:
gltfData() : fileName( "" ), fileNameHash( 0 ), json( nullptr ), data( nullptr ), totalChunks( -1 ) { };
~gltfData();
byte* AddData( int size, int* bufferID = nullptr );
byte* GetJsonData( int& size )
{
size = jsonDataLength;
return json;
}
byte* GetData( int index )
{
return data[index];
}
void FileName( const idStr& file, int hash )
{
fileName = file;
fileNameHash = hash;
}
int FileNameHash()
{
return fileNameHash;
}
idStr& FileName()
{
return fileName;
}
static idHashIndex fileDataHash;
static idList<gltfData*> dataList;
//add data for filename
static gltfData* Data( idStr& fileName, bool create = false )
{
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( 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..)
//This is determined by checking for an "_Orientation" suffix to the camera name of the node that has the target camera assigned.
// if so, translate node will be set to the parent node of the orientation node.
//Note: does not take overides into account!
gltfNode* GetCameraNodes( gltfCamera* camera )
{
gltfCameraNodePtrs result;
assert( camera );
int camId = -1;
for( auto* cam : cameras )
{
camId++;
if( cam == camera )
{
break;
}
}
for( int i = 0; i < nodes.Num(); i++ )
{
if( nodes[i]->camera != -1 && nodes[i]->camera == camId )
{
return nodes[i];
}
}
return nullptr;
}
gltfNode* GetNode( gltfScene* scene , gltfMesh* mesh , int* id = nullptr )
{
assert( scene );
assert( mesh );
auto& nodeList = scene->nodes;
for( gltfMesh* meshIt : meshes )
{
if( meshIt != mesh )
{
continue;
}
int nodeCnt = 0;
for( auto& nodeId : nodeList )
{
if( nodes[nodeId]->mesh != -1 && meshes[nodes[nodeId]->mesh] == meshIt )
{
if( id != nullptr )
{
*id = nodeCnt;
}
return nodes[nodeId];
}
nodeCnt++;
}
}
return nullptr;
}
gltfNode* GetNode( const idStr& sceneName, int id, idStr* name = nullptr )
{
int sceneId = GetSceneId( sceneName );
if( sceneId < 0 || sceneId > scenes.Num() )
{
return nullptr;
}
gltfScene* scene = scenes[sceneId];
assert( scene );
assert( id >= 0 );
auto& nodeList = scene->nodes;
for( auto& nodeId : nodeList )
{
if( nodeId == id )
{
if( name != nullptr )
{
*name = nodes[nodeId]->name;
}
return nodes[nodeId];
}
}
return nullptr;
}
gltfNode* GetNode( const 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* GetMeshNode( const idStr& meshName, int* id = nullptr, bool caseSensitive = false )
{
int nodeCnt = 0;
for( auto* node : nodes )
{
if( node->mesh != -1 &&
( caseSensitive ? node->name.Cmp( meshName ) : node->name.Icmp( meshName ) ) == 0 )
{
if( id != nullptr )
{
*id = nodeCnt;
}
return node;
}
nodeCnt++;
}
return nullptr;
}
gltfNode* GetNode( const idStr& sceneName, const idStr& name , int* id = nullptr , bool caseSensitive = false )
{
int sceneId = GetSceneId( sceneName );
if( sceneId < 0 || sceneId > scenes.Num() )
{
return nullptr;
}
gltfScene* scene = scenes[sceneId];
assert( scene );
assert( name[0] );
auto& nodeList = scene->nodes;
for( auto nodeId : nodeList )
{
if( caseSensitive ? nodes[nodeId]->name.Cmp( name ) : nodes[nodeId]->name.Icmp( name ) == 0 )
{
if( id != nullptr )
{
*id = nodeId;
}
return nodes[nodeId];
}
}
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 )
{
for( auto channel : anim->channels )
{
if( channel->target.node == nodeID )
{
return true;
}
}
}
return false;
}
gltfAnimation* GetAnimation( const idStr& animName )
{
for( auto* anim : animations )
{
if( anim->name == animName )
{
return anim;
}
}
return nullptr;
}
gltfAnimation* GetAnimation( const 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( const 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.AddUnique( GetNodeIndex( node ) );
}
for( auto child : node->children )
{
GetAllMeshes( nodes[child], meshIds );
}
}
void GetAllMeshes( idList<int>& meshIds )
{
for( int i = 0; i < nodes.Num(); i++ )
{
auto* node = nodes[i];
if( node->mesh != -1 )
{
meshIds.AddUnique( i );
}
}
}
void GetAllSkinnedMeshes( gltfNode* node, idList<int>& meshIds )
{
if( node->mesh != -1 && node->skin != -1 )
{
meshIds.AddUnique( GetNodeIndex( node ) );
}
for( auto child : node->children )
{
GetAllSkinnedMeshes( nodes[child], meshIds );
}
}
void GetAllSkinnedMeshes( gltfSkin* skin, idList<int>& meshIds )
{
for( int i = 0; i < nodes.Num(); i++ )
{
auto* node = nodes[i];
if( node->mesh != -1 && node->skin != -1 )
{
gltfSkin* meshSkin = skins[node->skin];
if( meshSkin == skin )
{
meshIds.AddUnique( i );
}
}
}
}
void GetAllSkinnedMeshes( idList<int>& meshIds )
{
for( int i = 0; i < nodes.Num(); i++ )
{
auto* node = nodes[i];
if( node->mesh != -1 && node->skin != -1 )
{
meshIds.AddUnique( i );
}
}
}
gltfSkin* GetSkin( const idStr& name )
{
for( auto skin : skins )
{
if( skin->name == name )
{
return skin;
}
}
return nullptr;
}
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 );
break;
}
}
animIdx++;
}
for( int nodeId : node->children )
{
GetAnimationIds( nodes[nodeId], result );
}
return result.Num();
}
idMat4 GetViewMatrix( int camId ) const
{
//if (cameraManager->HasOverideID(camId) )
//{
// auto overrideCam = cameraManager->GetOverride( camId );
// camId = overrideCam.newCameraID;
//}
idMat4 result = mat4_identity;
idList<gltfNode*> hierachy( 2 );
gltfNode* parent = nullptr;
for( int i = 0; i < nodes.Num(); i++ )
{
if( nodes[i]->camera != -1 && nodes[i]->camera == camId )
{
parent = nodes[i];
while( parent )
{
hierachy.Append( parent );
parent = parent->parent;
}
break;
}
}
for( int i = hierachy.Num() - 1; i >= 0; i-- )
{
ResolveNodeMatrix( hierachy[i] );
result *= hierachy[i]->matrix;
}
return result;
}
// Please note : assumes all nodes are _not_ dirty!
idMat4 GetLightMatrix( int lightId ) const
{
idMat4 result = mat4_identity;
idList<gltfNode*> hierachy;
gltfNode* parent = nullptr;
hierachy.SetGranularity( 2 );
for( int i = 0; i < nodes.Num(); i++ )
{
if( nodes[i]->extensions.KHR_lights_punctual && nodes[i]->extensions.KHR_lights_punctual->light == lightId )
{
parent = nodes[i];
while( parent )
{
hierachy.Append( parent );
parent = parent->parent;
}
break;
}
}
for( int i = hierachy.Num() - 1; i >= 0; i-- )
{
result *= hierachy[i]->matrix;
}
return result;
}
// v * T * R * S. ->row major
// v' = S * R * T * v -> column major;
//bgfx = column-major
//idmath = row major, except mat3
//gltf matrices : column-major.
//if mat* is valid , it will be multplied by this node's matrix that is resolved in its full hiararchy and stops at root.
static void ResolveNodeMatrix( gltfNode* node, idMat4* mat = nullptr, gltfNode* root = nullptr )
{
if( node->dirty )
{
idMat4 scaleMat = idMat4(
node->scale.x, 0, 0, 0,
0, node->scale.y, 0, 0,
0, 0, node->scale.z, 0,
0, 0, 0, 1
);
node->matrix = idMat4( mat3_identity, node->translation ) * node->rotation.ToMat4().Transpose() * scaleMat;
node->dirty = false;
}
// resolve full hierarchy
if( mat != nullptr )
{
// collect hierarchy upwards
idList<gltfNode*> hierachy( 2 );
gltfNode* parent = node;
while( parent )
{
ResolveNodeMatrix( parent );
hierachy.Append( parent );
if( parent == root )
{
break;
}
parent = parent->parent;
}
// build world transform from up to down
for( int i = hierachy.Num() - 1; i >= 0; i-- )
{
*mat *= hierachy[i]->matrix;
}
}
}
//void Advance( gltfAnimation* anim = nullptr );
//this copies the data and view cached on the accessor
template <class T>
idList<T*>& GetAccessorView( gltfAccessor* accessor );
idList<float>& GetAccessorView( gltfAccessor* accessor );
idList<idMat4>& GetAccessorViewMat( gltfAccessor* accessor );
int& DefaultScene()
{
return scene;
}
//#define GLTFCACHEITEM(name,target) \
//gltf##name * name () { target.AssureSizeAlloc( target.Num()+1,idListNewElement<gltf##name>); return target[target.Num()-1];} \
//const inline idList<gltf##name*> & ##name##List() { return target; }
gltfBuffer* Buffer()
{
buffers.AssureSizeAlloc( buffers.Num() + 1 , idListNewElement<gltfBuffer> );
return buffers[buffers.Num() - 1];
}
const inline idList<gltfBuffer*>& BufferList()
{
return buffers;
}
gltfSampler* Sampler()
{
samplers.AssureSizeAlloc( samplers.Num() + 1 , idListNewElement<gltfSampler> );
return samplers[samplers.Num() - 1];
}
const inline idList<gltfSampler*>& SamplerList()
{
return samplers;
}
gltfBufferView* BufferView()
{
bufferViews.AssureSizeAlloc( bufferViews.Num() + 1 , idListNewElement<gltfBufferView> );
return bufferViews[bufferViews.Num() - 1];
}
const inline idList<gltfBufferView*>& BufferViewList()
{
return bufferViews;
}
gltfImage* Image()
{
images.AssureSizeAlloc( images.Num() + 1 , idListNewElement<gltfImage> );
return images[images.Num() - 1];
}
const inline idList<gltfImage*>& ImageList()
{
return images;
}
gltfTexture* Texture()
{
textures.AssureSizeAlloc( textures.Num() + 1 , idListNewElement<gltfTexture> );
return textures[textures.Num() - 1];
}
const inline idList<gltfTexture*>& TextureList()
{
return textures;
}
gltfAccessor* Accessor()
{
accessors.AssureSizeAlloc( accessors.Num() + 1 , idListNewElement<gltfAccessor> );
return accessors[accessors.Num() - 1];
}
const inline idList<gltfAccessor*>& AccessorList()
{
return accessors;
}
gltfExtensionsUsed* ExtensionsUsed()
{
extensionsUsed.AssureSizeAlloc( accessors.Num() + 1 , idListNewElement<gltfExtensionsUsed> );
return extensionsUsed[extensionsUsed.Num() - 1];
}
const inline idList<gltfExtensionsUsed*>& ExtensionsUsedList()
{
return extensionsUsed;
}
gltfMesh* Mesh()
{
meshes.AssureSizeAlloc( meshes.Num() + 1 , idListNewElement<gltfMesh> );
return meshes[meshes.Num() - 1];
}
const inline idList<gltfMesh*>& MeshList()
{
return meshes;
}
gltfScene* Scene()
{
scenes.AssureSizeAlloc( scenes.Num() + 1 , idListNewElement<gltfScene> );
return scenes[scenes.Num() - 1];
}
const inline idList<gltfScene*>& SceneList()
{
return scenes;
}
gltfNode* Node()
{
nodes.AssureSizeAlloc( nodes.Num() + 1 , idListNewElement<gltfNode> );
return nodes[nodes.Num() - 1];
}
const inline idList<gltfNode*>& NodeList()
{
return nodes;
}
gltfCamera* Camera()
{
cameras.AssureSizeAlloc( cameras.Num() + 1 , idListNewElement<gltfCamera> );
return cameras[cameras.Num() - 1];
}
const inline idList<gltfCamera*>& CameraList()
{
return cameras;
}
gltfMaterial* Material()
{
materials.AssureSizeAlloc( materials.Num() + 1 , idListNewElement<gltfMaterial> );
return materials[materials.Num() - 1];
}
const inline idList<gltfMaterial*>& MaterialList()
{
return materials;
}
gltfExtensions* Extensions()
{
extensions.AssureSizeAlloc( extensions.Num() + 1 , idListNewElement<gltfExtensions> );
return extensions[extensions.Num() - 1];
}
const inline idList<gltfExtensions*>& ExtensionsList()
{
return extensions;
}
gltfAnimation* Animation()
{
animations.AssureSizeAlloc( animations.Num() + 1 , idListNewElement<gltfAnimation> );
return animations[animations.Num() - 1];
}
const inline idList<gltfAnimation*>& AnimationList()
{
return animations;
}
gltfSkin* Skin()
{
skins.AssureSizeAlloc( skins.Num() + 1 , idListNewElement<gltfSkin> );
return skins[skins.Num() - 1];
}
const inline idList<gltfSkin*>& SkinList()
{
return skins;
}
/*
GLTFCACHEITEM( Buffer, buffers )
GLTFCACHEITEM( Sampler, samplers )
GLTFCACHEITEM( BufferView, bufferViews )
GLTFCACHEITEM( Image, images )
GLTFCACHEITEM( Texture, textures )
GLTFCACHEITEM( Accessor, accessors )
GLTFCACHEITEM( ExtensionsUsed, extensionsUsed )
GLTFCACHEITEM( Mesh, meshes )
GLTFCACHEITEM( Scene, scenes )
GLTFCACHEITEM( Node, nodes )
GLTFCACHEITEM( Camera, cameras )
GLTFCACHEITEM( Material, materials )
GLTFCACHEITEM( Extensions, extensions )
GLTFCACHEITEM( Animation, animations )
GLTFCACHEITEM( Skin, skins )
*/
//gltfCameraManager * cameraManager;
private:
idStr fileName;
int fileNameHash;
byte* json;
byte** data;
int jsonDataLength;
int totalChunks;
idList<gltfBuffer*> buffers;
idList<gltfImage*> images;
idList<gltfData*> assetData;
idList<gltfSampler*> samplers;
idList<gltfBufferView*> bufferViews;
idList<gltfTexture*> textures;
idList<gltfAccessor*> accessors;
idList<gltfExtensionsUsed*> extensionsUsed;
idList<gltfMesh*> meshes;
int scene;
idList<gltfScene*> scenes;
idList<gltfNode*> nodes;
idList<gltfCamera*> cameras;
idList<gltfMaterial*> materials;
idList<gltfExtensions*> extensions;
idList<gltfAnimation*> animations;
idList<gltfSkin*> skins;
};
#undef GLTFCACHEITEM