mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-15 07:00:58 +00:00
+ id style gltf2 parser
+ initial attempt to dmap glb/gltf [!] added blend file and glb for debugging purposes
This commit is contained in:
parent
e6caee4cae
commit
331d14567d
20 changed files with 3888 additions and 54 deletions
BIN
base/physics_test.blend
Normal file
BIN
base/physics_test.blend
Normal file
Binary file not shown.
BIN
base/physics_test.glb
Normal file
BIN
base/physics_test.glb
Normal file
Binary file not shown.
|
@ -243,7 +243,7 @@ ID_INLINE void idCmdSystem::ArgCompletion_FileName( const idCmdArgs& args, void(
|
|||
|
||||
ID_INLINE void idCmdSystem::ArgCompletion_MapName( const idCmdArgs& args, void( *callback )( const char* s ) )
|
||||
{
|
||||
cmdSystem->ArgCompletion_FolderExtension( args, callback, "maps/", true, ".map", ".json", NULL );
|
||||
cmdSystem->ArgCompletion_FolderExtension( args, callback, "maps/", true, ".map", ".json",".gltf",".glb", NULL );
|
||||
}
|
||||
|
||||
ID_INLINE void idCmdSystem::ArgCompletion_MapNameNoJson( const idCmdArgs& args, void( *callback )( const char* s ) )
|
||||
|
|
|
@ -1507,31 +1507,31 @@ Skips until a matching close brace is found.
|
|||
Internal brace depths are properly skipped.
|
||||
=================
|
||||
*/
|
||||
int idLexer::SkipBracedSection( bool parseFirstBrace )
|
||||
{
|
||||
int idLexer::SkipBracedSection( bool parseFirstBrace, braceSkipMode_t skipMode/* = BRSKIP_BRACE */, int * skipped /*= nullptr*/) {
|
||||
idToken token;
|
||||
int depth;
|
||||
idStr openTokens[2] = { "{" , "[" };
|
||||
idStr closeTokens[2] = { "}" , "]" };
|
||||
|
||||
if ( skipped != nullptr )
|
||||
*skipped = 0;
|
||||
|
||||
int scopeCount = 0;
|
||||
depth = parseFirstBrace ? 0 : 1;
|
||||
do
|
||||
{
|
||||
if( !ReadToken( &token ) )
|
||||
{
|
||||
do {
|
||||
if ( !ReadToken( &token ) ) {
|
||||
return false;
|
||||
}
|
||||
if( token.type == TT_PUNCTUATION )
|
||||
{
|
||||
if( token == "{" )
|
||||
{
|
||||
if ( token.type == TT_PUNCTUATION ) {
|
||||
if ( token == openTokens[skipMode] ) {
|
||||
depth++;
|
||||
}
|
||||
else if( token == "}" )
|
||||
{
|
||||
if ( skipped != nullptr )
|
||||
(*skipped)++;
|
||||
} else if ( token == closeTokens[skipMode] ) {
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( depth );
|
||||
} while( depth );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2083,8 +2083,9 @@ void idLexer::Reset()
|
|||
// set if there's a token available in idLexer::token
|
||||
idLexer::tokenavailable = 0;
|
||||
|
||||
idLexer::line = 1;
|
||||
idLexer::lastline = 1;
|
||||
idLexer::line = intialLine;
|
||||
idLexer::lastline = intialLine;
|
||||
|
||||
// clear the saved token
|
||||
idLexer::token = "";
|
||||
}
|
||||
|
@ -2166,6 +2167,7 @@ int idLexer::LoadFile( const char* filename, bool OSPath )
|
|||
|
||||
idLexer::tokenavailable = 0;
|
||||
idLexer::line = 1;
|
||||
idLexer::line = 1;
|
||||
idLexer::lastline = 1;
|
||||
idLexer::allocated = true;
|
||||
idLexer::loaded = true;
|
||||
|
@ -2199,6 +2201,7 @@ int idLexer::LoadMemory( const char* ptr, int length, const char* name, int star
|
|||
idLexer::tokenavailable = 0;
|
||||
idLexer::line = startLine;
|
||||
idLexer::lastline = startLine;
|
||||
idLexer::intialLine = startLine;
|
||||
idLexer::allocated = false;
|
||||
idLexer::loaded = true;
|
||||
|
||||
|
|
|
@ -64,6 +64,12 @@ typedef enum
|
|||
LEXFL_ONLYSTRINGS = BIT( 13 ) // parse as whitespace deliminated strings (quoted strings keep quotes)
|
||||
} lexerFlags_t;
|
||||
|
||||
typedef enum {
|
||||
BRSKIP_BRACES,
|
||||
BRSKIP_BRACKET
|
||||
} braceSkipMode_t;
|
||||
|
||||
|
||||
// punctuation ids
|
||||
#define P_RSHIFT_ASSIGN 1
|
||||
#define P_LSHIFT_ASSIGN 2
|
||||
|
@ -182,7 +188,7 @@ public:
|
|||
// skip the rest of the current line
|
||||
int SkipRestOfLine();
|
||||
// skip the braced section
|
||||
int SkipBracedSection( bool parseFirstBrace = true );
|
||||
int SkipBracedSection( bool parseFirstBrace = true , braceSkipMode_t skipMode = BRSKIP_BRACES,int * skipped = nullptr);
|
||||
// skips spaces, tabs, C-like comments etc. Returns false if there is no token left to read.
|
||||
bool SkipWhiteSpace( bool currentLine );
|
||||
// unread the given token
|
||||
|
@ -267,6 +273,7 @@ private:
|
|||
int length; // length of the script in bytes
|
||||
int line; // current line in script
|
||||
int lastline; // line before reading token
|
||||
int intialLine; // line that was set on load as starting line
|
||||
int tokenavailable; // set by unreadToken
|
||||
int flags; // several script flags
|
||||
const punctuation_t* punctuations; // the punctuations used in the script
|
||||
|
|
|
@ -1553,6 +1553,7 @@ bool idMapFile::Parse( const char* filename, bool ignoreRegion, bool osPath )
|
|||
idMapEntity* mapEnt;
|
||||
int i, j, k;
|
||||
|
||||
idStr extension;
|
||||
name = filename;
|
||||
name.StripFileExtension();
|
||||
name.StripFileExtension(); // RB: there might be .map.map
|
||||
|
@ -1572,6 +1573,18 @@ bool idMapFile::Parse( const char* filename, bool ignoreRegion, bool osPath )
|
|||
}
|
||||
}
|
||||
|
||||
bool isGTLF = false;
|
||||
if ( !src.IsLoaded( ) ) {
|
||||
// HVG: try loading a .gltf/glb second
|
||||
fullName.SetFileExtension( "glb" );
|
||||
isGTLF = src.LoadFile( fullName, osPath );
|
||||
if ( !isGTLF )
|
||||
{
|
||||
fullName.SetFileExtension( "gltf" );
|
||||
isGTLF = src.LoadFile( fullName, osPath );
|
||||
}
|
||||
}
|
||||
|
||||
if( !src.IsLoaded() )
|
||||
{
|
||||
// now try a .map file
|
||||
|
@ -1588,17 +1601,11 @@ bool idMapFile::Parse( const char* filename, bool ignoreRegion, bool osPath )
|
|||
fileTime = src.GetFileTime();
|
||||
entities.DeleteContents( true );
|
||||
|
||||
if( !src.ReadToken( &token ) )
|
||||
if(!isGTLF && !src.ReadToken( &token ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// RB: TODO check for JSON in another way
|
||||
//if( token == "{" )
|
||||
//{
|
||||
// isJSON = true;
|
||||
//}
|
||||
|
||||
if( isJSON )
|
||||
{
|
||||
while( true )
|
||||
|
@ -1661,7 +1668,11 @@ bool idMapFile::Parse( const char* filename, bool ignoreRegion, bool osPath )
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if ( isGTLF )
|
||||
{
|
||||
gltfParser->Load( fullName );
|
||||
idMapEntity::GetEntities(gltfParser->currentAsset,entities,0);
|
||||
}else
|
||||
{
|
||||
if( token == "Version" )
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#ifndef __MAPFILE_H__
|
||||
#define __MAPFILE_H__
|
||||
#include "gltfProperties.h"
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
@ -348,7 +349,7 @@ public:
|
|||
|
||||
void ConvertFromBrush( const idMapBrush* brush, int entityNum, int primitiveNum );
|
||||
void ConvertFromPatch( const idMapPatch* patch, int entityNum, int primitiveNum );
|
||||
|
||||
void ConvertFromMeshGltf( const gltfMesh * mesh , gltfData * data );
|
||||
static MapPolygonMesh* Parse( idLexer& src, const idVec3& origin, float version = CURRENT_MAP_VERSION );
|
||||
bool Write( idFile* fp, int primitiveNum, const idVec3& origin ) const;
|
||||
|
||||
|
@ -367,6 +368,9 @@ public:
|
|||
return verts.Append( v );
|
||||
}
|
||||
|
||||
int AddVertices( const idList<idDrawVert> &v ) {
|
||||
return verts.Append( v );
|
||||
}
|
||||
|
||||
int GetNumPolygons() const
|
||||
{
|
||||
|
@ -422,6 +426,10 @@ protected:
|
|||
|
||||
class idMapEntity
|
||||
{
|
||||
typedef idList<idMapEntity *, TAG_IDLIB_LIST_MAP> EntityList;
|
||||
typedef idList<idMapEntity *, TAG_IDLIB_LIST_MAP> &EntityListRef;
|
||||
typedef idList<idMapEntity *, TAG_IDLIB_LIST_MAP> *EntityListPtr;
|
||||
|
||||
friend class idMapFile;
|
||||
|
||||
public:
|
||||
|
@ -437,8 +445,12 @@ public:
|
|||
{
|
||||
primitives.DeleteContents( true );
|
||||
}
|
||||
// HVG check gltf scene for entities
|
||||
static int GetEntities( gltfData * data, EntityListRef entities, int scene = 0 );
|
||||
static idMapEntity* Parse( idLexer& src, bool worldSpawn = false, float version = CURRENT_MAP_VERSION );
|
||||
bool Write( idFile* fp, int entityNum, bool valve220 ) const;
|
||||
|
||||
// HVG NOTE: this is not compatible with gltf (extra) json!
|
||||
// RB begin
|
||||
static idMapEntity* ParseJSON( idLexer& src );
|
||||
bool WriteJSON( idFile* fp, int entityNum, int numEntities ) const;
|
||||
|
@ -538,7 +550,7 @@ protected:
|
|||
float version;
|
||||
ID_TIME_T fileTime;
|
||||
unsigned int geometryCRC;
|
||||
idList<idMapEntity*, TAG_IDLIB_LIST_MAP> entities;
|
||||
idMapEntity::EntityList entities;
|
||||
idStr name;
|
||||
bool hasPrimitiveData;
|
||||
bool valve220Format; // RB: for TrenchBroom support
|
||||
|
|
|
@ -203,29 +203,21 @@ public:
|
|||
memTag = ( byte )tag_;
|
||||
};
|
||||
|
||||
// Begin/End methods for range-based for loops.
|
||||
_type_* begin()
|
||||
{
|
||||
if( num > 0 )
|
||||
{
|
||||
return &list[0];
|
||||
struct Iterator {
|
||||
_type_ *p;
|
||||
_type_ &operator*( ) { return *p; }
|
||||
bool operator != ( const Iterator &rhs ) {
|
||||
return p != rhs.p;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
_type_* end()
|
||||
{
|
||||
if( num > 0 )
|
||||
{
|
||||
return &list[num - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
void operator ++( ) { ++p; }
|
||||
};
|
||||
|
||||
auto begin( ) const { // const version
|
||||
return Iterator{list};
|
||||
};
|
||||
auto end( ) const { // const version
|
||||
return Iterator{list + Num( )};
|
||||
};
|
||||
|
||||
private:
|
||||
int num;
|
||||
|
|
35
neo/idlib/gltfExtras.cpp
Normal file
35
neo/idlib/gltfExtras.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
#include "gltfExtras.h"
|
||||
|
||||
extern idCVar gltf_parseVerbose;
|
||||
|
||||
void gltfExtra_Scatter::parse( idToken &token, idLexer * parser ) {
|
||||
|
||||
parser->UnreadToken( &token );
|
||||
|
||||
gltfItemArray scatterInfo;
|
||||
GLTFARRAYITEM( scatterInfo, emitter, gltfObject );
|
||||
scatterInfo.Parse( parser,true );
|
||||
}
|
||||
|
||||
void gltfExtra_cvar::parse( idToken &token, idLexer *parser ) {
|
||||
|
||||
parser->UnreadToken( &token );
|
||||
gltfItemArray cvarInfo;
|
||||
idStr n,t,v,d;
|
||||
GLTFARRAYITEMREF( cvarInfo, name, gltfItem , n);
|
||||
GLTFARRAYITEMREF( cvarInfo, type, gltfItem , t);
|
||||
GLTFARRAYITEMREF( cvarInfo, value, gltfItem, v );
|
||||
GLTFARRAYITEMREF( cvarInfo, desc, gltfItem , d);
|
||||
int total = cvarInfo.Parse( parser );
|
||||
assert( total == 3 );
|
||||
idCVar * gltExtra_cvar = new idCVar(
|
||||
n.c_str(),
|
||||
v.c_str(),
|
||||
CVAR_SYSTEM | CVAR_BOOL,
|
||||
d.c_str()
|
||||
);
|
||||
|
||||
cvarSystem->Register(gltExtra_cvar);
|
||||
}
|
35
neo/idlib/gltfExtras.h
Normal file
35
neo/idlib/gltfExtras.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include "gltfParser.h"
|
||||
|
||||
#ifndef gltfExtraParser
|
||||
#define gltfExtraParser(className,ptype) \
|
||||
class gltfExtra_##className : public parsable, public parseType<ptype> \
|
||||
{public: \
|
||||
gltfExtra_##className( idStr Name ) : name( Name ){ item = nullptr; } \
|
||||
virtual void parse( idToken &token ){parse(token,nullptr);} \
|
||||
virtual void parse( idToken &token , idLexer * parser ); \
|
||||
virtual idStr &Name( ) { return name; } \
|
||||
private: \
|
||||
idStr name;}
|
||||
#pragma endregion
|
||||
#endif
|
||||
|
||||
//Helper macros for gltf data deserialize
|
||||
#define GLTFARRAYITEM(target,name,type) auto * name = new type (#name); target.AddItemDef((parsable*)name)
|
||||
#define GLTFARRAYITEMREF(target,name,type,ref) auto * name = new type (#name); target.AddItemDef((parsable*)name); name->Set(&ref)
|
||||
#ifndef GLTF_EXTRAS_H
|
||||
#define GLTF_EXTRAS_H
|
||||
|
||||
class test {
|
||||
public:
|
||||
test(){ }
|
||||
};
|
||||
|
||||
|
||||
gltfExtraParser( Scatter, test );
|
||||
|
||||
gltfExtraParser( cvar, idCVar );
|
||||
#endif // GLTF_EXTRAS_H
|
||||
|
||||
#ifndef gltfExternalParser
|
||||
#undef gltfExtraParser
|
||||
#endif
|
2111
neo/idlib/gltfParser.cpp
Normal file
2111
neo/idlib/gltfParser.cpp
Normal file
File diff suppressed because it is too large
Load diff
240
neo/idlib/gltfParser.h
Normal file
240
neo/idlib/gltfParser.h
Normal file
|
@ -0,0 +1,240 @@
|
|||
#pragma once
|
||||
#include "containers/StrList.h"
|
||||
#include <functional>
|
||||
#include "gltfProperties.h"
|
||||
|
||||
#pragma region GLTF Types parsing
|
||||
|
||||
#pragma region Parser interfaces
|
||||
struct parsable {
|
||||
public:
|
||||
virtual void parse(idToken & token )=0;
|
||||
virtual void parse(idToken & token , idLexer * parser){};
|
||||
virtual idStr &Name( ) = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class parseType {
|
||||
public:
|
||||
void Set(T * type ) { item = type; }
|
||||
virtual ~parseType() { delete item; }
|
||||
T* item;
|
||||
};
|
||||
|
||||
class gltfItem : public parsable, public parseType<idStr>
|
||||
{
|
||||
public:
|
||||
gltfItem( idStr Name) : name( Name ) { item = nullptr; }
|
||||
virtual void parse( idToken &token ) { *item = token; };
|
||||
virtual idStr &Name( ) {return name;}
|
||||
~gltfItem(){}
|
||||
private:
|
||||
idStr name;
|
||||
};
|
||||
|
||||
class gltfObject : public parsable, public parseType<idStr> {
|
||||
public:
|
||||
gltfObject( idStr Name ) : name( Name ), object("null"){}
|
||||
virtual void parse( idToken &token ) {}
|
||||
virtual void parse(idToken & token , idLexer * parser){
|
||||
parser->UnreadToken( &token );parser->ParseBracedSection( object );
|
||||
}
|
||||
virtual idStr &Name( ) { return name; }
|
||||
private:
|
||||
idStr name;
|
||||
idStr object;
|
||||
};
|
||||
|
||||
class gltfItemArray;
|
||||
class gltfItem_Extra : public parsable, public parseType<gltfExtra> {
|
||||
public:
|
||||
gltfItem_Extra( idStr Name ) : name( Name ), data(nullptr),parser(nullptr) { item = nullptr; }
|
||||
virtual void parse( idToken &token ) ;
|
||||
virtual idStr &Name( ) { return name; }
|
||||
void Set( gltfExtra *type, idLexer *lexer ) { parseType::Set( type ); parser = lexer; }
|
||||
static void Register(parsable * extra);
|
||||
private:
|
||||
idStr name;
|
||||
gltfData *data;
|
||||
idLexer* parser;
|
||||
static gltfItemArray*items;
|
||||
};
|
||||
|
||||
class gltfItem_uri : public parsable, public parseType<idStr> {
|
||||
public:
|
||||
gltfItem_uri( idStr Name ) : name( Name ) { item = nullptr; }
|
||||
virtual void parse( idToken &token ) { *item = token; Convert(); };
|
||||
virtual idStr &Name( ) { return name; }
|
||||
void Set( idStr *type,int * targetBufferview,gltfData* dataDestination ) { parseType::Set(type); bufferView = targetBufferview; data = dataDestination; }
|
||||
// read data from uri file, and push it at end of current data buffer for this GLTF File
|
||||
// bufferView will be set accordingly to the generated buffer.
|
||||
bool Convert( );
|
||||
private:
|
||||
idStr name;
|
||||
int * bufferView;
|
||||
gltfData * data;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region helper macro to define gltf data types with extra parsing context forced to be implemented externally
|
||||
#define gltfItemClassParser(className,ptype) \
|
||||
class gltfItem_##className : public parsable, public parseType<ptype> \
|
||||
{public: \
|
||||
gltfItem_##className( idStr Name ) : name( Name ){ item = nullptr; } \
|
||||
virtual void parse( idToken &token ); \
|
||||
virtual idStr &Name( ) { return name; } \
|
||||
void Set( ptype *type, idLexer *lexer ) { parseType::Set( type ); parser = lexer; } \
|
||||
private: \
|
||||
idStr name; \
|
||||
idLexer *parser;}
|
||||
#pragma endregion
|
||||
|
||||
gltfItemClassParser( animation_sampler, idList<gltfAnimation_Sampler*> );
|
||||
gltfItemClassParser( animation_channel_target, gltfAnimation_Channel_Target );
|
||||
gltfItemClassParser( animation_channel, idList<gltfAnimation_Channel*>);
|
||||
gltfItemClassParser( mesh_primitive, idList<gltfMesh_Primitive *>);
|
||||
gltfItemClassParser( mesh_primitive_attribute, idList<gltfMesh_Primitive_Attribute *> );
|
||||
gltfItemClassParser( integer_array, idList<int>);
|
||||
gltfItemClassParser( number_array, idList<double>);//does float suffice?
|
||||
gltfItemClassParser( mat4, idMat4 );
|
||||
gltfItemClassParser( vec4, idVec4 );
|
||||
gltfItemClassParser( vec3, idVec3 );
|
||||
gltfItemClassParser( vec2, idVec2 );
|
||||
gltfItemClassParser( quat, idQuat );
|
||||
gltfItemClassParser( accessor_sparse, gltfAccessor_Sparse );
|
||||
gltfItemClassParser( accessor_sparse_indices, gltfAccessor_Sparse_Indices );
|
||||
gltfItemClassParser( accessor_sparse_values, gltfAccessor_Sparse_Values );
|
||||
gltfItemClassParser( camera_perspective, gltfCamera_Perspective );
|
||||
gltfItemClassParser( camera_orthographic, gltfCamera_Orthographic );
|
||||
gltfItemClassParser( pbrMetallicRoughness, gltfMaterial_pbrMetallicRoughness );
|
||||
gltfItemClassParser( texture_info, gltfTexture_Info);
|
||||
gltfItemClassParser( normal_texture, gltfNormalTexture_Info);
|
||||
gltfItemClassParser( occlusion_texture, gltfOcclusionTexture_Info );
|
||||
gltfItemClassParser( node_extensions, gltfNode_Extensions );
|
||||
gltfItemClassParser( material_extensions, gltfMaterial_Extensions );
|
||||
gltfItemClassParser( texture_info_extensions, gltfTexture_Info_Extensions );
|
||||
|
||||
//extensions
|
||||
gltfItemClassParser( KHR_lights_punctual, gltfExtensions );
|
||||
gltfItemClassParser( Node_KHR_lights_punctual, gltfNode_Extensions );
|
||||
gltfItemClassParser( Material_KHR_materials_pbrSpecularGlossiness, gltfMaterial_Extensions );
|
||||
gltfItemClassParser( TextureInfo_KHR_texture_transform, gltfTexture_Info_Extensions );
|
||||
|
||||
#undef gltfItemClassParser
|
||||
|
||||
#pragma region helper macro to define more gltf data types that only rely on token
|
||||
#define gltfItemClass(className,type,function) \
|
||||
class gltfItem_##className : public parsable, public parseType<type> \
|
||||
{public: \
|
||||
gltfItem_##className( idStr Name ) : name( Name ){ item = nullptr; } \
|
||||
virtual void parse( idToken &token ) { function } \
|
||||
virtual idStr &Name( ) { return name; } \
|
||||
private: \
|
||||
idStr name;}
|
||||
#pragma endregion
|
||||
|
||||
gltfItemClass(integer, int, *item = token.GetIntValue( ); );
|
||||
gltfItemClass(number, float, *item = token.GetFloatValue( ); );
|
||||
gltfItemClass(boolean, bool, if (token.Icmp("true") == 0 ) *item=true; else{ if(token.Icmp("false") == 0)*item=false; else idLib::FatalError("parse error");});
|
||||
#undef gltfItemClass
|
||||
|
||||
class gltfItemArray
|
||||
{
|
||||
public:
|
||||
~gltfItemArray( ) { items.DeleteContents(true); }
|
||||
gltfItemArray( ) { };
|
||||
int Num() { return items.Num(); }
|
||||
void AddItemDef( parsable *item ) { items.Alloc( ) = item;}
|
||||
int Fill(idLexer * lexer , idDict * strPairs );
|
||||
int Parse(idLexer * lexer , bool forwardLexer = false );
|
||||
template<class T>
|
||||
T* Get(idStr name ){ for ( auto * item : items) if (item->Name() == name) return static_cast<T*>(item); return nullptr; }
|
||||
private:
|
||||
idList<parsable*> items;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region GLTF Object parsing
|
||||
class gltfPropertyArray;
|
||||
class gltfPropertyItem
|
||||
{
|
||||
public:
|
||||
gltfPropertyItem( ) : array(nullptr){ }
|
||||
gltfPropertyArray * array;
|
||||
idToken item;
|
||||
};
|
||||
|
||||
class gltfPropertyArray
|
||||
{
|
||||
public:
|
||||
gltfPropertyArray( idLexer *Parser,bool AoS = true );
|
||||
~gltfPropertyArray( );
|
||||
struct Iterator {
|
||||
gltfPropertyArray * array;
|
||||
gltfPropertyItem *p;
|
||||
gltfPropertyItem &operator*( ) {return *p;}
|
||||
bool operator != ( Iterator &rhs ) {
|
||||
return p != rhs.p;
|
||||
}
|
||||
void operator ++( );
|
||||
};
|
||||
gltfPropertyArray::Iterator begin( );
|
||||
gltfPropertyArray::Iterator end( );
|
||||
private:
|
||||
bool iterating;
|
||||
bool dirty;
|
||||
int index;
|
||||
idLexer * parser;
|
||||
idList<gltfPropertyItem*> properties;
|
||||
gltfPropertyItem * endPtr;
|
||||
bool isArrayOfStructs;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
class GLTF_Parser
|
||||
{
|
||||
public:
|
||||
GLTF_Parser();
|
||||
void Shutdown();
|
||||
bool Parse();
|
||||
bool Load(idStr filename );
|
||||
bool loadGLB(idStr filename );
|
||||
|
||||
//current/last loaded gltf asset and index offsets
|
||||
gltfData *currentAsset;
|
||||
private:
|
||||
void SetNodeParent( gltfNode *node, gltfNode *parent = nullptr );
|
||||
//void CreateBgfxData( );
|
||||
|
||||
void Parse_ASSET( idToken &token );
|
||||
void Parse_CAMERAS( idToken &token );
|
||||
void Parse_SCENE( idToken &token );
|
||||
void Parse_SCENES( idToken &token );
|
||||
void Parse_NODES( idToken &token );
|
||||
void Parse_MATERIALS( idToken &token );
|
||||
void Parse_MESHES( idToken &token );
|
||||
void Parse_TEXTURES( idToken &token );
|
||||
void Parse_IMAGES( idToken &token );
|
||||
void Parse_ACCESSORS( idToken &token );
|
||||
void Parse_BUFFERVIEWS( idToken &token );
|
||||
void Parse_SAMPLERS( idToken &token );
|
||||
void Parse_BUFFERS( idToken &token );
|
||||
void Parse_ANIMATIONS( idToken &token );
|
||||
void Parse_SKINS( idToken &token );
|
||||
void Parse_EXTENSIONS( idToken &token );
|
||||
void Parse_EXTENSIONS_USED( idToken &token );
|
||||
void Parse_EXTENSIONS_REQUIRED( idToken &token );
|
||||
|
||||
|
||||
gltfProperty ParseProp( idToken &token );
|
||||
gltfProperty ResolveProp( idToken &token );
|
||||
|
||||
idLexer parser;
|
||||
idToken token;
|
||||
idStr currentFile;
|
||||
|
||||
bool buffersDone;
|
||||
bool bufferViewsDone;
|
||||
};
|
||||
|
||||
extern GLTF_Parser * gltfParser;
|
838
neo/idlib/gltfProperties.h
Normal file
838
neo/idlib/gltfProperties.h
Normal file
|
@ -0,0 +1,838 @@
|
|||
#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;
|
||||
//specialized parsers
|
||||
idList<gltfExtra *> extras;
|
||||
};
|
||||
|
||||
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 ) { }
|
||||
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,
|
||||
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;}
|
||||
const idVec3 &TotalMovementDelta( void ) const {static idVec3 temp; return temp; }
|
||||
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;
|
||||
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;
|
||||
};
|
||||
typedef gltfExt_KHR_lights_punctual_spot spot;
|
||||
|
||||
//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:
|
||||
gltfExt_KHR_lights_punctual( ) : color(vec3_one),intensity(1.0f),range(-1.0f),intType(-1) { }
|
||||
idVec3 color;
|
||||
float intensity;
|
||||
spot spot;
|
||||
idStr type; //directional=0,point=1,spot=2
|
||||
float range;
|
||||
idStr name;
|
||||
idStr extensions;
|
||||
gltfExtra extras;
|
||||
|
||||
int intType;
|
||||
|
||||
static int resolveType( idStr type ) {
|
||||
if (type == "directional" )
|
||||
return 0;
|
||||
else if (type == "point" )
|
||||
return 1;
|
||||
else if (type == "spot" )
|
||||
return 2;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
//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( ) : 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 ) { fileName = file; fileNameHash = fileDataHash.GenerateKey( file.c_str( ) ); }
|
||||
int FileNameHash( ) { return fileNameHash; }
|
||||
idStr &FileName( ) { return fileName; }
|
||||
|
||||
static idHashIndex fileDataHash;
|
||||
static idList<gltfData *> dataList;
|
||||
//add data from filename
|
||||
static gltfData *Data( idStr &fileName ) {
|
||||
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 const idList<gltfData *> &DataList( ) { return dataList; }
|
||||
static void ClearData( ) { idLib::Warning( "TODO! DATA NOT FREED" ); }
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
idList<gltfNode *> hierachy(2);
|
||||
gltfNode *parent = node;
|
||||
while ( parent ) {
|
||||
ResolveNodeMatrix(parent);
|
||||
hierachy.Append( parent );
|
||||
if ( parent == root )
|
||||
break;
|
||||
parent = parent->parent;
|
||||
}
|
||||
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; }
|
||||
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
|
|
@ -30,6 +30,10 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
idVec2 vec2_one( 1.0f, 1.0f );
|
||||
idVec3 vec3_one( 1.0f, 1.0f, 1.0f );
|
||||
idVec4 vec4_one( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
idVec2 vec2_origin( 0.0f, 0.0f );
|
||||
idVec3 vec3_origin( 0.0f, 0.0f, 0.0f );
|
||||
idVec4 vec4_origin( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
|
|
|
@ -109,6 +109,7 @@ public:
|
|||
|
||||
extern idVec2 vec2_origin;
|
||||
#define vec2_zero vec2_origin
|
||||
extern idVec2 vec2_one;
|
||||
|
||||
ID_INLINE idVec2::idVec2()
|
||||
{
|
||||
|
@ -463,6 +464,7 @@ public:
|
|||
|
||||
extern idVec3 vec3_origin;
|
||||
#define vec3_zero vec3_origin
|
||||
extern idVec3 vec3_one;
|
||||
|
||||
ID_INLINE idVec3::idVec3()
|
||||
{
|
||||
|
@ -1066,6 +1068,7 @@ public:
|
|||
|
||||
extern idVec4 vec4_origin;
|
||||
#define vec4_zero vec4_origin
|
||||
extern idVec4 vec4_one;
|
||||
|
||||
ID_INLINE void idVec4::Set( const float x, const float y, const float z, const float w )
|
||||
{
|
||||
|
|
|
@ -46,6 +46,9 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
// id lib
|
||||
#include "../idlib/Lib.h"
|
||||
#include "../idlib/gltfProperties.h"
|
||||
#include "../idlib/gltfParser.h"
|
||||
|
||||
|
||||
#include "sys/sys_filesystem.h"
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ MEM_TAG( IDLIB_SURFACE )
|
|||
MEM_TAG( IDLIB_WINDING )
|
||||
MEM_TAG( IDLIB_LEXER )
|
||||
MEM_TAG( IDLIB_PARSER )
|
||||
MEM_TAG( IDLIB_GLTF )
|
||||
MEM_TAG( AF )
|
||||
MEM_TAG( COLLISION )
|
||||
MEM_TAG( COLLISION_QUERY )
|
||||
|
|
|
@ -29,7 +29,7 @@ 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
|
||||
|
||||
|
@ -356,9 +356,15 @@ idRenderModel* idRenderModelManagerLocal::GetModel( const char* _modelName, bool
|
|||
// determine which subclass of idRenderModel to initialize
|
||||
|
||||
idRenderModel* model = NULL;
|
||||
|
||||
// HvG: GLTF 2 support
|
||||
if ( (extension.Icmp( GLTF_GLB_EXT ) == 0 ) ||( extension.Icmp( GLTF_EXT ) == 0 ))
|
||||
{
|
||||
model = new( TAG_MODEL ) idRenderModelGLTF;
|
||||
|
||||
// RB: Collada DAE and Wavefront OBJ
|
||||
if( ( extension.Icmp( "dae" ) == 0 ) || ( extension.Icmp( "obj" ) == 0 ) || ( extension.Icmp( "ase" ) == 0 ) || ( extension.Icmp( "lwo" ) == 0 ) || ( extension.Icmp( "flt" ) == 0 ) || ( extension.Icmp( "ma" ) == 0 ) )
|
||||
}else if ( ( extension.Icmp( "dae" ) == 0 ) || ( extension.Icmp( "obj" ) == 0 ) // RB: Collada DAE and Wavefront OBJ
|
||||
|| ( extension.Icmp( "ase" ) == 0 ) || ( extension.Icmp( "lwo" ) == 0 )
|
||||
|| ( extension.Icmp( "flt" ) == 0 ) || ( extension.Icmp( "ma" ) == 0 ) )
|
||||
{
|
||||
model = new( TAG_MODEL ) idRenderModelStatic;
|
||||
}
|
||||
|
|
465
neo/renderer/Model_gltf.cpp
Normal file
465
neo/renderer/Model_gltf.cpp
Normal file
|
@ -0,0 +1,465 @@
|
|||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
|
||||
#include "Model_gltf.h"
|
||||
#include "Model_local.h"
|
||||
|
||||
|
||||
|
||||
bool idRenderModelStatic::ConvertGltfMeshToModelsurfaces( const gltfMesh *mesh ) {
|
||||
|
||||
//for ( auto mesh : currentAsset->MeshList( ) ) {
|
||||
// for ( auto prim : mesh->primitives ) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MapPolygonMesh::ConvertFromMeshGltf( const gltfMesh *_mesh, gltfData *data ) {
|
||||
for ( auto* gltfMesh : data->MeshList( ) ) {
|
||||
for ( auto prim : gltfMesh->primitives ) {
|
||||
common->Printf("primitive for %s\n",gltfMesh->name.c_str() );
|
||||
|
||||
gltfAccessor *accessor = data->AccessorList( )[prim->indices];
|
||||
gltfBufferView *bv = data->BufferViewList( )[accessor->bufferView];
|
||||
gltfData *data = bv->parent;
|
||||
|
||||
gltfBuffer *buff = data->BufferList( )[bv->buffer];
|
||||
uint idxDataSize = sizeof( uint ) * accessor->count;
|
||||
uint *indices = ( uint * ) Mem_ClearedAlloc( idxDataSize , TAG_IDLIB_GLTF);
|
||||
|
||||
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 );
|
||||
if ( bv->byteStride )
|
||||
idxBin.Seek( bv->byteStride - accessor->typeSize, FS_SEEK_CUR );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < accessor->count; i+=3 ) {
|
||||
MapPolygon &polygon = polygons.Alloc( );
|
||||
polygon.SetMaterial( "textures/base_wall/lfwall27d" );
|
||||
polygon.AddIndex( indices[i + 1] );
|
||||
polygon.AddIndex( indices[i + 2] );
|
||||
polygon.AddIndex( indices[i + 0] );
|
||||
}
|
||||
|
||||
Mem_Free( indices );
|
||||
bool sizeSet = false;
|
||||
|
||||
for ( auto &attrib : prim->attributes ) {
|
||||
gltfAccessor *attrAcc = data->AccessorList( )[attrib->accessorIndex];
|
||||
gltfBufferView *attrBv = data->BufferViewList( )[attrAcc->bufferView];
|
||||
gltfData *attrData = attrBv->parent;
|
||||
gltfBuffer *attrbuff = attrData->BufferList( )[attrBv->buffer];
|
||||
|
||||
idFile_Memory bin = idFile_Memory( "gltfChunkVertices",
|
||||
( const char * ) ( ( attrData->GetData( attrBv->buffer ) + attrBv->byteOffset + attrAcc->byteOffset ) ), attrBv->byteLength );
|
||||
|
||||
if ( !sizeSet )
|
||||
{
|
||||
verts.AssureSize( attrAcc->count );
|
||||
sizeSet = true;
|
||||
}
|
||||
|
||||
switch ( attrib->type ) {
|
||||
case gltfMesh_Primitive_Attribute::Type::Position:
|
||||
{
|
||||
for ( int i = attrAcc->count-1; i >= 0; i-- ) {
|
||||
bin.Read( ( void * ) ( &verts[i].xyz.x ), attrAcc->typeSize );
|
||||
bin.Read( ( void * ) ( &verts[i].xyz.y ), attrAcc->typeSize );
|
||||
bin.Read( ( void * ) ( &verts[i].xyz.z ), attrAcc->typeSize );
|
||||
if ( attrBv->byteStride )
|
||||
bin.Seek( attrBv->byteStride - ( 3 * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
|
||||
idRandom rnd( i );
|
||||
int r = rnd.RandomInt( 255 ), g = rnd.RandomInt( 255 ), b = rnd.RandomInt( 255 );
|
||||
|
||||
//vtxData[i].abgr = 0xff000000 + ( b << 16 ) + ( g << 8 ) + r;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case gltfMesh_Primitive_Attribute::Type::Normal:
|
||||
{
|
||||
idVec3 vec;
|
||||
for ( int i = 0; i < attrAcc->count; i++ ) {
|
||||
idVec3 vec;
|
||||
bin.Read( ( void * ) ( &vec.x ), attrAcc->typeSize );
|
||||
bin.Read( ( void * ) ( &vec.y ), attrAcc->typeSize );
|
||||
bin.Read( ( void * ) ( &vec.z ), attrAcc->typeSize );
|
||||
if ( attrBv->byteStride )
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
verts[i].SetNormal(vec);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case gltfMesh_Primitive_Attribute::Type::TexCoord0:
|
||||
{
|
||||
idVec2 vec;
|
||||
for ( int i = 0; i < attrAcc->count; i++ ) {
|
||||
bin.Read( ( void * ) ( &vec.x ), attrAcc->typeSize );
|
||||
bin.Read( ( void * ) ( &vec.y ), attrAcc->typeSize );
|
||||
if ( attrBv->byteStride )
|
||||
bin.Seek( attrBv->byteStride - ( attrib->elementSize * attrAcc->typeSize ), FS_SEEK_CUR );
|
||||
verts[i].SetTexCoord(vec);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case gltfMesh_Primitive_Attribute::Type::Tangent:
|
||||
{
|
||||
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 );
|
||||
verts[i].SetTangent(vec.ToVec3());
|
||||
verts[i].SetBiTangentSign(vec.w);
|
||||
}
|
||||
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;
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
SetContents();
|
||||
}
|
||||
|
||||
int idMapEntity::GetEntities( gltfData * data, EntityListRef entities, int sceneID ) {
|
||||
int entityCount = 0;
|
||||
for ( auto & nodeID : data->SceneList()[sceneID]->nodes )
|
||||
{
|
||||
auto * node = data->NodeList()[nodeID];
|
||||
auto * newEntity = new idMapEntity( );
|
||||
|
||||
bool isWorldSpawn = false;
|
||||
|
||||
//set name and retrieve epairs from node extras
|
||||
if ( node->name.Length() )
|
||||
newEntity->epairs.Set( "name", node->name);
|
||||
newEntity->epairs.Copy(node->extras.strPairs);
|
||||
|
||||
isWorldSpawn = idStr::Icmp(newEntity->epairs.GetString( "classname" ), "worldspawn" ) == 0;
|
||||
|
||||
if ( isWorldSpawn )
|
||||
newEntity->primitives.Resize( 1024, 256 );
|
||||
|
||||
//check for primitive type
|
||||
idStr primType = newEntity->epairs.GetString( "PrimitiveType" );
|
||||
if ( primType.Length() )
|
||||
{
|
||||
if ( primType.Icmp( "BrushDef3" ) == 0 ) // change to MapMesh/Primitive
|
||||
{
|
||||
MapPolygonMesh *meshPrim = new MapPolygonMesh( );
|
||||
meshPrim->epairs.Copy( newEntity->epairs );
|
||||
|
||||
meshPrim->ConvertFromMeshGltf(data->MeshList()[node->mesh],data);
|
||||
newEntity->AddPrimitive(meshPrim);
|
||||
}
|
||||
}
|
||||
data->ResolveNodeMatrix(node);
|
||||
newEntity->epairs.Set( "origin", node->translation.ToString());
|
||||
common->Printf(" %s \n ", node->name.c_str( ) );
|
||||
entities.Append(newEntity);
|
||||
|
||||
entityCount++;
|
||||
}
|
||||
|
||||
if ( entities.Num( ) > 0 && ( idStr::Icmp( entities[0]->epairs.GetString( "name" ), "worldspawn" ) != 0 ) ) {
|
||||
// move world spawn to first place
|
||||
for ( int i = 1; i < entities.Num( ); i++ ) {
|
||||
if ( idStr::Icmp( entities[i]->epairs.GetString( "name" ), "worldspawn" ) == 0 ) {
|
||||
idMapEntity *tmp = entities[0];
|
||||
entities[0] = entities[i];
|
||||
entities[i] = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entityCount;
|
||||
}
|
||||
|
||||
|
||||
// [filename].[%i|%s].[gltf/glb]
|
||||
bool gltfManager::ExtractMeshIdentifier( idStr &filename, int &meshId, idStr &meshName ) {
|
||||
|
||||
idStr extension;
|
||||
filename.ExtractFileExtension(extension);
|
||||
|
||||
idStr idPart = filename.Left(filename.Length()-extension.Length()-1);
|
||||
idStr id;
|
||||
idPart.ExtractFileExtension(id);
|
||||
|
||||
if ( !id.Length() )
|
||||
{
|
||||
idLib::Warning( "no gltf mesh identifier");
|
||||
return false;
|
||||
}
|
||||
|
||||
filename = idPart.Left(idPart.Length()-id.Length()) + extension;
|
||||
|
||||
idLexer lexer( LEXFL_ALLOWMULTICHARLITERALS | LEXFL_NOSTRINGESCAPECHARS );
|
||||
lexer.LoadMemory( id.c_str( ), id.Size( ), "GltfmeshID", 0 );
|
||||
|
||||
idToken token;
|
||||
if (lexer.ExpectAnyToken(&token))
|
||||
{
|
||||
if (lexer.EndOfFile() && (token.type == TT_NUMBER) && (token.subtype & TT_INTEGER) )
|
||||
meshId = token.GetIntValue();
|
||||
else if (token.type == TT_NUMBER || token.type == TT_STRING )
|
||||
meshName = id;
|
||||
else {
|
||||
lexer.Warning("malformed gltf mesh identifier" );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}else
|
||||
lexer.Warning("malformed gltf mesh identifier" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::InitFromFile( const char *fileName ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::LoadBinaryModel( idFile *file, const ID_TIME_T sourceTimeStamp ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::WriteBinaryModel( idFile *file, ID_TIME_T *_timeStamp /*= NULL */ ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::SupportsBinaryModel( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::ExportOBJ( idFile *objFile, idFile *mtlFile, ID_TIME_T *_timeStamp /*= NULL */ ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::PartialInitFromFile( const char *fileName ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::PurgeModel( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::Reset( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::LoadModel( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::IsLoaded( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::SetLevelLoadReferenced( bool referenced ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::IsLevelLoadReferenced( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::TouchData( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::CreateBuffers( nvrhi::ICommandList *commandList ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::InitEmpty( const char *name ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::AddSurface( modelSurface_t surface ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::FinishSurfaces( bool useMikktspace ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::FreeVertexCache( ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
const char *idRenderModelGLTF::Name( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return "";
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::Print( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::List( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
int idRenderModelGLTF::Memory( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
ID_TIME_T idRenderModelGLTF::Timestamp( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return FILE_NOT_FOUND_TIMESTAMP;
|
||||
}
|
||||
|
||||
int idRenderModelGLTF::NumSurfaces( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
int idRenderModelGLTF::NumBaseSurfaces( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
const modelSurface_t *idRenderModelGLTF::Surface( int surfaceNum ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
srfTriangles_t *idRenderModelGLTF::AllocSurfaceTriangles( int numVerts, int numIndexes ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::FreeSurfaceTriangles( srfTriangles_t *tris ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::IsStaticWorldModel( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
dynamicModel_t idRenderModelGLTF::IsDynamicModel( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return dynamicModel_t();
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::IsDefaultModel( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::IsReloadable( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
idRenderModel *idRenderModelGLTF::InstantiateDynamicModel( const struct renderEntity_s *ent, const viewDef_t *view, idRenderModel *cachedModel ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int idRenderModelGLTF::NumJoints( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return 0;
|
||||
}
|
||||
|
||||
const idMD5Joint *idRenderModelGLTF::GetJoints( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jointHandle_t idRenderModelGLTF::GetJointHandle( const char *name ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return jointHandle_t();
|
||||
}
|
||||
|
||||
const char *idRenderModelGLTF::GetJointName( jointHandle_t handle ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return "";
|
||||
}
|
||||
|
||||
const idJointQuat *idRenderModelGLTF::GetDefaultPose( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int idRenderModelGLTF::NearestJoint( int surfaceNum, int a, int b, int c ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
idBounds idRenderModelGLTF::Bounds( const struct renderEntity_s *ent ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return idBounds();
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::ReadFromDemoFile( class idDemoFile *f ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
void idRenderModelGLTF::WriteToDemoFile( class idDemoFile *f ) {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
}
|
||||
|
||||
float idRenderModelGLTF::DepthHack( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::ModelHasDrawingSurfaces( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::ModelHasInteractingSurfaces( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool idRenderModelGLTF::ModelHasShadowCastingSurfaces( ) const {
|
||||
common->Warning( "The method or operation is not implemented." );
|
||||
return false;
|
||||
}
|
68
neo/renderer/Model_gltf.h
Normal file
68
neo/renderer/Model_gltf.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
#include "Model_local.h"
|
||||
|
||||
class gltfManager {
|
||||
public:
|
||||
static bool ExtractMeshIdentifier(idStr& filename , int & meshId, idStr & meshName );
|
||||
};
|
||||
|
||||
class idGltfMesh
|
||||
{
|
||||
public:
|
||||
idGltfMesh(gltfMesh * _mesh, gltfData * _data) : mesh(_mesh),data(_data){};
|
||||
|
||||
private:
|
||||
gltfMesh * mesh;
|
||||
gltfData * data;
|
||||
};
|
||||
|
||||
class idRenderModelGLTF : public idRenderModelStatic
|
||||
{
|
||||
public:
|
||||
void InitFromFile( const char *fileName ) override;
|
||||
bool LoadBinaryModel( idFile *file, const ID_TIME_T sourceTimeStamp ) override;
|
||||
void WriteBinaryModel( idFile *file, ID_TIME_T *_timeStamp = NULL ) const override;
|
||||
bool SupportsBinaryModel( ) override;
|
||||
void ExportOBJ( idFile *objFile, idFile *mtlFile, ID_TIME_T *_timeStamp = NULL ) override;
|
||||
void PartialInitFromFile( const char *fileName ) override;
|
||||
void PurgeModel( ) override;
|
||||
void Reset( ) override;
|
||||
void LoadModel( ) override;
|
||||
bool IsLoaded( ) override;
|
||||
void SetLevelLoadReferenced( bool referenced ) override;
|
||||
bool IsLevelLoadReferenced( ) override;
|
||||
void TouchData( ) override;
|
||||
void CreateBuffers( nvrhi::ICommandList *commandList ) override;
|
||||
void InitEmpty( const char *name ) override;
|
||||
void AddSurface( modelSurface_t surface ) override;
|
||||
void FinishSurfaces( bool useMikktspace ) override;
|
||||
void FreeVertexCache( ) override;
|
||||
const char *Name( ) const override;
|
||||
void Print( ) const override;
|
||||
void List( ) const override;
|
||||
int Memory( ) const override;
|
||||
ID_TIME_T Timestamp( ) const override;
|
||||
int NumSurfaces( ) const override;
|
||||
int NumBaseSurfaces( ) const override;
|
||||
const modelSurface_t *Surface( int surfaceNum ) const override;
|
||||
srfTriangles_t *AllocSurfaceTriangles( int numVerts, int numIndexes ) const override;
|
||||
void FreeSurfaceTriangles( srfTriangles_t *tris ) const override;
|
||||
bool IsStaticWorldModel( ) const override;
|
||||
dynamicModel_t IsDynamicModel( ) const override;
|
||||
bool IsDefaultModel( ) const override;
|
||||
bool IsReloadable( ) const override;
|
||||
idRenderModel *InstantiateDynamicModel( const struct renderEntity_s *ent, const viewDef_t *view, idRenderModel *cachedModel ) override;
|
||||
int NumJoints( ) const override;
|
||||
const idMD5Joint *GetJoints( ) const override;
|
||||
jointHandle_t GetJointHandle( const char *name ) const override;
|
||||
const char *GetJointName( jointHandle_t handle ) const override;
|
||||
const idJointQuat *GetDefaultPose( ) const override;
|
||||
int NearestJoint( int surfaceNum, int a, int b, int c ) const override;
|
||||
idBounds Bounds( const struct renderEntity_s *ent ) const override;
|
||||
void ReadFromDemoFile( class idDemoFile *f ) override;
|
||||
void WriteToDemoFile( class idDemoFile *f ) override;
|
||||
float DepthHack( ) const override;
|
||||
bool ModelHasDrawingSurfaces( ) const override;
|
||||
bool ModelHasInteractingSurfaces( ) const override;
|
||||
bool ModelHasShadowCastingSurfaces( ) const override;
|
||||
};
|
Loading…
Reference in a new issue