pull/1461/head
Kim Kulling 2017-09-19 00:32:50 +02:00
commit d27e667f1e
62 changed files with 2610 additions and 1655 deletions

View File

@ -1,6 +1,8 @@
sudo: required sudo: required
language: cpp language: cpp
cache: ccache
before_install: before_install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
- 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then - 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then
@ -20,24 +22,33 @@ branches:
only: only:
- master - master
osx_image: xcode8.3 os:
- linux
env: env:
global: global:
# COVERITY_SCAN_TOKEN # COVERITY_SCAN_TOKEN
- secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc=" - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
- PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME} - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
matrix:
- os: linux LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON matrix:
exclude:
- os: linux
env:
include:
- os: linux
compiler: gcc compiler: gcc
- os: linux LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF env: LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
compiler: clang - os: linux
- os: linux LINUX=1 SHARED_BUILD=ON TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
compiler: gcc compiler: gcc
- os: linux LINUX=1 SHARED_BUILD=ON TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF env: LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
compiler: clang - os: linux
- os: osx compiler: gcc
osx_image: xcode8.2 env: LINUX=1 SHARED_BUILD=ON TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
- os: linux
compiler: gcc
env: LINUX=1 SHARED_BUILD=ON TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
install: install:
- if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
@ -50,9 +61,6 @@ script:
- export COVERALLS_SERVICE_NAME=travis-ci - export COVERALLS_SERVICE_NAME=travis-ci
- export COVERALLS_REPO_TOKEN=abc12345 - export COVERALLS_REPO_TOKEN=abc12345
- . ./.travis.sh - . ./.travis.sh
os:
- linux
- osx
after_success: after_success:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi

View File

@ -78,6 +78,10 @@ OPTION ( ASSIMP_COVERALLS
"Enable this to measure test coverage." "Enable this to measure test coverage."
OFF OFF
) )
OPTION ( ASSIMP_WERRRO
"Treat warnings as errors."
OFF
)
OPTION ( SYSTEM_IRRXML OPTION ( SYSTEM_IRRXML
"Use system installed Irrlicht/IrrXML library." "Use system installed Irrlicht/IrrXML library."
OFF OFF
@ -212,6 +216,11 @@ if (ASSIMP_COVERALLS)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
endif() endif()
if (ASSIMP_WERROR)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
endif()
INCLUDE (FindPkgMacros) INCLUDE (FindPkgMacros)
INCLUDE (PrecompiledHeader) INCLUDE (PrecompiledHeader)

View File

@ -52,7 +52,8 @@ __Importers__:
- DXF - DXF
- ENFF - ENFF
- FBX - FBX
- GLB/GLTF - glTF 1.0 + GLB
- glTF 2.0
- HMB - HMB
- IFC-STEP - IFC-STEP
- IRR / IRRMESH - IRR / IRRMESH
@ -106,8 +107,8 @@ __Exporters__:
- JSON (for WebGl, via https://github.com/acgessler/assimp2json) - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN - ASSBIN
- STEP - STEP
- glTF (partial) - glTF 1.0 (partial)
- glTF2.0 - glTF 2.0 (partial)
### Building ### ### Building ###
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do. Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
@ -119,6 +120,7 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak
* [Pascal](port/AssimpPascal/Readme.md) * [Pascal](port/AssimpPascal/Readme.md)
* [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Javascript (Alpha)](https://github.com/makc/assimp2json)
* [Unity 3d Plugin] (https://www.assetstore.unity3d.com/en/#!/content/91777) * [Unity 3d Plugin] (https://www.assetstore.unity3d.com/en/#!/content/91777)
* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (currently supported obj, ply, stl, ~collada)
### Other tools ### ### Other tools ###
[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.

View File

@ -1381,7 +1381,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent )
bGamma = true; bGamma = true;
case Discreet3DS::CHUNK_RGBF: case Discreet3DS::CHUNK_RGBF:
if (sizeof(ai_real) * 3 > diff) { if (sizeof(float) * 3 > diff) {
*out = clrError; *out = clrError;
return; return;
} }

View File

@ -139,6 +139,17 @@ inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
return t; return t;
} }
// -----------------------------------------------------------------------------------
// Serialize a color value
template <>
inline size_t Write<aiColor3D>(IOStream * stream, const aiColor3D& v)
{
size_t t = Write<float>(stream,v.r);
t += Write<float>(stream,v.g);
t += Write<float>(stream,v.b);
return t;
}
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a color value // Serialize a color value
template <> template <>
@ -325,7 +336,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
{ {
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
size_t nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0);
Write<aiString>(&chunk,node->mName); Write<aiString>(&chunk,node->mName);
Write<aiMatrix4x4>(&chunk,node->mTransformation); Write<aiMatrix4x4>(&chunk,node->mTransformation);
@ -639,9 +650,9 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
Write<float>(&chunk,l->mAttenuationQuadratic); Write<float>(&chunk,l->mAttenuationQuadratic);
} }
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse); Write<aiColor3D>(&chunk,l->mColorDiffuse);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular); Write<aiColor3D>(&chunk,l->mColorSpecular);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient); Write<aiColor3D>(&chunk,l->mColorAmbient);
if (l->mType == aiLightSource_SPOT) { if (l->mType == aiLightSource_SPOT) {
Write<float>(&chunk,l->mAngleInnerCone); Write<float>(&chunk,l->mAngleInnerCone);

View File

@ -61,6 +61,7 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/color4.inl ${HEADER_PATH}/color4.inl
${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h
${HEADER_PATH}/defs.h ${HEADER_PATH}/defs.h
${HEADER_PATH}/Defines.h
${HEADER_PATH}/cfileio.h ${HEADER_PATH}/cfileio.h
${HEADER_PATH}/light.h ${HEADER_PATH}/light.h
${HEADER_PATH}/material.h ${HEADER_PATH}/material.h
@ -665,6 +666,8 @@ ADD_ASSIMP_IMPORTER( GLTF
glTF2Asset.inl glTF2Asset.inl
glTF2AssetWriter.h glTF2AssetWriter.h
glTF2AssetWriter.inl glTF2AssetWriter.inl
glTF2Importer.cpp
glTF2Importer.h
glTF2Exporter.h glTF2Exporter.h
glTF2Exporter.cpp glTF2Exporter.cpp
) )

View File

@ -866,8 +866,8 @@ void ColladaExporter::WriteController( size_t pIndex)
std::vector<ai_real> bind_poses; std::vector<ai_real> bind_poses;
bind_poses.reserve(mesh->mNumBones * 16); bind_poses.reserve(mesh->mNumBones * 16);
for( size_t i = 0; i < mesh->mNumBones; ++i) for(unsigned int i = 0; i < mesh->mNumBones; ++i)
for( size_t j = 0; j < 4; ++j) for( unsigned int j = 0; j < 4; ++j)
bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4);
WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16);
@ -924,11 +924,11 @@ void ColladaExporter::WriteController( size_t pIndex)
ai_uint weight_index = 0; ai_uint weight_index = 0;
std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1);
for( size_t i = 0; i < mesh->mNumBones; ++i) for( unsigned int i = 0; i < mesh->mNumBones; ++i)
for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
{ {
unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId;
for( size_t k = 0; k < num_influences[vId]; ++k) for( ai_uint k = 0; k < num_influences[vId]; ++k)
{ {
if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1)
{ {

View File

@ -119,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
* might be NULL and it's our duty to return true here. * might be NULL and it's our duty to return true here.
*/ */
if (!pIOHandler)return true; if (!pIOHandler)return true;
const char* tokens[] = {"collada"}; const char* tokens[] = {"<collada"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
return false; return false;
@ -728,7 +728,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
? aiMorphingMethod_MORPH_RELATIVE ? aiMorphingMethod_MORPH_RELATIVE
: aiMorphingMethod_MORPH_NORMALIZED; : aiMorphingMethod_MORPH_NORMALIZED;
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()]; dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
dstMesh->mNumAnimMeshes = animMeshes.size(); dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
for (unsigned int i = 0; i < animMeshes.size(); i++) for (unsigned int i = 0; i < animMeshes.size(); i++)
dstMesh->mAnimMeshes[i] = animMeshes.at(i); dstMesh->mAnimMeshes[i] = animMeshes.at(i);
} }
@ -1377,9 +1377,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
{ {
aiNodeAnim* dstAnim = new aiNodeAnim; aiNodeAnim* dstAnim = new aiNodeAnim;
dstAnim->mNodeName = nodeName; dstAnim->mNodeName = nodeName;
dstAnim->mNumPositionKeys = resultTrafos.size(); dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumRotationKeys= resultTrafos.size(); dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumScalingKeys = resultTrafos.size(); dstAnim->mNumScalingKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()]; dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()]; dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()]; dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
@ -1445,11 +1445,11 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
++morphAnimChannelIndex; ++morphAnimChannelIndex;
} }
morphAnim->mNumKeys = morphTimeValues.size(); morphAnim->mNumKeys = static_cast<unsigned int>(morphTimeValues.size());
morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys]; morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys];
for (unsigned int key = 0; key < morphAnim->mNumKeys; key++) for (unsigned int key = 0; key < morphAnim->mNumKeys; key++)
{ {
morphAnim->mKeys[key].mNumValuesAndWeights = morphChannels.size(); morphAnim->mKeys[key].mNumValuesAndWeights = static_cast<unsigned int>(morphChannels.size());
morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()]; morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()];
morphAnim->mKeys[key].mWeights = new double [morphChannels.size()]; morphAnim->mKeys[key].mWeights = new double [morphChannels.size()];
@ -1470,13 +1470,13 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
{ {
aiAnimation* anim = new aiAnimation; aiAnimation* anim = new aiAnimation;
anim->mName.Set( pName); anim->mName.Set( pName);
anim->mNumChannels = anims.size(); anim->mNumChannels = static_cast<unsigned int>(anims.size());
if (anim->mNumChannels > 0) if (anim->mNumChannels > 0)
{ {
anim->mChannels = new aiNodeAnim*[anims.size()]; anim->mChannels = new aiNodeAnim*[anims.size()];
std::copy( anims.begin(), anims.end(), anim->mChannels); std::copy( anims.begin(), anims.end(), anim->mChannels);
} }
anim->mNumMorphMeshChannels = morphAnims.size(); anim->mNumMorphMeshChannels = static_cast<unsigned int>(morphAnims.size());
if (anim->mNumMorphMeshChannels > 0) if (anim->mNumMorphMeshChannels > 0)
{ {
anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels]; anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];

View File

@ -253,8 +253,8 @@ void DefaultLogger::kill()
// Debug message // Debug message
void DefaultLogger::OnDebug( const char* message ) void DefaultLogger::OnDebug( const char* message )
{ {
if ( m_Severity == Logger::NORMAL ) if ( m_Severity == Logger::NORMAL )
return; return;
static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
char msg[Size]; char msg[Size];

View File

@ -87,17 +87,16 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurve::~AnimationCurve() AnimationCurve::~AnimationCurve()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name,
const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) const Document& doc, const char* const * target_prop_whitelist /*= NULL*/,
size_t whitelist_size /*= 0*/)
: Object(id, element, name) : Object(id, element, name)
, target() , target()
, doc(doc) , doc(doc)
@ -154,18 +153,16 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::~AnimationCurveNode() AnimationCurveNode::~AnimationCurveNode()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const AnimationCurveMap& AnimationCurveNode::Curves() const const AnimationCurveMap& AnimationCurveNode::Curves() const
{ {
if(curves.empty()) { if ( curves.empty() ) {
// resolve attached animation curves // resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
@ -195,7 +192,6 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
return curves; return curves;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc) AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name) : Object(id, element, name)
@ -207,14 +203,12 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationLayer::~AnimationLayer() AnimationLayer::~AnimationLayer()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
size_t whitelist_size /*= 0*/) const size_t whitelist_size /*= 0*/) const
@ -298,14 +292,13 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationStack::~AnimationStack() AnimationStack::~AnimationStack()
{ {
// empty
} }
} //!FBX } //!FBX
} //!Assimp } //!Assimp
#endif #endif // ASSIMP_BUILD_NO_FBX_IMPORTER

View File

@ -66,4 +66,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# endif # endif
#endif #endif
#endif #endif // INCLUDED_AI_FBX_COMPILECONFIG_H

View File

@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h" #include "StringComparison.h"
#include <assimp/scene.h> #include <assimp/scene.h>
#include <tuple> #include <tuple>
#include <memory> #include <memory>
#include <iterator> #include <iterator>
#include <vector> #include <vector>
@ -931,7 +931,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model )
const TransformationComp comp = static_cast< TransformationComp >( i ); const TransformationComp comp = static_cast< TransformationComp >( i );
if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation || if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) { comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) {
continue; continue;
} }
@ -949,8 +949,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra
return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
} }
void Converter::GenerateTransformationNodeChain( const Model& model, void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
std::vector<aiNode*>& output_nodes )
{ {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder(); const Model::RotOrder rot = model.RotationOrder();
@ -3124,7 +3123,6 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
} }
} }
void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
const aiVector3D& def_value, const aiVector3D& def_value,
double& maxTime, double& maxTime,
@ -3145,7 +3143,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
valOut[ i ].mTime = temp[ i ].mTime; valOut[ i ].mTime = temp[ i ].mTime;
GetRotationMatrix( order, temp[ i ].mValue, m ); GetRotationMatrix( order, temp[ i ].mValue, m );
aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) ); aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) );
@ -3164,7 +3161,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
} }
} }
void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale,
aiVectorKey* out_translation, aiVectorKey* out_translation,
const KeyFrameListList& scaling, const KeyFrameListList& scaling,
@ -3223,7 +3219,6 @@ void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey
} }
} }
aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ) aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order )
{ {
aiMatrix4x4 m; aiMatrix4x4 m;
@ -3232,7 +3227,6 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde
return aiQuaternion( aiMatrix3x3( m ) ); return aiQuaternion( aiMatrix3x3( m ) );
} }
void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/, void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
double& maxTime, double& maxTime,
@ -3253,7 +3247,6 @@ void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const Animat
InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime ); InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime );
} }
void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& /*layers*/, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
@ -3272,7 +3265,6 @@ void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const
InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime ); InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime );
} }
void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& /*layers*/, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
@ -3294,7 +3286,8 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const Ani
void Converter::TransferDataToScene() void Converter::TransferDataToScene()
{ {
ai_assert( !out->mMeshes && !out->mNumMeshes ); ai_assert( !out->mMeshes );
ai_assert( !out->mNumMeshes );
// note: the trailing () ensures initialization with NULL - not // note: the trailing () ensures initialization with NULL - not
// many C++ users seem to know this, so pointing it out to avoid // many C++ users seem to know this, so pointing it out to avoid

View File

@ -70,13 +70,13 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
, id(id) , id(id)
, flags() , flags()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject::~LazyObject() LazyObject::~LazyObject()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -232,16 +232,15 @@ Object::Object(uint64_t id, const Element& element, const std::string& name)
, name(name) , name(name)
, id(id) , id(id)
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Object::~Object() Object::~Object()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props) FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
: props(props) : props(props)
@ -361,7 +360,6 @@ void Document::ReadGlobalSettings()
globals.reset(new FileGlobalSettings(*this, props)); globals.reset(new FileGlobalSettings(*this, props));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Document::ReadObjects() void Document::ReadObjects()
{ {
@ -387,7 +385,6 @@ void Document::ReadObjects()
} }
const char* err; const char* err;
const uint64_t id = ParseTokenAsID(*tok[0], err); const uint64_t id = ParseTokenAsID(*tok[0], err);
if(err) { if(err) {
DOMError(err,el.second); DOMError(err,el.second);
@ -469,8 +466,6 @@ void Document::ReadPropertyTemplates()
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Document::ReadConnections() void Document::ReadConnections()
{ {
@ -482,7 +477,6 @@ void Document::ReadConnections()
} }
uint64_t insertionOrder = 0l; uint64_t insertionOrder = 0l;
const Scope& sconns = *econns->Compound(); const Scope& sconns = *econns->Compound();
const ElementCollection conns = sconns.GetCollection("C"); const ElementCollection conns = sconns.GetCollection("C");
for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) { for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) {
@ -491,7 +485,9 @@ void Document::ReadConnections()
// PP = property-property connection, ignored for now // PP = property-property connection, ignored for now
// (tokens: "PP", ID1, "Property1", ID2, "Property2") // (tokens: "PP", ID1, "Property1", ID2, "Property2")
if(type == "PP") continue; if ( type == "PP" ) {
continue;
}
const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1)); const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1));
const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2)); const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2));
@ -518,11 +514,10 @@ void Document::ReadConnections()
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const std::vector<const AnimationStack*>& Document::AnimationStacks() const const std::vector<const AnimationStack*>& Document::AnimationStacks() const
{ {
if (!animationStacksResolved.empty() || !animationStacks.size()) { if (!animationStacksResolved.empty() || animationStacks.empty()) {
return animationStacksResolved; return animationStacksResolved;
} }
@ -540,7 +535,6 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
return animationStacksResolved; return animationStacksResolved;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject* Document::GetObject(uint64_t id) const LazyObject* Document::GetObject(uint64_t id) const
{ {
@ -551,8 +545,7 @@ LazyObject* Document::GetObject(uint64_t id) const
#define MAX_CLASSNAMES 6 #define MAX_CLASSNAMES 6
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
const ConnectionMap& conns) const
{ {
std::vector<const Connection*> temp; std::vector<const Connection*> temp;
@ -569,7 +562,6 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
return temp; // NRVO should handle this return temp; // NRVO should handle this
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src, std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
const ConnectionMap& conns, const ConnectionMap& conns,
@ -578,17 +570,17 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
{ {
ai_assert(classnames); ai_assert(classnames);
ai_assert(count != 0 && count <= MAX_CLASSNAMES); ai_assert( count != 0 );
ai_assert( count <= MAX_CLASSNAMES);
size_t lenghts[MAX_CLASSNAMES]; size_t lenghts[MAX_CLASSNAMES];
const size_t c = count; const size_t c = count;
for (size_t i = 0; i < c; ++i) { for (size_t i = 0; i < c; ++i) {
lenghts[i] = strlen(classnames[i]); lenghts[ i ] = strlen(classnames[i]);
} }
std::vector<const Connection*> temp; std::vector<const Connection*> temp;
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range = const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
conns.equal_range(id); conns.equal_range(id);
@ -620,49 +612,40 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
return temp; // NRVO should handle this return temp; // NRVO should handle this
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
{ {
return GetConnectionsSequenced(source, ConnectionsBySource()); return GetConnectionsSequenced(source, ConnectionsBySource());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest, std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest, const char* classname) const
const char* classname) const
{ {
const char* arr[] = {classname}; const char* arr[] = {classname};
return GetConnectionsBySourceSequenced(dest, arr,1); return GetConnectionsBySourceSequenced(dest, arr,1);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source, std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
const char* const* classnames, size_t count) const const char* const* classnames, size_t count) const
{ {
return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count); return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest, std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* classname) const const char* classname) const
{ {
const char* arr[] = {classname}; const char* arr[] = {classname};
return GetConnectionsByDestinationSequenced(dest, arr,1); return GetConnectionsByDestinationSequenced(dest, arr,1);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
{ {
return GetConnectionsSequenced(dest, ConnectionsByDestination()); return GetConnectionsSequenced(dest, ConnectionsByDestination());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest, std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* const* classnames, size_t count) const const char* const* classnames, size_t count) const
@ -671,10 +654,9 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count); return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
const Document& doc) const Document& doc)
: insertionOrder(insertionOrder) : insertionOrder(insertionOrder)
, prop(prop) , prop(prop)
@ -687,14 +669,12 @@ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, co
ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end()); ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Connection::~Connection() Connection::~Connection()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazySourceObject() const LazyObject& Connection::LazySourceObject() const
{ {
@ -703,7 +683,6 @@ LazyObject& Connection::LazySourceObject() const
return *lazy; return *lazy;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazyDestinationObject() const LazyObject& Connection::LazyDestinationObject() const
{ {
@ -712,7 +691,6 @@ LazyObject& Connection::LazyDestinationObject() const
return *lazy; return *lazy;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Object* Connection::SourceObject() const const Object* Connection::SourceObject() const
{ {
@ -721,7 +699,6 @@ const Object* Connection::SourceObject() const
return lazy->Get(); return lazy->Get();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Object* Connection::DestinationObject() const const Object* Connection::DestinationObject() const
{ {
@ -734,4 +711,3 @@ const Object* Connection::DestinationObject() const
} // !Assimp } // !Assimp
#endif #endif

View File

@ -338,12 +338,7 @@ public:
class Model : public Object class Model : public Object
{ {
public: public:
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); enum RotOrder {
virtual ~Model();
public:
enum RotOrder
{
RotOrder_EulerXYZ = 0, RotOrder_EulerXYZ = 0,
RotOrder_EulerXZY, RotOrder_EulerXZY,
RotOrder_EulerYZX, RotOrder_EulerYZX,
@ -357,8 +352,7 @@ public:
}; };
enum TransformInheritance enum TransformInheritance {
{
TransformInheritance_RrSs = 0, TransformInheritance_RrSs = 0,
TransformInheritance_RSrs, TransformInheritance_RSrs,
TransformInheritance_Rrs, TransformInheritance_Rrs,
@ -366,7 +360,10 @@ public:
TransformInheritance_MAX // end-of-enum sentinel TransformInheritance_MAX // end-of-enum sentinel
}; };
public: Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Model();
fbx_simple_property(QuaternionInterpolate, int, 0) fbx_simple_property(QuaternionInterpolate, int, 0)
fbx_simple_property(RotationOffset, aiVector3D, aiVector3D()) fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
@ -443,7 +440,6 @@ public:
fbx_simple_property(LODBox, bool, false) fbx_simple_property(LODBox, bool, false)
fbx_simple_property(Freeze, bool, false) fbx_simple_property(Freeze, bool, false)
public:
const std::string& Shading() const { const std::string& Shading() const {
return shading; return shading;
} }
@ -462,13 +458,11 @@ public:
return materials; return materials;
} }
/** Get geometry links */ /** Get geometry links */
const std::vector<const Geometry*>& GetGeometry() const { const std::vector<const Geometry*>& GetGeometry() const {
return geometry; return geometry;
} }
/** Get node attachments */ /** Get node attachments */
const std::vector<const NodeAttribute*>& GetAttributes() const { const std::vector<const NodeAttribute*>& GetAttributes() const {
return attributes; return attributes;
@ -477,7 +471,6 @@ public:
/** convenience method to check if the node has a Null node marker */ /** convenience method to check if the node has a Null node marker */
bool IsNull() const; bool IsNull() const;
private: private:
void ResolveLinks(const Element& element, const Document& doc); void ResolveLinks(const Element& element, const Document& doc);
@ -805,7 +798,6 @@ private:
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList; typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
/** Represents a FBX animation layer (i.e. a list of node animations) */ /** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer : public Object class AnimationLayer : public Object
{ {
@ -828,10 +820,8 @@ private:
const Document& doc; const Document& doc;
}; };
typedef std::vector<const AnimationLayer*> AnimationLayerList; typedef std::vector<const AnimationLayer*> AnimationLayerList;
/** Represents a FBX animation stack (i.e. a list of animation layers) */ /** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack : public Object class AnimationStack : public Object
{ {
@ -839,7 +829,6 @@ public:
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc); AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationStack(); virtual ~AnimationStack();
public:
fbx_simple_property(LocalStart, int64_t, 0L) fbx_simple_property(LocalStart, int64_t, 0L)
fbx_simple_property(LocalStop, int64_t, 0L) fbx_simple_property(LocalStop, int64_t, 0L)
fbx_simple_property(ReferenceStart, int64_t, 0L) fbx_simple_property(ReferenceStart, int64_t, 0L)
@ -879,7 +868,6 @@ private:
typedef std::vector<float> WeightArray; typedef std::vector<float> WeightArray;
typedef std::vector<unsigned int> WeightIndexArray; typedef std::vector<unsigned int> WeightIndexArray;
/** DOM class for skin deformer clusters (aka subdeformers) */ /** DOM class for skin deformer clusters (aka subdeformers) */
class Cluster : public Deformer class Cluster : public Deformer
{ {
@ -924,8 +912,6 @@ private:
const Model* node; const Model* node;
}; };
/** DOM class for skin deformers */ /** DOM class for skin deformers */
class Skin : public Deformer class Skin : public Deformer
{ {
@ -1009,10 +995,8 @@ public:
typedef std::map<uint64_t, LazyObject*> ObjectMap; typedef std::map<uint64_t, LazyObject*> ObjectMap;
typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap; typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
typedef std::multimap<uint64_t, const Connection*> ConnectionMap; typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
/** DOM class for global document settings, a single instance per document can /** DOM class for global document settings, a single instance per document can
* be accessed via Document.Globals(). */ * be accessed via Document.Globals(). */
class FileGlobalSettings class FileGlobalSettings
@ -1074,9 +1058,6 @@ private:
const Document& doc; const Document& doc;
}; };
/** DOM root for a FBX file */ /** DOM root for a FBX file */
class Document class Document
{ {
@ -1154,8 +1135,6 @@ private:
const ConnectionMap&, const ConnectionMap&,
const char* const* classnames, const char* const* classnames,
size_t count) const; size_t count) const;
private:
void ReadHeader(); void ReadHeader();
void ReadObjects(); void ReadObjects();
void ReadPropertyTemplates(); void ReadPropertyTemplates();

View File

@ -77,14 +77,12 @@ Model::Model(uint64_t id, const Element& element, const Document& doc, const std
ResolveLinks(element,doc); ResolveLinks(element,doc);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Model::~Model() Model::~Model()
{ {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Model::ResolveLinks(const Element& element, const Document& doc) void Model::ResolveLinks(const Element& element, const Document& doc)
{ {
@ -132,7 +130,6 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool Model::IsNull() const bool Model::IsNull() const
{ {

View File

@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name) NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
@ -75,7 +75,7 @@ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
NodeAttribute::~NodeAttribute() NodeAttribute::~NodeAttribute()
{ {
// empty
} }
@ -101,33 +101,30 @@ CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Docume
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
CameraSwitcher::~CameraSwitcher() CameraSwitcher::~CameraSwitcher()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name) Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name) : NodeAttribute(id,element,doc,name)
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Camera::~Camera() Camera::~Camera()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name) Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name) : NodeAttribute(id,element,doc,name)
{ {
// empty
} }

View File

@ -224,41 +224,36 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
root.reset(new Scope(*this,true)); root.reset(new Scope(*this,true));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Parser::~Parser() Parser::~Parser()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::AdvanceToNextToken() TokenPtr Parser::AdvanceToNextToken()
{ {
last = current; last = current;
if (cursor == tokens.end()) { if (cursor == tokens.end()) {
current = NULL; current = NULL;
} } else {
else {
current = *cursor++; current = *cursor++;
} }
return current; return current;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::CurrentToken() const TokenPtr Parser::CurrentToken() const
{ {
return current; return current;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::LastToken() const TokenPtr Parser::LastToken() const
{ {
return last; return last;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint64_t ParseTokenAsID(const Token& t, const char*& err_out) uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
{ {
@ -286,7 +281,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
unsigned int length = static_cast<unsigned int>(t.end() - t.begin()); unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
ai_assert(length > 0); ai_assert(length > 0);
const char* out; const char* out = nullptr;
const uint64_t id = strtoul10_64(t.begin(),&out,&length); const uint64_t id = strtoul10_64(t.begin(),&out,&length);
if (out > t.end()) { if (out > t.end()) {
err_out = "failed to parse ID (text)"; err_out = "failed to parse ID (text)";
@ -296,7 +291,6 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
return id; return id;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
size_t ParseTokenAsDim(const Token& t, const char*& err_out) size_t ParseTokenAsDim(const Token& t, const char*& err_out)
{ {
@ -333,7 +327,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return 0; return 0;
} }
const char* out; const char* out = nullptr;
const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length)); const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
if (out > t.end()) { if (out > t.end()) {
err_out = "failed to parse ID"; err_out = "failed to parse ID";
@ -446,7 +440,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
unsigned int length = static_cast<unsigned int>(t.end() - t.begin()); unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
ai_assert(length > 0); ai_assert(length > 0);
const char* out; const char* out = nullptr;
const int64_t id = strtol10_64(t.begin(), &out, &length); const int64_t id = strtol10_64(t.begin(), &out, &length);
if (out > t.end()) { if (out > t.end()) {
err_out = "failed to parse Int64 (text)"; err_out = "failed to parse Int64 (text)";

View File

@ -85,12 +85,9 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
class Element class Element
{ {
public: public:
Element(const Token& key_token, Parser& parser); Element(const Token& key_token, Parser& parser);
~Element(); ~Element();
public:
const Scope* Compound() const { const Scope* Compound() const {
return compound.get(); return compound.get();
} }
@ -104,14 +101,11 @@ public:
} }
private: private:
const Token& key_token; const Token& key_token;
TokenList tokens; TokenList tokens;
std::unique_ptr<Scope> compound; std::unique_ptr<Scope> compound;
}; };
/** FBX data entity that consists of a 'scope', a collection /** FBX data entity that consists of a 'scope', a collection
* of not necessarily unique #Element instances. * of not necessarily unique #Element instances.
* *
@ -125,14 +119,10 @@ private:
* @endverbatim */ * @endverbatim */
class Scope class Scope
{ {
public: public:
Scope(Parser& parser, bool topLevel = false); Scope(Parser& parser, bool topLevel = false);
~Scope(); ~Scope();
public:
const Element* operator[] (const std::string& index) const { const Element* operator[] (const std::string& index) const {
ElementMap::const_iterator it = elements.find(index); ElementMap::const_iterator it = elements.find(index);
return it == elements.end() ? NULL : (*it).second; return it == elements.end() ? NULL : (*it).second;
@ -158,28 +148,23 @@ public:
} }
private: private:
ElementMap elements; ElementMap elements;
}; };
/** FBX parsing class, takes a list of input tokens and generates a hierarchy /** FBX parsing class, takes a list of input tokens and generates a hierarchy
* of nested #Scope instances, representing the fbx DOM.*/ * of nested #Scope instances, representing the fbx DOM.*/
class Parser class Parser
{ {
public: public:
/** Parse given a token list. Does not take ownership of the tokens - /** Parse given a token list. Does not take ownership of the tokens -
* the objects must persist during the entire parser lifetime */ * the objects must persist during the entire parser lifetime */
Parser (const TokenList& tokens,bool is_binary); Parser (const TokenList& tokens,bool is_binary);
~Parser(); ~Parser();
public:
const Scope& GetRootScope() const { const Scope& GetRootScope() const {
return *root.get(); return *root.get();
} }
bool IsBinary() const { bool IsBinary() const {
return is_binary; return is_binary;
} }
@ -233,8 +218,6 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e); void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el); void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
// extract a required element from a scope, abort if the element cannot be found // extract a required element from a scope, abort if the element cannot be found
const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL);
@ -243,8 +226,6 @@ const Scope& GetRequiredScope(const Element& el);
// get token at a particular index // get token at a particular index
const Token& GetRequiredToken(const Element& el, unsigned int index); const Token& GetRequiredToken(const Element& el, unsigned int index);
// read a 4x4 matrix from an array of 16 floats // read a 4x4 matrix from an array of 16 floats
aiMatrix4x4 ReadMatrix(const Element& element); aiMatrix4x4 ReadMatrix(const Element& element);

View File

@ -128,7 +128,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f )); meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
} }
meshout.vertcnt.push_back(segments); meshout.vertcnt.push_back(static_cast<unsigned int>(segments));
} }
else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) { else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) {
// construct simplified IBeam shape // construct simplified IBeam shape

View File

@ -831,8 +831,8 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), static_cast<int>(pimpl->mPostProcessingSteps.size()) ); pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
// update private scene flags // update private scene flags
if( pimpl->mScene ) if( pimpl->mScene )
ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags; ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
// clear any data allocated by post-process steps // clear any data allocated by post-process steps
pimpl->mPPShared->Clean(); pimpl->mPPShared->Clean();

View File

@ -182,6 +182,7 @@ corresponding preprocessor flag to selectively disable formats.
#endif #endif
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
# include "glTFImporter.h" # include "glTFImporter.h"
# include "glTF2Importer.h"
#endif #endif
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
# include "C4DImporter.h" # include "C4DImporter.h"
@ -336,6 +337,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#endif #endif
#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) #if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
out.push_back( new glTFImporter() ); out.push_back( new glTFImporter() );
out.push_back( new glTF2Importer() );
#endif #endif
#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER ) #if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
out.push_back( new C4DImporter() ); out.push_back( new C4DImporter() );

View File

@ -278,7 +278,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back( bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back(
aiVertexWeight(index, vsBDEF2_ptr->bone_weight)); aiVertexWeight(index, vsBDEF2_ptr->bone_weight));
bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back( bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back(
aiVertexWeight(index, 1.0 - vsBDEF2_ptr->bone_weight)); aiVertexWeight(index, 1.0f - vsBDEF2_ptr->bone_weight));
break; break;
case pmx::PmxVertexSkinningType::BDEF4: case pmx::PmxVertexSkinningType::BDEF4:
bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back( bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back(
@ -295,7 +295,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
bone_vertex_map[vsSDEF_ptr->bone_index1].push_back( bone_vertex_map[vsSDEF_ptr->bone_index1].push_back(
aiVertexWeight(index, vsSDEF_ptr->bone_weight)); aiVertexWeight(index, vsSDEF_ptr->bone_weight));
bone_vertex_map[vsSDEF_ptr->bone_index2].push_back( bone_vertex_map[vsSDEF_ptr->bone_index2].push_back(
aiVertexWeight(index, 1.0 - vsSDEF_ptr->bone_weight)); aiVertexWeight(index, 1.0f - vsSDEF_ptr->bone_weight));
break; break;
case pmx::PmxVertexSkinningType::QDEF: case pmx::PmxVertexSkinningType::QDEF:
const auto vsQDEF_ptr = const auto vsQDEF_ptr =
@ -325,7 +325,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix); aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix);
auto it = bone_vertex_map.find(ii); auto it = bone_vertex_map.find(ii);
if (it != bone_vertex_map.end()) { if (it != bone_vertex_map.end()) {
pBone->mNumWeights = it->second.size(); pBone->mNumWeights = static_cast<unsigned int>(it->second.size());
pBone->mWeights = it->second.data(); pBone->mWeights = it->second.data();
it->second.swap(*(new vector<aiVertexWeight>)); it->second.swap(*(new vector<aiVertexWeight>));
} }

View File

@ -49,17 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace pmd namespace pmd
{ {
/// ヘッダ
class PmdHeader class PmdHeader
{ {
public: public:
/// モデル名
std::string name; std::string name;
/// モデル名(英語)
std::string name_english; std::string name_english;
/// コメント
std::string comment; std::string comment;
/// コメント(英語)
std::string comment_english; std::string comment_english;
bool Read(std::ifstream* stream) bool Read(std::ifstream* stream)
@ -83,26 +78,19 @@ namespace pmd
} }
}; };
/// 頂点
class PmdVertex class PmdVertex
{ {
public: public:
/// 位置
float position[3]; float position[3];
/// 法線
float normal[3]; float normal[3];
/// UV座標
float uv[2]; float uv[2];
/// 関連ボーンインデックス
uint16_t bone_index[2]; uint16_t bone_index[2];
/// ボーンウェイト
uint8_t bone_weight; uint8_t bone_weight;
/// エッジ不可視
bool edge_invisible; bool edge_invisible;
bool Read(std::ifstream* stream) bool Read(std::ifstream* stream)
@ -117,27 +105,17 @@ namespace pmd
} }
}; };
/// 材質
class PmdMaterial class PmdMaterial
{ {
public: public:
/// 減衰色
float diffuse[4]; float diffuse[4];
/// 光沢度
float power; float power;
/// 光沢色
float specular[3]; float specular[3];
/// 環境色
float ambient[3]; float ambient[3];
/// トーンインデックス
uint8_t toon_index; uint8_t toon_index;
/// エッジ
uint8_t edge_flag; uint8_t edge_flag;
/// インデックス数
uint32_t index_count; uint32_t index_count;
/// テクスチャファイル名
std::string texture_filename; std::string texture_filename;
/// スフィアファイル名
std::string sphere_filename; std::string sphere_filename;
bool Read(std::ifstream* stream) bool Read(std::ifstream* stream)
@ -180,23 +158,15 @@ namespace pmd
RotationMovement RotationMovement
}; };
/// ボーン
class PmdBone class PmdBone
{ {
public: public:
/// ボーン名
std::string name; std::string name;
/// ボーン名(英語)
std::string name_english; std::string name_english;
/// 親ボーン番号
uint16_t parent_bone_index; uint16_t parent_bone_index;
/// 末端ボーン番号
uint16_t tail_pos_bone_index; uint16_t tail_pos_bone_index;
/// ボーン種類
BoneType bone_type; BoneType bone_type;
/// IKボーン番号
uint16_t ik_parent_bone_index; uint16_t ik_parent_bone_index;
/// ボーンのヘッドの位置
float bone_head_pos[3]; float bone_head_pos[3];
void Read(std::istream *stream) void Read(std::istream *stream)
@ -219,19 +189,13 @@ namespace pmd
} }
}; };
/// IK
class PmdIk class PmdIk
{ {
public: public:
/// IKボーン番号
uint16_t ik_bone_index; uint16_t ik_bone_index;
/// IKターゲットボーン番号
uint16_t target_bone_index; uint16_t target_bone_index;
/// 再帰回数
uint16_t interations; uint16_t interations;
/// 角度制限
float angle_limit; float angle_limit;
/// 影響下ボーン番号
std::vector<uint16_t> ik_child_bone_index; std::vector<uint16_t> ik_child_bone_index;
void Read(std::istream *stream) void Read(std::istream *stream)
@ -303,7 +267,6 @@ namespace pmd
} }
}; };
/// ボーン枠用の枠名
class PmdBoneDispName class PmdBoneDispName
{ {
public: public:
@ -338,59 +301,36 @@ namespace pmd
} }
}; };
/// 衝突形状
enum class RigidBodyShape : uint8_t enum class RigidBodyShape : uint8_t
{ {
/// 球
Sphere = 0, Sphere = 0,
/// 直方体
Box = 1, Box = 1,
/// カプセル
Cpusel = 2 Cpusel = 2
}; };
/// 剛体タイプ
enum class RigidBodyType : uint8_t enum class RigidBodyType : uint8_t
{ {
/// ボーン追従
BoneConnected = 0, BoneConnected = 0,
/// 物理演算
Physics = 1, Physics = 1,
/// 物理演算(Bone位置合せ)
ConnectedPhysics = 2 ConnectedPhysics = 2
}; };
/// 剛体
class PmdRigidBody class PmdRigidBody
{ {
public: public:
/// 名前
std::string name; std::string name;
/// 関連ボーン番号
uint16_t related_bone_index; uint16_t related_bone_index;
/// グループ番号
uint8_t group_index; uint8_t group_index;
/// マスク
uint16_t mask; uint16_t mask;
/// 形状
RigidBodyShape shape; RigidBodyShape shape;
/// 大きさ
float size[3]; float size[3];
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[3]; float orientation[3];
/// 質量
float weight; float weight;
/// 移動ダンピング
float linear_damping; float linear_damping;
/// 回転ダンピング
float anglar_damping; float anglar_damping;
/// 反発係数
float restitution; float restitution;
/// 摩擦係数
float friction; float friction;
/// 演算方法
RigidBodyType rigid_type; RigidBodyType rigid_type;
void Read(std::istream *stream) void Read(std::istream *stream)
@ -414,31 +354,19 @@ namespace pmd
} }
}; };
/// 剛体の拘束
class PmdConstraint class PmdConstraint
{ {
public: public:
/// 名前
std::string name; std::string name;
/// 剛体Aのインデックス
uint32_t rigid_body_index_a; uint32_t rigid_body_index_a;
/// 剛体Bのインデックス
uint32_t rigid_body_index_b; uint32_t rigid_body_index_b;
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[3]; float orientation[3];
/// 最小移動制限
float linear_lower_limit[3]; float linear_lower_limit[3];
/// 最大移動制限
float linear_upper_limit[3]; float linear_upper_limit[3];
/// 最小回転制限
float angular_lower_limit[3]; float angular_lower_limit[3];
/// 最大回転制限
float angular_upper_limit[3]; float angular_upper_limit[3];
/// 移動に対する復元力
float linear_stiffness[3]; float linear_stiffness[3];
/// 回転に対する復元力
float angular_stiffness[3]; float angular_stiffness[3];
void Read(std::istream *stream) void Read(std::istream *stream)
@ -459,7 +387,6 @@ namespace pmd
} }
}; };
/// PMDモデル
class PmdModel class PmdModel
{ {
public: public:
@ -491,7 +418,6 @@ namespace pmd
return result; return result;
} }
/// ファイルからPmdModelを生成する
static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream) static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
{ {
auto result = mmd::make_unique<PmdModel>(); auto result = mmd::make_unique<PmdModel>();

View File

@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace pmx namespace pmx
{ {
/// インデックス値を読み込む
int ReadIndex(std::istream *stream, int size) int ReadIndex(std::istream *stream, int size)
{ {
switch (size) switch (size)
@ -79,7 +78,6 @@ namespace pmx
} }
} }
/// 文字列を読み込む
std::string ReadString(std::istream *stream, uint8_t encoding) std::string ReadString(std::istream *stream, uint8_t encoding)
{ {
int size; int size;
@ -607,7 +605,6 @@ namespace pmx
this->joints[i].Read(stream, &setting); this->joints[i].Read(stream, &setting);
} }
//// ソフトボディ
//if (this->version == 2.1f) //if (this->version == 2.1f)
//{ //{
// stream->read((char*) &this->soft_body_count, sizeof(int)); // stream->read((char*) &this->soft_body_count, sizeof(int));

View File

@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace pmx namespace pmx
{ {
/// インデックス設定
class PmxSetting class PmxSetting
{ {
public: public:
@ -64,26 +63,17 @@ namespace pmx
, rigidbody_index_size(0) , rigidbody_index_size(0)
{} {}
/// エンコード方式
uint8_t encoding; uint8_t encoding;
/// 追加UV数
uint8_t uv; uint8_t uv;
/// 頂点インデックスサイズ
uint8_t vertex_index_size; uint8_t vertex_index_size;
/// テクスチャインデックスサイズ
uint8_t texture_index_size; uint8_t texture_index_size;
/// マテリアルインデックスサイズ
uint8_t material_index_size; uint8_t material_index_size;
/// ボーンインデックスサイズ
uint8_t bone_index_size; uint8_t bone_index_size;
/// モーフインデックスサイズ
uint8_t morph_index_size; uint8_t morph_index_size;
/// 剛体インデックスサイズ
uint8_t rigidbody_index_size; uint8_t rigidbody_index_size;
void Read(std::istream *stream); void Read(std::istream *stream);
}; };
/// 頂点スキニングタイプ
enum class PmxVertexSkinningType : uint8_t enum class PmxVertexSkinningType : uint8_t
{ {
BDEF1 = 0, BDEF1 = 0,
@ -93,7 +83,6 @@ namespace pmx
QDEF = 4, QDEF = 4,
}; };
/// 頂点スキニング
class PmxVertexSkinning class PmxVertexSkinning
{ {
public: public:
@ -200,7 +189,6 @@ namespace pmx
void Read(std::istream *stresam, PmxSetting *setting); void Read(std::istream *stresam, PmxSetting *setting);
}; };
/// 頂点
class PmxVertex class PmxVertex
{ {
public: public:
@ -219,24 +207,16 @@ namespace pmx
} }
} }
/// 位置
float position[3]; float position[3];
/// 法線
float normal[3]; float normal[3];
/// テクスチャ座標
float uv[2]; float uv[2];
/// 追加テクスチャ座標
float uva[4][4]; float uva[4][4];
/// スキニングタイプ
PmxVertexSkinningType skinning_type; PmxVertexSkinningType skinning_type;
/// スキニング
std::unique_ptr<PmxVertexSkinning> skinning; std::unique_ptr<PmxVertexSkinning> skinning;
/// エッジ倍率
float edge; float edge;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// マテリアル
class PmxMaterial class PmxMaterial
{ {
public: public:
@ -261,42 +241,25 @@ namespace pmx
} }
} }
/// モデル名
std::string material_name; std::string material_name;
/// モデル英名
std::string material_english_name; std::string material_english_name;
/// 減衰色
float diffuse[4]; float diffuse[4];
/// 光沢色
float specular[3]; float specular[3];
/// 光沢度
float specularlity; float specularlity;
/// 環境色
float ambient[3]; float ambient[3];
/// 描画フラグ
uint8_t flag; uint8_t flag;
/// エッジ色
float edge_color[4]; float edge_color[4];
/// エッジサイズ
float edge_size; float edge_size;
/// アルベドテクスチャインデックス
int diffuse_texture_index; int diffuse_texture_index;
/// スフィアテクスチャインデックス
int sphere_texture_index; int sphere_texture_index;
/// スフィアテクスチャ演算モード
uint8_t sphere_op_mode; uint8_t sphere_op_mode;
/// 共有トゥーンフラグ
uint8_t common_toon_flag; uint8_t common_toon_flag;
/// トゥーンテクスチャインデックス
int toon_texture_index; int toon_texture_index;
/// メモ
std::string memo; std::string memo;
/// 頂点インデックス数
int index_count; int index_count;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// リンク
class PmxIkLink class PmxIkLink
{ {
public: public:
@ -310,18 +273,13 @@ namespace pmx
} }
} }
/// リンクボーンインデックス
int link_target; int link_target;
/// 角度制限
uint8_t angle_lock; uint8_t angle_lock;
/// 最大制限角度
float max_radian[3]; float max_radian[3];
/// 最小制限角度
float min_radian[3]; float min_radian[3];
void Read(std::istream *stream, PmxSetting *settingn); void Read(std::istream *stream, PmxSetting *settingn);
}; };
/// ボーン
class PmxBone class PmxBone
{ {
public: public:
@ -347,43 +305,24 @@ namespace pmx
} }
} }
/// ボーン名
std::string bone_name; std::string bone_name;
/// ボーン英名
std::string bone_english_name; std::string bone_english_name;
/// 位置
float position[3]; float position[3];
/// 親ボーンインデックス
int parent_index; int parent_index;
/// 階層
int level; int level;
/// ボーンフラグ
uint16_t bone_flag; uint16_t bone_flag;
/// 座標オフセット(has Target)
float offset[3]; float offset[3];
/// 接続先ボーンインデックス(not has Target)
int target_index; int target_index;
/// 付与親ボーンインデックス
int grant_parent_index; int grant_parent_index;
/// 付与率
float grant_weight; float grant_weight;
/// 固定軸の方向
float lock_axis_orientation[3]; float lock_axis_orientation[3];
/// ローカル軸のX軸方向
float local_axis_x_orientation[3]; float local_axis_x_orientation[3];
/// ローカル軸のY軸方向
float local_axis_y_orientation[3]; float local_axis_y_orientation[3];
/// 外部親変形のkey値
int key; int key;
/// IKターゲットボーン
int ik_target_bone_index; int ik_target_bone_index;
/// IKループ回数
int ik_loop; int ik_loop;
/// IKループ計算時の角度制限(ラジアン)
float ik_loop_angle_limit; float ik_loop_angle_limit;
/// IKリンク数
int ik_link_count; int ik_link_count;
/// IKリンク
std::unique_ptr<PmxIkLink []> ik_links; std::unique_ptr<PmxIkLink []> ik_links;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
@ -543,7 +482,6 @@ namespace pmx
void Read(std::istream *stream, PmxSetting *setting); //override; void Read(std::istream *stream, PmxSetting *setting); //override;
}; };
/// モーフ
class PmxMorph class PmxMorph
{ {
public: public:
@ -551,34 +489,21 @@ namespace pmx
: offset_count(0) : offset_count(0)
{ {
} }
/// モーフ名
std::string morph_name; std::string morph_name;
/// モーフ英名
std::string morph_english_name; std::string morph_english_name;
/// カテゴリ
MorphCategory category; MorphCategory category;
/// モーフタイプ
MorphType morph_type; MorphType morph_type;
/// オフセット数
int offset_count; int offset_count;
/// 頂点モーフ配列
std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets; std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets;
/// UVモーフ配列
std::unique_ptr<PmxMorphUVOffset []> uv_offsets; std::unique_ptr<PmxMorphUVOffset []> uv_offsets;
/// ボーンモーフ配列
std::unique_ptr<PmxMorphBoneOffset []> bone_offsets; std::unique_ptr<PmxMorphBoneOffset []> bone_offsets;
/// マテリアルモーフ配列
std::unique_ptr<PmxMorphMaterialOffset []> material_offsets; std::unique_ptr<PmxMorphMaterialOffset []> material_offsets;
/// グループモーフ配列
std::unique_ptr<PmxMorphGroupOffset []> group_offsets; std::unique_ptr<PmxMorphGroupOffset []> group_offsets;
/// フリップモーフ配列
std::unique_ptr<PmxMorphFlipOffset []> flip_offsets; std::unique_ptr<PmxMorphFlipOffset []> flip_offsets;
/// インパルスモーフ配列
std::unique_ptr<PmxMorphImplusOffset []> implus_offsets; std::unique_ptr<PmxMorphImplusOffset []> implus_offsets;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// 枠内要素
class PmxFrameElement class PmxFrameElement
{ {
public: public:
@ -587,14 +512,11 @@ namespace pmx
, index(0) , index(0)
{ {
} }
/// 要素対象
uint8_t element_target; uint8_t element_target;
/// 要素対象インデックス
int index; int index;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// 表示枠
class PmxFrame class PmxFrame
{ {
public: public:
@ -603,15 +525,10 @@ namespace pmx
, element_count(0) , element_count(0)
{ {
} }
/// 枠名
std::string frame_name; std::string frame_name;
/// 枠英名
std::string frame_english_name; std::string frame_english_name;
/// 特殊枠フラグ
uint8_t frame_flag; uint8_t frame_flag;
/// 枠内要素数
int element_count; int element_count;
/// 枠内要素配列
std::unique_ptr<PmxFrameElement []> elements; std::unique_ptr<PmxFrameElement []> elements;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
@ -637,17 +554,11 @@ namespace pmx
orientation[i] = 0.0f; orientation[i] = 0.0f;
} }
} }
/// 剛体名
std::string girid_body_name; std::string girid_body_name;
/// 剛体英名
std::string girid_body_english_name; std::string girid_body_english_name;
/// 関連ボーンインデックス
int target_bone; int target_bone;
/// グループ
uint8_t group; uint8_t group;
/// マスク
uint16_t mask; uint16_t mask;
/// 形状
uint8_t shape; uint8_t shape;
float size[3]; float size[3];
float position[3]; float position[3];
@ -818,7 +729,6 @@ namespace pmx
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// PMXモデル
class PmxModel class PmxModel
{ {
public: public:
@ -836,65 +746,35 @@ namespace pmx
, soft_body_count(0) , soft_body_count(0)
{} {}
/// バージョン
float version; float version;
/// 設定
PmxSetting setting; PmxSetting setting;
/// モデル名
std::string model_name; std::string model_name;
/// モデル英名
std::string model_english_name; std::string model_english_name;
/// コメント
std::string model_comment; std::string model_comment;
/// 英語コメント
std::string model_english_comment; std::string model_english_comment;
/// 頂点数
int vertex_count; int vertex_count;
/// 頂点配列
std::unique_ptr<PmxVertex []> vertices; std::unique_ptr<PmxVertex []> vertices;
/// インデックス数
int index_count; int index_count;
/// インデックス配列
std::unique_ptr<int []> indices; std::unique_ptr<int []> indices;
/// テクスチャ数
int texture_count; int texture_count;
/// テクスチャ配列
std::unique_ptr< std::string []> textures; std::unique_ptr< std::string []> textures;
/// マテリアル数
int material_count; int material_count;
/// マテリアル
std::unique_ptr<PmxMaterial []> materials; std::unique_ptr<PmxMaterial []> materials;
/// ボーン数
int bone_count; int bone_count;
/// ボーン配列
std::unique_ptr<PmxBone []> bones; std::unique_ptr<PmxBone []> bones;
/// モーフ数
int morph_count; int morph_count;
/// モーフ配列
std::unique_ptr<PmxMorph []> morphs; std::unique_ptr<PmxMorph []> morphs;
/// 表示枠数
int frame_count; int frame_count;
/// 表示枠配列
std::unique_ptr<PmxFrame [] > frames; std::unique_ptr<PmxFrame [] > frames;
/// 剛体数
int rigid_body_count; int rigid_body_count;
/// 剛体配列
std::unique_ptr<PmxRigidBody []> rigid_bodies; std::unique_ptr<PmxRigidBody []> rigid_bodies;
/// ジョイント数
int joint_count; int joint_count;
/// ジョイント配列
std::unique_ptr<PmxJoint []> joints; std::unique_ptr<PmxJoint []> joints;
/// ソフトボディ数
int soft_body_count; int soft_body_count;
/// ソフトボディ配列
std::unique_ptr<PmxSoftBody []> soft_bodies; std::unique_ptr<PmxSoftBody []> soft_bodies;
/// モデル初期化
void Init(); void Init();
/// モデル読み込み
void Read(std::istream *stream); void Read(std::istream *stream);
///// ファイルからモデルの読み込み
//static std::unique_ptr<PmxModel> ReadFromFile(const char *filename); //static std::unique_ptr<PmxModel> ReadFromFile(const char *filename);
///// 入力ストリームからモデルの読み込み
//static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream); //static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream);
}; };
} }

View File

@ -50,19 +50,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace vmd namespace vmd
{ {
/// ボーンフレーム
class VmdBoneFrame class VmdBoneFrame
{ {
public: public:
/// ボーン名
std::string name; std::string name;
/// フレーム番号
int frame; int frame;
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[4]; float orientation[4];
/// 補間曲線
char interpolation[4][4][4]; char interpolation[4][4][4];
void Read(std::istream* stream) void Read(std::istream* stream)
@ -86,15 +80,11 @@ namespace vmd
} }
}; };
/// 表情フレーム
class VmdFaceFrame class VmdFaceFrame
{ {
public: public:
/// 表情名
std::string face_name; std::string face_name;
/// 表情の重み
float weight; float weight;
/// フレーム番号
uint32_t frame; uint32_t frame;
void Read(std::istream* stream) void Read(std::istream* stream)
@ -114,23 +104,15 @@ namespace vmd
} }
}; };
/// カメラフレーム
class VmdCameraFrame class VmdCameraFrame
{ {
public: public:
/// フレーム番号
int frame; int frame;
/// 距離
float distance; float distance;
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[3]; float orientation[3];
/// 補間曲線
char interpolation[6][4]; char interpolation[6][4];
/// 視野角
float angle; float angle;
/// 不明データ
char unknown[3]; char unknown[3];
void Read(std::istream *stream) void Read(std::istream *stream)
@ -156,15 +138,11 @@ namespace vmd
} }
}; };
/// ライトフレーム
class VmdLightFrame class VmdLightFrame
{ {
public: public:
/// フレーム番号
int frame; int frame;
/// 色
float color[3]; float color[3];
/// 位置
float position[3]; float position[3];
void Read(std::istream* stream) void Read(std::istream* stream)
@ -182,7 +160,6 @@ namespace vmd
} }
}; };
/// IKの有効無効
class VmdIkEnable class VmdIkEnable
{ {
public: public:
@ -190,7 +167,6 @@ namespace vmd
bool enable; bool enable;
}; };
/// IKフレーム
class VmdIkFrame class VmdIkFrame
{ {
public: public:
@ -229,23 +205,15 @@ namespace vmd
} }
}; };
/// VMDモーション
class VmdMotion class VmdMotion
{ {
public: public:
/// モデル名
std::string model_name; std::string model_name;
/// バージョン
int version; int version;
/// ボーンフレーム
std::vector<VmdBoneFrame> bone_frames; std::vector<VmdBoneFrame> bone_frames;
/// 表情フレーム
std::vector<VmdFaceFrame> face_frames; std::vector<VmdFaceFrame> face_frames;
/// カメラフレーム
std::vector<VmdCameraFrame> camera_frames; std::vector<VmdCameraFrame> camera_frames;
/// ライトフレーム
std::vector<VmdLightFrame> light_frames; std::vector<VmdLightFrame> light_frames;
/// IKフレーム
std::vector<VmdIkFrame> ik_frames; std::vector<VmdIkFrame> ik_frames;
static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename) static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)

View File

@ -94,7 +94,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
{ {
if (!pIOHandler)return true; if (!pIOHandler)return true;
const char* tokens[] = {"off"}; const char* tokens[] = {"off"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3);
} }
return false; return false;
} }

View File

@ -304,7 +304,7 @@ void ObjFileMtlImporter::createMaterial()
m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
if (m_pModel->m_pCurrentMesh) { if (m_pModel->m_pCurrentMesh) {
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = m_pModel->m_MaterialLib.size() - 1; m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
} }
m_pModel->m_MaterialLib.push_back( name ); m_pModel->m_MaterialLib.push_back( name );
m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;

View File

@ -618,7 +618,7 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pc
} }
streamBuffer.getNextBlock(buffer); streamBuffer.getNextBlock(buffer);
unsigned int bufferSize = buffer.size(); unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
const char* pCur = (char*)&buffer[0]; const char* pCur = (char*)&buffer[0];
if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE))
{ {
@ -1025,7 +1025,7 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end()); buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end());
buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end());
nbuffer.clear(); nbuffer.clear();
bufferSize = buffer.size(); bufferSize = static_cast<unsigned int>(buffer.size());
pCur = (char*)&buffer[0]; pCur = (char*)&buffer[0];
} }
else else

View File

@ -160,6 +160,11 @@ void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsign
unsigned int& num_ref = num_refs[pcNode->mMeshes[i]]; unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
ai_assert(0 != num_ref); ai_assert(0 != num_ref);
--num_ref; --num_ref;
// Save the name of the last mesh
if (num_ref==0)
{
pcMeshOut->mName = pcMesh->mName;
}
if (identity) { if (identity) {
// copy positions without modifying them // copy positions without modifying them
@ -626,9 +631,10 @@ void PretransformVertices::Execute( aiScene* pScene)
// now delete all nodes in the scene and build a new // now delete all nodes in the scene and build a new
// flat node graph with a root node and some level 1 children // flat node graph with a root node and some level 1 children
aiNode* newRoot = new aiNode();
newRoot->mName = pScene->mRootNode->mName;
delete pScene->mRootNode; delete pScene->mRootNode;
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<dummy_root>");
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
{ {
@ -646,7 +652,7 @@ void PretransformVertices::Execute( aiScene* pScene)
{ {
aiNode* pcNode = *nodes = new aiNode(); aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode; pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"mesh_%u",i); pcNode->mName = pScene->mMeshes[i]->mName;
// setup mesh indices // setup mesh indices
pcNode->mNumMeshes = 1; pcNode->mNumMeshes = 1;

View File

@ -201,7 +201,7 @@ static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars)
//ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion); //ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
//*dest = '\0'; //*dest = '\0';
str[str.size()-1] = '\0'; str[str.size()] = '\0';
// Return the final string. // Return the final string.
aiString result = aiString((const char *)&str[0]); aiString result = aiString((const char *)&str[0]);
//delete[] str; //delete[] str;
@ -827,7 +827,7 @@ static void ReadInstance(SIB* sib, StreamReaderLE* stream)
static void CheckVersion(StreamReaderLE* stream) static void CheckVersion(StreamReaderLE* stream)
{ {
uint32_t version = stream->GetU4(); uint32_t version = stream->GetU4();
if ( version != 1 ) { if ( version < 1 || version > 2 ) {
throw DeadlyImportError( "SIB: Unsupported file version." ); throw DeadlyImportError( "SIB: Unsupported file version." );
} }
} }

View File

@ -558,7 +558,7 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector
WordIterator wordItBegin(val, val + strlen(val)); WordIterator wordItBegin(val, val + strlen(val));
WordIterator wordItEnd; WordIterator wordItEnd;
std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atof(match); }); std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return static_cast<float>(atof(match)); });
} }
} }

View File

@ -43,8 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Declares a glTF class to handle gltf/glb files * Declares a glTF class to handle gltf/glb files
* *
* glTF Extensions Support: * glTF Extensions Support:
* KHR_binary_glTF: full * KHR_materials_pbrSpecularGlossiness full
* KHR_materials_common: full
*/ */
#ifndef GLTF2ASSET_H_INC #ifndef GLTF2ASSET_H_INC
#define GLTF2ASSET_H_INC #define GLTF2ASSET_H_INC
@ -130,15 +129,12 @@ namespace glTF2
struct BufferView; // here due to cross-reference struct BufferView; // here due to cross-reference
struct Texture; struct Texture;
struct Light;
struct Skin; struct Skin;
// Vec/matrix types, as raw float arrays // Vec/matrix types, as raw float arrays
typedef float (vec3)[3]; typedef float (vec3)[3];
typedef float (vec4)[4]; typedef float (vec4)[4];
typedef float (mat4)[16]; typedef float (mat4)[16];
namespace Util namespace Util
{ {
@ -166,23 +162,36 @@ namespace glTF2
//! Magic number for GLB files //! Magic number for GLB files
#define AI_GLB_MAGIC_NUMBER "glTF" #define AI_GLB_MAGIC_NUMBER "glTF"
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0
#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0
#define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0
#define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR "$clr.diffuse", 0, 1
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR "$clr.specular", 0, 1
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE aiTextureType_DIFFUSE, 1
#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE aiTextureType_UNKNOWN, 1
#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord"
#define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname"
#define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid"
#define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag"
#define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin"
#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N
#define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N
#ifdef ASSIMP_API #ifdef ASSIMP_API
#include "./../include/assimp/Compiler/pushpack1.h" #include "./../include/assimp/Compiler/pushpack1.h"
#endif #endif
//! For the KHR_binary_glTF extension (binary .glb file)
//! 20-byte header (+ the JSON + a "body" data section)
struct GLB_Header
{
uint8_t magic[4]; //!< Magic number: "glTF"
uint32_t version; //!< Version number
uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
uint32_t sceneLength; //!< Length, in bytes, of the glTF scene
uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum)
} PACK_STRUCT;
#ifdef ASSIMP_API #ifdef ASSIMP_API
#include "./../include/assimp/Compiler/poppack1.h" #include "./../include/assimp/Compiler/poppack1.h"
#endif #endif
@ -232,7 +241,7 @@ namespace glTF2
case ComponentType_UNSIGNED_BYTE: case ComponentType_UNSIGNED_BYTE:
return 1; return 1;
default: default:
throw DeadlyImportError("GLTF: Unsupported Component Type "+t); throw DeadlyImportError("GLTF: Unsupported Component Type " + std::to_string(t));
} }
} }
@ -244,15 +253,17 @@ namespace glTF2
}; };
//! Values for the Sampler::magFilter field //! Values for the Sampler::magFilter field
enum SamplerMagFilter enum class SamplerMagFilter: unsigned int
{ {
UNSET = 0,
SamplerMagFilter_Nearest = 9728, SamplerMagFilter_Nearest = 9728,
SamplerMagFilter_Linear = 9729 SamplerMagFilter_Linear = 9729
}; };
//! Values for the Sampler::minFilter field //! Values for the Sampler::minFilter field
enum SamplerMinFilter enum class SamplerMinFilter: unsigned int
{ {
UNSET = 0,
SamplerMinFilter_Nearest = 9728, SamplerMinFilter_Nearest = 9728,
SamplerMinFilter_Linear = 9729, SamplerMinFilter_Linear = 9729,
SamplerMinFilter_Nearest_Mipmap_Nearest = 9984, SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
@ -262,11 +273,12 @@ namespace glTF2
}; };
//! Values for the Sampler::wrapS and Sampler::wrapT field //! Values for the Sampler::wrapS and Sampler::wrapT field
enum SamplerWrap enum class SamplerWrap: unsigned int
{ {
SamplerWrap_Clamp_To_Edge = 33071, UNSET = 0,
SamplerWrap_Mirrored_Repeat = 33648, Clamp_To_Edge = 33071,
SamplerWrap_Repeat = 10497 Mirrored_Repeat = 33648,
Repeat = 10497
}; };
//! Values for the Texture::format and Texture::internalFormat fields //! Values for the Texture::format and Texture::internalFormat fields
@ -382,6 +394,7 @@ namespace glTF2
struct Object struct Object
{ {
int index; //!< The index of this object within its property container int index; //!< The index of this object within its property container
int oIndex; //!< The original index of this object defined in the JSON
std::string id; //!< The globally unique ID used to reference this object std::string id; //!< The globally unique ID used to reference this object
std::string name; //!< The user-defined name of this object std::string name; //!< The user-defined name of this object
@ -629,7 +642,7 @@ namespace glTF2
float zfar; //! The floating-point distance to the far clipping plane. (required) float zfar; //! The floating-point distance to the far clipping plane. (required)
float znear; //! The floating-point distance to the near clipping plane. (required) float znear; //! The floating-point distance to the near clipping plane. (required)
} ortographic; } ortographic;
}; } cameraProperties;
Camera() {} Camera() {}
void Read(Value& obj, Asset& r); void Read(Value& obj, Asset& r);
@ -668,43 +681,68 @@ namespace glTF2
inline uint8_t* StealData(); inline uint8_t* StealData();
inline void SetData(uint8_t* data, size_t length, Asset& r); inline void SetData(uint8_t* data, size_t length, Asset& r);
}; };
//! Holds a material property that can be a texture or a color const vec4 defaultBaseColor = {1, 1, 1, 1};
struct TexProperty const vec3 defaultEmissiveFactor = {0, 0, 0};
const vec4 defaultDiffuseFactor = {1, 1, 1, 1};
const vec3 defaultSpecularFactor = {1, 1, 1};
struct TextureInfo
{ {
Ref<Texture> texture; Ref<Texture> texture;
vec4 color; unsigned int index;
unsigned int texCoord = 0;
};
struct NormalTextureInfo : TextureInfo
{
float scale = 1;
};
struct OcclusionTextureInfo : TextureInfo
{
float strength = 1;
};
struct PbrMetallicRoughness
{
vec4 baseColorFactor;
TextureInfo baseColorTexture;
TextureInfo metallicRoughnessTexture;
float metallicFactor;
float roughnessFactor;
};
struct PbrSpecularGlossiness
{
vec4 diffuseFactor;
vec3 specularFactor;
float glossinessFactor;
TextureInfo diffuseTexture;
TextureInfo specularGlossinessTexture;
PbrSpecularGlossiness() { SetDefaults(); }
void SetDefaults();
}; };
//! The material appearance of a primitive. //! The material appearance of a primitive.
struct Material : public Object struct Material : public Object
{ {
//Ref<Sampler> source; //!< The ID of the technique. //PBR metallic roughness properties
//std::gltf_unordered_map<std::string, std::string> values; //!< A dictionary object of parameter values. PbrMetallicRoughness pbrMetallicRoughness;
//! Techniques defined by KHR_materials_common
enum Technique
{
Technique_undefined = 0,
Technique_BLINN,
Technique_PHONG,
Technique_LAMBERT,
Technique_CONSTANT
};
TexProperty ambient;
TexProperty diffuse;
TexProperty specular;
TexProperty emission;
Ref<Texture> normal;
//other basic material properties
NormalTextureInfo normalTexture;
OcclusionTextureInfo occlusionTexture;
TextureInfo emissiveTexture;
vec3 emissiveFactor;
std::string alphaMode;
float alphaCutoff;
bool doubleSided; bool doubleSided;
bool transparent;
float transparency;
float shininess;
Technique technique; //extension: KHR_materials_pbrSpecularGlossiness
Nullable<PbrSpecularGlossiness> pbrSpecularGlossiness;
Material() { SetDefaults(); } Material() { SetDefaults(); }
void Read(Value& obj, Asset& r); void Read(Value& obj, Asset& r);
@ -729,92 +767,21 @@ namespace glTF2
Ref<Material> material; Ref<Material> material;
}; };
/// \struct SExtension
/// Extension used for mesh.
struct SExtension
{
/// \enum EType
/// Type of extension.
enum EType
{
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
Compression_Open3DGC,///< Compression of mesh data using Open3DGC algorithm.
#endif
Unknown
};
EType Type;///< Type of extension.
/// \fn SExtension
/// Constructor.
/// \param [in] pType - type of extension.
SExtension(const EType pType)
: Type(pType)
{}
virtual ~SExtension() {
// empty
}
};
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \struct SCompression_Open3DGC
/// Compression of mesh data using Open3DGC algorithm.
struct SCompression_Open3DGC : public SExtension
{
using SExtension::Type;
std::string Buffer;///< ID of "buffer" used for storing compressed data.
size_t Offset;///< Offset in "bufferView" where compressed data are stored.
size_t Count;///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type".
bool Binary;///< If true then "binary" mode is used for coding, if false - "ascii" mode.
size_t IndicesCount;///< Count of indices in mesh.
size_t VerticesCount;///< Count of vertices in mesh.
// AttribType::Value Type;///< Is always "SCALAR".
// ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121).
/// \fn SCompression_Open3DGC
/// Constructor.
SCompression_Open3DGC()
: SExtension(Compression_Open3DGC) {
// empty
}
virtual ~SCompression_Open3DGC() {
// empty
}
};
#endif
std::vector<Primitive> primitives; std::vector<Primitive> primitives;
std::list<SExtension*> Extension;///< List of extensions used in mesh.
Mesh() {} Mesh() {}
/// \fn ~Mesh()
/// Destructor.
~Mesh() { for(std::list<SExtension*>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { delete *it; }; }
/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root) /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
/// Get mesh data from JSON-object and place them to root asset. /// Get mesh data from JSON-object and place them to root asset.
/// \param [in] pJSON_Object - reference to pJSON-object from which data are read. /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
/// \param [out] pAsset_Root - reference to root assed where data will be stored. /// \param [out] pAsset_Root - reference to root assed where data will be stored.
void Read(Value& pJSON_Object, Asset& pAsset_Root); void Read(Value& pJSON_Object, Asset& pAsset_Root);
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
/// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
/// Decode part of "buffer" which encoded with Open3DGC algorithm.
/// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
/// \param [out] pAsset_Root - reference to root assed where data will be stored.
void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root);
#endif
}; };
struct Node : public Object struct Node : public Object
{ {
std::vector< Ref<Node> > children; std::vector< Ref<Node> > children;
std::vector< Ref<Mesh> > meshes; Ref<Mesh> mesh;
Nullable<mat4> matrix; Nullable<mat4> matrix;
Nullable<vec3> translation; Nullable<vec3> translation;
@ -822,10 +789,9 @@ namespace glTF2
Nullable<vec3> scale; Nullable<vec3> scale;
Ref<Camera> camera; Ref<Camera> camera;
Ref<Light> light;
std::vector< Ref<Node> > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy. std::vector< Ref<Node> > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
Ref<Skin> skin; //!< The ID of the skin referenced by this node. Ref<Skin> skin; //!< The ID of the skin referenced by this node.
std::string jointName; //!< Name used when this node is a joint in a skin. std::string jointName; //!< Name used when this node is a joint in a skin.
Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper. Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
@ -843,12 +809,12 @@ namespace glTF2
struct Sampler : public Object struct Sampler : public Object
{ {
SamplerMagFilter magFilter; //!< The texture magnification filter. (required) SamplerMagFilter magFilter; //!< The texture magnification filter.
SamplerMinFilter minFilter; //!< The texture minification filter. (required) SamplerMinFilter minFilter; //!< The texture minification filter.
SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required) SamplerWrap wrapS; //!< The texture wrapping in the S direction.
SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required) SamplerWrap wrapT; //!< The texture wrapping in the T direction.
Sampler() {} Sampler() { SetDefaults(); }
void Read(Value& obj, Asset& r); void Read(Value& obj, Asset& r);
void SetDefaults(); void SetDefaults();
}; };
@ -878,27 +844,6 @@ namespace glTF2
void Read(Value& obj, Asset& r); void Read(Value& obj, Asset& r);
}; };
struct Technique : public Object
{
struct Parameters
{
};
struct States
{
};
struct Functions
{
};
Technique() {}
void Read(Value& obj, Asset& r);
};
//! A texture and its sampler. //! A texture and its sampler.
struct Texture : public Object struct Texture : public Object
{ {
@ -915,35 +860,6 @@ namespace glTF2
void Read(Value& obj, Asset& r); void Read(Value& obj, Asset& r);
}; };
//! A light (from KHR_materials_common extension)
struct Light : public Object
{
enum Type
{
Type_undefined,
Type_ambient,
Type_directional,
Type_point,
Type_spot
};
Type type;
vec4 color;
float distance;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
float falloffAngle;
float falloffExponent;
Light() {}
void Read(Value& obj, Asset& r);
void SetDefaults();
};
struct Animation : public Object struct Animation : public Object
{ {
struct AnimSampler { struct AnimSampler {
@ -1025,14 +941,16 @@ namespace glTF2
friend class Asset; friend class Asset;
friend class AssetWriter; friend class AssetWriter;
typedef typename std::gltf_unordered_map< std::string, unsigned int > Dict; typedef typename std::gltf_unordered_map< unsigned int, unsigned int > Dict;
typedef typename std::gltf_unordered_map< std::string, unsigned int > IdDict;
std::vector<T*> mObjs; //! The read objects std::vector<T*> mObjs; //! The read objects
Dict mObjsById; //! The read objects accessible by id Dict mObjsByOIndex; //! The read objects accessible by original index
const char* mDictId; //! ID of the dictionary object IdDict mObjsById; //! The read objects accessible by id
const char* mExtId; //! ID of the extension defining the dictionary const char* mDictId; //! ID of the dictionary object
Value* mDict; //! JSON dictionary object const char* mExtId; //! ID of the extension defining the dictionary
Asset& mAsset; //! The asset instance Value* mDict; //! JSON dictionary object
Asset& mAsset; //! The asset instance
void AttachToDocument(Document& doc); void AttachToDocument(Document& doc);
void DetachFromDocument(); void DetachFromDocument();
@ -1046,9 +964,10 @@ namespace glTF2
LazyDict(Asset& asset, const char* dictId, const char* extId = 0); LazyDict(Asset& asset, const char* dictId, const char* extId = 0);
~LazyDict(); ~LazyDict();
Ref<T> Get(const char* id); Ref<T> Retrieve(unsigned int i);
Ref<T> Get(unsigned int i); Ref<T> Get(unsigned int i);
Ref<T> Get(const std::string& pID) { return Get(pID.c_str()); } Ref<T> Get(const char* id);
Ref<T> Create(const char* id); Ref<T> Create(const char* id);
Ref<T> Create(const std::string& id) Ref<T> Create(const std::string& id)
@ -1067,22 +986,17 @@ namespace glTF2
{ {
std::string copyright; //!< A copyright message suitable for display to credit the content creator. std::string copyright; //!< A copyright message suitable for display to credit the content creator.
std::string generator; //!< Tool that generated this glTF model.Useful for debugging. std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false)
struct { struct {
std::string api; //!< Specifies the target rendering API (default: "WebGL") std::string api; //!< Specifies the target rendering API (default: "WebGL")
std::string version; //!< Specifies the target rendering API (default: "1.0.3") std::string version; //!< Specifies the target rendering API (default: "1.0.3")
} profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
float version; //!< The glTF format version std::string version; //!< The glTF format version
void Read(Document& doc); void Read(Document& doc);
AssetMetadata() AssetMetadata() : version("") {}
: premultipliedAlpha(false)
, version(0)
{
}
}; };
// //
@ -1123,8 +1037,7 @@ namespace glTF2
//! Keeps info about the enabled extensions //! Keeps info about the enabled extensions
struct Extensions struct Extensions
{ {
bool KHR_binary_glTF; bool KHR_materials_pbrSpecularGlossiness;
bool KHR_materials_common;
} extensionsUsed; } extensionsUsed;
@ -1142,16 +1055,11 @@ namespace glTF2
LazyDict<Material> materials; LazyDict<Material> materials;
LazyDict<Mesh> meshes; LazyDict<Mesh> meshes;
LazyDict<Node> nodes; LazyDict<Node> nodes;
//LazyDict<Program> programs;
LazyDict<Sampler> samplers; LazyDict<Sampler> samplers;
LazyDict<Scene> scenes; LazyDict<Scene> scenes;
//LazyDict<Shader> shaders; LazyDict<Skin> skins;
LazyDict<Skin> skins;
//LazyDict<Technique> techniques;
LazyDict<Texture> textures; LazyDict<Texture> textures;
LazyDict<Light> lights; // KHR_materials_common ext
Ref<Scene> scene; Ref<Scene> scene;
public: public:
@ -1167,23 +1075,16 @@ namespace glTF2
, materials (*this, "materials") , materials (*this, "materials")
, meshes (*this, "meshes") , meshes (*this, "meshes")
, nodes (*this, "nodes") , nodes (*this, "nodes")
//, programs (*this, "programs")
, samplers (*this, "samplers") , samplers (*this, "samplers")
, scenes (*this, "scenes") , scenes (*this, "scenes")
//, shaders (*this, "shaders") , skins (*this, "skins")
, skins (*this, "skins")
//, techniques (*this, "techniques")
, textures (*this, "textures") , textures (*this, "textures")
, lights (*this, "lights", "KHR_materials_common")
{ {
memset(&extensionsUsed, 0, sizeof(extensionsUsed)); memset(&extensionsUsed, 0, sizeof(extensionsUsed));
} }
//! Main function //! Main function
void Load(const std::string& file, bool isBinary = false); void Load(const std::string& file);
//! Enables the "KHR_binary_glTF" extension on the asset
void SetAsBinary();
//! Search for an available name, starting from the given strings //! Search for an available name, starting from the given strings
std::string FindUniqueID(const std::string& str, const char* suffix); std::string FindUniqueID(const std::string& str, const char* suffix);
@ -1192,11 +1093,8 @@ namespace glTF2
{ return mBodyBuffer; } { return mBodyBuffer; }
private: private:
void ReadBinaryHeader(IOStream& stream);
void ReadExtensionsUsed(Document& doc); void ReadExtensionsUsed(Document& doc);
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
}; };

View File

@ -1,4 +1,4 @@
/* /*
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -44,11 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Header files, Assimp // Header files, Assimp
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
// Header files, Open3DGC.
# include <Open3DGC/o3dgcSC3DMCDecoder.h>
#endif
using namespace Assimp; using namespace Assimp;
namespace glTF2 { namespace glTF2 {
@ -128,6 +123,18 @@ namespace {
return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
} }
inline Value* FindNumber(Value& val, const char* id)
{
Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
}
inline Value* FindUInt(Value& val, const char* id)
{
Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd() && it->value.IsUint()) ? &it->value : 0;
}
inline Value* FindArray(Value& val, const char* id) inline Value* FindArray(Value& val, const char* id)
{ {
Value::MemberIterator it = val.FindMember(id); Value::MemberIterator it = val.FindMember(id);
@ -176,7 +183,7 @@ inline void LazyDict<T>::AttachToDocument(Document& doc)
} }
if (container) { if (container) {
mDict = FindObject(*container, mDictId); mDict = FindArray(*container, mDictId);
} }
} }
@ -187,18 +194,11 @@ inline void LazyDict<T>::DetachFromDocument()
} }
template<class T> template<class T>
Ref<T> LazyDict<T>::Get(unsigned int i) Ref<T> LazyDict<T>::Retrieve(unsigned int i)
{ {
return Ref<T>(mObjs, i);
}
template<class T> typename Dict::iterator it = mObjsByOIndex.find(i);
Ref<T> LazyDict<T>::Get(const char* id) if (it != mObjsByOIndex.end()) {// already created?
{
id = T::TranslateId(mAsset, id);
typename Dict::iterator it = mObjsById.find(id);
if (it != mObjsById.end()) { // already created?
return Ref<T>(mObjs, it->second); return Ref<T>(mObjs, it->second);
} }
@ -207,27 +207,52 @@ Ref<T> LazyDict<T>::Get(const char* id)
throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\""); throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\"");
} }
Value::MemberIterator obj = mDict->FindMember(id); if (!mDict->IsArray()) {
if (obj == mDict->MemberEnd()) { throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\"");
throw DeadlyImportError("GLTF: Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\""); }
}
if (!obj->value.IsObject()) { Value &obj = (*mDict)[i];
throw DeadlyImportError("GLTF: Object with id \"" + std::string(id) + "\" is not a JSON object");
if (!obj.IsObject()) {
throw DeadlyImportError("GLTF: Object at index \"" + std::to_string(i) + "\" is not a JSON object");
} }
// create an instance of the given type
T* inst = new T(); T* inst = new T();
inst->id = id; inst->id = std::string(mDictId) + "_" + std::to_string(i);
ReadMember(obj->value, "name", inst->name); inst->oIndex = i;
inst->Read(obj->value, mAsset); ReadMember(obj, "name", inst->name);
inst->Read(obj, mAsset);
return Add(inst); return Add(inst);
} }
template<class T>
Ref<T> LazyDict<T>::Get(unsigned int i)
{
return Ref<T>(mObjs, i);
}
template<class T>
Ref<T> LazyDict<T>::Get(const char* id)
{
id = T::TranslateId(mAsset, id);
typename IdDict::iterator it = mObjsById.find(id);
if (it != mObjsById.end()) { // already created?
return Ref<T>(mObjs, it->second);
}
return Ref<T>();
}
template<class T> template<class T>
Ref<T> LazyDict<T>::Add(T* obj) Ref<T> LazyDict<T>::Add(T* obj)
{ {
unsigned int idx = unsigned(mObjs.size()); unsigned int idx = unsigned(mObjs.size());
mObjs.push_back(obj); mObjs.push_back(obj);
mObjsByOIndex[obj->oIndex] = idx;
mObjsById[obj->id] = idx; mObjsById[obj->id] = idx;
mAsset.mUsedIds[obj->id] = true; mAsset.mUsedIds[obj->id] = true;
return Ref<T>(mObjs, idx); return Ref<T>(mObjs, idx);
@ -241,8 +266,10 @@ Ref<T> LazyDict<T>::Create(const char* id)
throw DeadlyImportError("GLTF: two objects with the same ID exist"); throw DeadlyImportError("GLTF: two objects with the same ID exist");
} }
T* inst = new T(); T* inst = new T();
unsigned int idx = unsigned(mObjs.size());
inst->id = id; inst->id = id;
inst->index = mObjs.size(); inst->index = idx;
inst->oIndex = idx;
return Add(inst); return Add(inst);
} }
@ -263,11 +290,6 @@ inline Buffer::~Buffer()
inline const char* Buffer::TranslateId(Asset& r, const char* id) inline const char* Buffer::TranslateId(Asset& r, const char* id)
{ {
// Compatibility with old spec
if (r.extensionsUsed.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) {
return "binary_glTF";
}
return id; return id;
} }
@ -310,7 +332,9 @@ inline void Buffer::Read(Value& obj, Asset& r)
} }
else { // Local file else { // Local file
if (byteLength > 0) { if (byteLength > 0) {
IOStream* file = r.OpenFile(uri, "rb"); std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : "";
IOStream* file = r.OpenFile(dir + uri, "rb");
if (file) { if (file) {
bool ok = LoadFromStream(*file, byteLength); bool ok = LoadFromStream(*file, byteLength);
delete file; delete file;
@ -437,9 +461,9 @@ inline void Buffer::Grow(size_t amount)
inline void BufferView::Read(Value& obj, Asset& r) inline void BufferView::Read(Value& obj, Asset& r)
{ {
const char* bufferId = MemberOrDefault<const char*>(obj, "buffer", 0);
if (bufferId) { if (Value* bufferVal = FindUInt(obj, "buffer")) {
buffer = r.buffers.Get(bufferId); buffer = r.buffers.Retrieve(bufferVal->GetUint());
} }
byteOffset = MemberOrDefault(obj, "byteOffset", 0u); byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
@ -452,9 +476,9 @@ inline void BufferView::Read(Value& obj, Asset& r)
inline void Accessor::Read(Value& obj, Asset& r) inline void Accessor::Read(Value& obj, Asset& r)
{ {
const char* bufferViewId = MemberOrDefault<const char*>(obj, "bufferView", 0);
if (bufferViewId) { if (Value* bufferViewVal = FindUInt(obj, "bufferView")) {
bufferView = r.bufferViews.Get(bufferViewId); bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
} }
byteOffset = MemberOrDefault(obj, "byteOffset", 0u); byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
@ -601,29 +625,6 @@ inline Image::Image()
inline void Image::Read(Value& obj, Asset& r) inline void Image::Read(Value& obj, Asset& r)
{ {
// Check for extensions first (to detect binary embedded data)
if (Value* extensions = FindObject(obj, "extensions")) {
if (r.extensionsUsed.KHR_binary_glTF) {
if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) {
width = MemberOrDefault(*ext, "width", 0);
height = MemberOrDefault(*ext, "height", 0);
ReadMember(*ext, "mimeType", mimeType);
const char* bufferViewId;
if (ReadMember(*ext, "bufferView", bufferViewId)) {
Ref<BufferView> bv = r.bufferViews.Get(bufferViewId);
if (bv) {
mDataLength = bv->byteLength;
mData = new uint8_t[mDataLength];
memcpy(mData, bv->buffer->GetPointer() + bv->byteOffset, mDataLength);
}
}
}
}
}
if (!mDataLength) { if (!mDataLength) {
if (Value* uri = FindString(obj, "uri")) { if (Value* uri = FindString(obj, "uri")) {
const char* uristr = uri->GetString(); const char* uristr = uri->GetString();
@ -671,6 +672,7 @@ inline void Sampler::Read(Value& obj, Asset& r)
{ {
SetDefaults(); SetDefaults();
ReadMember(obj, "name", name);
ReadMember(obj, "magFilter", magFilter); ReadMember(obj, "magFilter", magFilter);
ReadMember(obj, "minFilter", minFilter); ReadMember(obj, "minFilter", minFilter);
ReadMember(obj, "wrapS", wrapS); ReadMember(obj, "wrapS", wrapS);
@ -679,34 +681,61 @@ inline void Sampler::Read(Value& obj, Asset& r)
inline void Sampler::SetDefaults() inline void Sampler::SetDefaults()
{ {
magFilter = SamplerMagFilter_Linear; //only wrapping modes have defaults
minFilter = SamplerMinFilter_Linear; wrapS = SamplerWrap::Repeat;
wrapS = SamplerWrap_Repeat; wrapT = SamplerWrap::Repeat;
wrapT = SamplerWrap_Repeat; magFilter = SamplerMagFilter::UNSET;
minFilter = SamplerMinFilter::UNSET;
} }
inline void Texture::Read(Value& obj, Asset& r) inline void Texture::Read(Value& obj, Asset& r)
{ {
const char* sourcestr; if (Value* sourceVal = FindUInt(obj, "source")) {
if (ReadMember(obj, "source", sourcestr)) { source = r.images.Retrieve(sourceVal->GetUint());
source = r.images.Get(sourcestr);
} }
const char* samplerstr; if (Value* samplerVal = FindUInt(obj, "sampler")) {
if (ReadMember(obj, "sampler", samplerstr)) { sampler = r.samplers.Retrieve(samplerVal->GetUint());
sampler = r.samplers.Get(samplerstr);
} }
} }
namespace { namespace {
inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out) inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out)
{
if (Value* index = FindUInt(*prop, "index")) {
out.texture = r.textures.Retrieve(index->GetUint());
}
if (Value* texcoord = FindUInt(*prop, "texCoord")) {
out.texCoord = texcoord->GetUint();
}
}
inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, TextureInfo& out)
{ {
if (Value* prop = FindMember(vals, propName)) { if (Value* prop = FindMember(vals, propName)) {
if (prop->IsString()) { SetTextureProperties(r, prop, out);
out.texture = r.textures.Get(prop->GetString()); }
}
inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, NormalTextureInfo& out)
{
if (Value* prop = FindMember(vals, propName)) {
SetTextureProperties(r, prop, out);
if (Value* scale = FindNumber(*prop, "scale")) {
out.scale = scale->GetDouble();
} }
else { }
ReadValue(*prop, out.color); }
inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, OcclusionTextureInfo& out)
{
if (Value* prop = FindMember(vals, propName)) {
SetTextureProperties(r, prop, out);
if (Value* strength = FindNumber(*prop, "strength")) {
out.strength = strength->GetDouble();
} }
} }
} }
@ -716,59 +745,67 @@ inline void Material::Read(Value& material, Asset& r)
{ {
SetDefaults(); SetDefaults();
if (Value* values = FindObject(material, "values")) { if (Value* pbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) {
ReadMaterialProperty(r, *values, "ambient", this->ambient); ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor);
ReadMaterialProperty(r, *values, "diffuse", this->diffuse); ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture);
ReadMaterialProperty(r, *values, "specular", this->specular); ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture);
ReadMember(*pbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor);
ReadMember(*values, "transparency", transparency); ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor);
ReadMember(*values, "shininess", shininess);
} }
ReadTextureProperty(r, material, "normalTexture", this->normalTexture);
ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture);
ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture);
ReadMember(material, "emissiveFactor", this->emissiveFactor);
ReadMember(material, "doubleSided", this->doubleSided);
ReadMember(material, "alphaMode", this->alphaMode);
ReadMember(material, "alphaCutoff", this->alphaCutoff);
if (Value* extensions = FindObject(material, "extensions")) { if (Value* extensions = FindObject(material, "extensions")) {
if (r.extensionsUsed.KHR_materials_common) { if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) {
if (Value* tnq = FindString(*ext, "technique")) { PbrSpecularGlossiness pbrSG;
const char* t = tnq->GetString();
if (strcmp(t, "BLINN") == 0) technique = Technique_BLINN;
else if (strcmp(t, "PHONG") == 0) technique = Technique_PHONG;
else if (strcmp(t, "LAMBERT") == 0) technique = Technique_LAMBERT;
else if (strcmp(t, "CONSTANT") == 0) technique = Technique_CONSTANT;
}
if (Value* values = FindObject(*ext, "values")) { ReadMember(*pbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor);
ReadMaterialProperty(r, *values, "ambient", this->ambient); ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture);
ReadMaterialProperty(r, *values, "diffuse", this->diffuse); ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture);
ReadMaterialProperty(r, *values, "specular", this->specular); ReadMember(*pbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor);
ReadMember(*pbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor);
ReadMember(*values, "doubleSided", doubleSided); this->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
ReadMember(*values, "transparent", transparent);
ReadMember(*values, "transparency", transparency);
ReadMember(*values, "shininess", shininess);
}
} }
} }
} }
} }
namespace { namespace {
void SetVector(vec4& v, float x, float y, float z, float w) void SetVector(vec4& v, const float(&in)[4])
{ v[0] = x; v[1] = y; v[2] = z; v[3] = w; } { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; v[3] = in[3]; }
void SetVector(vec3& v, const float(&in)[3])
{ v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; }
} }
inline void Material::SetDefaults() inline void Material::SetDefaults()
{ {
SetVector(ambient.color, 0, 0, 0, 1); //pbr materials
SetVector(diffuse.color, 0, 0, 0, 1); SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor);
SetVector(specular.color, 0, 0, 0, 1); pbrMetallicRoughness.metallicFactor = 1.0;
SetVector(emission.color, 0, 0, 0, 1); pbrMetallicRoughness.roughnessFactor = 1.0;
SetVector(emissiveFactor, defaultEmissiveFactor);
alphaMode = "OPAQUE";
alphaCutoff = 0.5;
doubleSided = false; doubleSided = false;
transparent = false; }
transparency = 1.0;
shininess = 0.0;
technique = Technique_undefined; inline void PbrSpecularGlossiness::SetDefaults()
{
//pbrSpecularGlossiness properties
SetVector(diffuseFactor, defaultDiffuseFactor);
SetVector(specularFactor, defaultSpecularFactor);
glossinessFactor = 1.0;
} }
namespace { namespace {
@ -808,6 +845,10 @@ namespace {
inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
{ {
if (Value* name = FindMember(pJSON_Object, "name")) {
this->name = name->GetString();
}
/****************** Mesh primitives ******************/ /****************** Mesh primitives ******************/
if (Value* primitives = FindArray(pJSON_Object, "primitives")) { if (Value* primitives = FindArray(pJSON_Object, "primitives")) {
this->primitives.resize(primitives->Size()); this->primitives.resize(primitives->Size());
@ -819,7 +860,7 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
if (Value* attrs = FindObject(primitive, "attributes")) { if (Value* attrs = FindObject(primitive, "attributes")) {
for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) {
if (!it->value.IsString()) continue; if (!it->value.IsUint()) continue;
const char* attr = it->name.GetString(); const char* attr = it->name.GetString();
// Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX,
// and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc.
@ -829,262 +870,22 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
if (GetAttribVector(prim, attr, vec, undPos)) { if (GetAttribVector(prim, attr, vec, undPos)) {
size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
if ((*vec).size() <= idx) (*vec).resize(idx + 1); if ((*vec).size() <= idx) (*vec).resize(idx + 1);
(*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetString()); (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint());
} }
} }
} }
if (Value* indices = FindString(primitive, "indices")) { if (Value* indices = FindUInt(primitive, "indices")) {
prim.indices = pAsset_Root.accessors.Get(indices->GetString()); prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
} }
if (Value* material = FindString(primitive, "material")) { if (Value* material = FindUInt(primitive, "material")) {
prim.material = pAsset_Root.materials.Get(material->GetString()); prim.material = pAsset_Root.materials.Retrieve(material->GetUint());
} }
} }
} }
/****************** Mesh extensions ******************/
Value* json_extensions = FindObject(pJSON_Object, "extensions");
if(json_extensions == nullptr) goto mr_skip_extensions;
for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); it_memb++)
{
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
if(it_memb->name.GetString() == std::string("Open3DGC-compression"))
{
// Search for compressed data.
// Compressed data contain description of part of "buffer" which is encoded. This part must be decoded and
// new data will replace old encoded part by request. In fact \"compressedData\" is kind of "accessor" structure.
Value* comp_data = FindObject(it_memb->value, "compressedData");
if(comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\".");
DefaultLogger::get()->info("GLTF: Decompressing Open3DGC data.");
/************** Read data from JSON-document **************/
#define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \
if(!ReadMember(*comp_data, pFieldName, pOut)) \
{ \
throw DeadlyImportError(std::string("GLTF: \"compressedData\" must has \"") + pFieldName + "\"."); \
}
const char* mode_str;
const char* type_str;
ComponentType component_type;
SCompression_Open3DGC* ext_o3dgc = new SCompression_Open3DGC;
MESH_READ_COMPRESSEDDATA_MEMBER("buffer", ext_o3dgc->Buffer);
MESH_READ_COMPRESSEDDATA_MEMBER("byteOffset", ext_o3dgc->Offset);
MESH_READ_COMPRESSEDDATA_MEMBER("componentType", component_type);
MESH_READ_COMPRESSEDDATA_MEMBER("type", type_str);
MESH_READ_COMPRESSEDDATA_MEMBER("count", ext_o3dgc->Count);
MESH_READ_COMPRESSEDDATA_MEMBER("mode", mode_str);
MESH_READ_COMPRESSEDDATA_MEMBER("indicesCount", ext_o3dgc->IndicesCount);
MESH_READ_COMPRESSEDDATA_MEMBER("verticesCount", ext_o3dgc->VerticesCount);
#undef MESH_READ_COMPRESSEDDATA_MEMBER
// Check some values
if(strcmp(type_str, "SCALAR")) throw DeadlyImportError("GLTF: only \"SCALAR\" type is supported for compressed data.");
if(component_type != ComponentType_UNSIGNED_BYTE) throw DeadlyImportError("GLTF: only \"UNSIGNED_BYTE\" component type is supported for compressed data.");
// Set read/write data mode.
if(strcmp(mode_str, "binary") == 0)
ext_o3dgc->Binary = true;
else if(strcmp(mode_str, "ascii") == 0)
ext_o3dgc->Binary = false;
else
throw DeadlyImportError(std::string("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"") + mode_str + "\".");
/************************ Decoding ************************/
Decode_O3DGC(*ext_o3dgc, pAsset_Root);
Extension.push_back(ext_o3dgc);// store info in mesh extensions list.
}// if(it_memb->name.GetString() == "Open3DGC-compression")
else
#endif
{
throw DeadlyImportError(std::string("GLTF: Unknown mesh extension: \"") + it_memb->name.GetString() + "\".");
}
}// for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++)
mr_skip_extensions:
return;// After label some operators must be present.
} }
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
{
typedef unsigned short IndicesType;///< \sa glTFExporter::ExportMeshes.
o3dgc::SC3DMCDecoder<IndicesType> decoder;
o3dgc::IndexedFaceSet<IndicesType> ifs;
o3dgc::BinaryStream bstream;
uint8_t* decoded_data;
size_t decoded_data_size = 0;
Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer);
// Read data from buffer and place it in BinaryStream for decoder.
// Just "Count" because always is used type equivalent to uint8_t.
bstream.LoadFromBuffer(&buf->GetPointer()[pCompression_Open3DGC.Offset], static_cast<unsigned long>(pCompression_Open3DGC.Count));
// After decoding header we can get size of primitives.
if(decoder.DecodeHeader(ifs, bstream) != o3dgc::O3DGC_OK) throw DeadlyImportError("GLTF: can not decode Open3DGC header.");
/****************** Get sizes of arrays and check sizes ******************/
// Note. See "Limitations for meshes when using Open3DGC-compression".
// Indices
size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note.
if(primitives[0].indices->count != size_coordindex)
throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + std::to_string(size_coordindex) +
") not equal to uncompressed (" + std::to_string(primitives[0].indices->count) + ").");
size_coordindex *= sizeof(IndicesType);
// Coordinates
size_t size_coord = ifs.GetNCoord();// See float attributes note.
if(primitives[0].attributes.position[0]->count != size_coord)
throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + std::to_string(size_coord) +
") not equal to uncompressed (" + std::to_string(primitives[0].attributes.position[0]->count) + ").");
size_coord *= 3 * sizeof(float);
// Normals
size_t size_normal = ifs.GetNNormal();// See float attributes note.
if(primitives[0].attributes.normal[0]->count != size_normal)
throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + std::to_string(size_normal) +
") not equal to uncompressed (" + std::to_string(primitives[0].attributes.normal[0]->count) + ").");
size_normal *= 3 * sizeof(float);
// Additional attributes.
std::vector<size_t> size_floatattr;
std::vector<size_t> size_intattr;
size_floatattr.resize(ifs.GetNumFloatAttributes());
size_intattr.resize(ifs.GetNumIntAttributes());
decoded_data_size = size_coordindex + size_coord + size_normal;
for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++)
{
// size = number_of_elements * components_per_element * size_of_component.
// Note. But as you can see above, at first we are use this variable in meaning "count". After checking count of objects...
size_t tval = ifs.GetNFloatAttribute(static_cast<unsigned long>(idx));
switch(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))
{
case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
// Check situation when encoded data contain texture coordinates but primitive not.
if(idx_texcoord < primitives[0].attributes.texcoord.size())
{
if(primitives[0].attributes.texcoord[idx]->count != tval)
throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + std::to_string(tval) +
") not equal to uncompressed (" + std::to_string(primitives[0].attributes.texcoord[idx]->count) + ").");
idx_texcoord++;
}
else
{
ifs.SetNFloatAttribute(static_cast<unsigned long>(idx), 0ul);// Disable decoding this attribute.
}
break;
default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
}
tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real);// After checking count of objects we can get size of array.
size_floatattr[idx] = tval;
decoded_data_size += tval;
}
for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++)
{
// size = number_of_elements * components_per_element * size_of_component. See float attributes note.
size_t tval = ifs.GetNIntAttribute(static_cast<unsigned long>(idx));
switch( ifs.GetIntAttributeType(static_cast<unsigned long>(idx) ) )
{
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
break;
default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
}
tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long);// See float attributes note.
size_intattr[idx] = tval;
decoded_data_size += tval;
}
// Create array for decoded data.
decoded_data = new uint8_t[decoded_data_size];
/****************** Set right array regions for decoder ******************/
auto get_buf_offset = [](Ref<Accessor>& pAccessor) -> size_t { return pAccessor->byteOffset + pAccessor->bufferView->byteOffset; };
// Indices
ifs.SetCoordIndex((IndicesType* const)(decoded_data + get_buf_offset(primitives[0].indices)));
// Coordinates
ifs.SetCoord((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.position[0])));
// Normals
if(size_normal)
{
ifs.SetNormal((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0])));
}
for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++)
{
switch(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))
{
case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD:
if(idx_texcoord < primitives[0].attributes.texcoord.size())
{
// See above about absent attributes.
ifs.SetFloatAttribute(static_cast<unsigned long>(idx), (o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx])));
idx_texcoord++;
}
break;
default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))));
}
}
for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) {
switch(ifs.GetIntAttributeType(static_cast<unsigned int>(idx))) {
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN:
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX:
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID:
case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID:
break;
// ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint)));
default:
throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx))));
}
}
//
// Decode data
//
if ( decoder.DecodePayload( ifs, bstream ) != o3dgc::O3DGC_OK ) {
throw DeadlyImportError( "GLTF: can not decode Open3DGC data." );
}
// Set encoded region for "buffer".
buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id);
// No. Do not delete "output_data". After calling "EncodedRegion_Mark" bufferView is owner of "output_data".
// "delete [] output_data;"
}
#endif
inline void Camera::Read(Value& obj, Asset& r) inline void Camera::Read(Value& obj, Asset& r)
{ {
type = MemberOrDefault(obj, "type", Camera::Perspective); type = MemberOrDefault(obj, "type", Camera::Perspective);
@ -1095,80 +896,34 @@ inline void Camera::Read(Value& obj, Asset& r)
if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters"); if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters");
if (type == Camera::Perspective) { if (type == Camera::Perspective) {
perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f); cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f); cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f);
perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
perspective.znear = MemberOrDefault(*it, "znear", 0.01f); cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
} }
else { else {
ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f);
} }
} }
inline void Light::Read(Value& obj, Asset& r)
{
SetDefaults();
if (Value* type = FindString(obj, "type")) {
const char* t = type->GetString();
if (strcmp(t, "ambient") == 0) this->type = Type_ambient;
else if (strcmp(t, "directional") == 0) this->type = Type_directional;
else if (strcmp(t, "point") == 0) this->type = Type_point;
else if (strcmp(t, "spot") == 0) this->type = Type_spot;
if (this->type != Type_undefined) {
if (Value* vals = FindString(obj, t)) {
ReadMember(*vals, "color", color);
ReadMember(*vals, "constantAttenuation", constantAttenuation);
ReadMember(*vals, "linearAttenuation", linearAttenuation);
ReadMember(*vals, "quadraticAttenuation", quadraticAttenuation);
ReadMember(*vals, "distance", distance);
ReadMember(*vals, "falloffAngle", falloffAngle);
ReadMember(*vals, "falloffExponent", falloffExponent);
}
}
}
}
inline void Light::SetDefaults()
{
#ifndef M_PI
const float M_PI = 3.14159265358979323846f;
#endif
type = Type_undefined;
SetVector(color, 0.f, 0.f, 0.f, 1.f);
constantAttenuation = 0.f;
linearAttenuation = 1.f;
quadraticAttenuation = 1.f;
distance = 0.f;
falloffAngle = static_cast<float>(M_PI / 2.f);
falloffExponent = 0.f;
}
inline void Node::Read(Value& obj, Asset& r) inline void Node::Read(Value& obj, Asset& r)
{ {
if (Value* children = FindArray(obj, "children")) { if (Value* children = FindArray(obj, "children")) {
this->children.reserve(children->Size()); this->children.reserve(children->Size());
for (unsigned int i = 0; i < children->Size(); ++i) { for (unsigned int i = 0; i < children->Size(); ++i) {
Value& child = (*children)[i]; Value& child = (*children)[i];
if (child.IsString()) { if (child.IsUint()) {
// get/create the child node // get/create the child node
Ref<Node> chn = r.nodes.Get(child.GetString()); Ref<Node> chn = r.nodes.Retrieve(child.GetUint());
if (chn) this->children.push_back(chn); if (chn) this->children.push_back(chn);
} }
} }
} }
if (Value* matrix = FindArray(obj, "matrix")) { if (Value* matrix = FindArray(obj, "matrix")) {
ReadValue(*matrix, this->matrix); ReadValue(*matrix, this->matrix);
} }
@ -1178,64 +933,46 @@ inline void Node::Read(Value& obj, Asset& r)
ReadMember(obj, "rotation", rotation); ReadMember(obj, "rotation", rotation);
} }
if (Value* meshes = FindArray(obj, "meshes")) { if (Value* mesh = FindUInt(obj, "mesh")) {
unsigned numMeshes = (unsigned)meshes->Size(); Ref<Mesh> meshRef = r.meshes.Retrieve((*mesh).GetUint());
std::vector<unsigned int> meshList; if (meshRef) this->mesh = meshRef;
this->meshes.reserve(numMeshes);
for (unsigned i = 0; i < numMeshes; ++i) {
if ((*meshes)[i].IsString()) {
Ref<Mesh> mesh = r.meshes.Get((*meshes)[i].GetString());
if (mesh) this->meshes.push_back(mesh);
}
}
} }
if (Value* camera = FindString(obj, "camera")) { if (Value* camera = FindUInt(obj, "camera")) {
this->camera = r.cameras.Get(camera->GetString()); this->camera = r.cameras.Retrieve(camera->GetUint());
if (this->camera) if (this->camera)
this->camera->id = this->id; this->camera->id = this->id;
} }
// TODO load "skeletons", "skin", "jointName"
if (Value* extensions = FindObject(obj, "extensions")) {
if (r.extensionsUsed.KHR_materials_common) {
if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
if (Value* light = FindString(*ext, "light")) {
this->light = r.lights.Get(light->GetString());
}
}
}
}
} }
inline void Scene::Read(Value& obj, Asset& r) inline void Scene::Read(Value& obj, Asset& r)
{ {
if (Value* array = FindArray(obj, "nodes")) { if (Value* array = FindArray(obj, "nodes")) {
for (unsigned int i = 0; i < array->Size(); ++i) { for (unsigned int i = 0; i < array->Size(); ++i) {
if (!(*array)[i].IsString()) continue; if (!(*array)[i].IsUint()) continue;
Ref<Node> node = r.nodes.Get((*array)[i].GetString()); Ref<Node> node = r.nodes.Retrieve((*array)[i].GetUint());
if (node) if (node)
this->nodes.push_back(node); this->nodes.push_back(node);
} }
} }
} }
inline void AssetMetadata::Read(Document& doc) inline void AssetMetadata::Read(Document& doc)
{ {
// read the version, etc.
float statedVersion = 0;
if (Value* obj = FindObject(doc, "asset")) { if (Value* obj = FindObject(doc, "asset")) {
ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "copyright", copyright);
ReadMember(*obj, "generator", generator); ReadMember(*obj, "generator", generator);
premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); if (Value* versionString = FindString(*obj, "version")) {
statedVersion = MemberOrDefault(*obj, "version", 0); version = versionString->GetString();
} else if (Value* versionNumber = FindNumber (*obj, "version")) {
char buf[4];
ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
version = buf;
}
if (Value* profile = FindObject(*obj, "profile")) { if (Value* profile = FindObject(*obj, "profile")) {
ReadMember(*profile, "api", this->profile.api); ReadMember(*profile, "api", this->profile.api);
@ -1243,60 +980,16 @@ inline void AssetMetadata::Read(Document& doc)
} }
} }
version = std::max(statedVersion, version); if (version.empty() || version[0] != '2') {
throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
if (version == 0) {
// if missing version, we'll assume version 1.0...
version = 1;
}
if (version != 1) {
char msg[128];
ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %.1f", version);
throw DeadlyImportError(msg);
} }
} }
// //
// Asset methods implementation // Asset methods implementation
// //
inline void Asset::ReadBinaryHeader(IOStream& stream) inline void Asset::Load(const std::string& pFile)
{
GLB_Header header;
if (stream.Read(&header, sizeof(header), 1) != 1) {
throw DeadlyImportError("GLTF: Unable to read the file header");
}
if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
throw DeadlyImportError("GLTF: Invalid binary glTF file");
}
AI_SWAP4(header.version);
asset.version = header.version;
if (header.version != 1) {
throw DeadlyImportError("GLTF: Unsupported binary glTF version");
}
AI_SWAP4(header.sceneFormat);
if (header.sceneFormat != SceneFormat_JSON) {
throw DeadlyImportError("GLTF: Unsupported binary glTF scene format");
}
AI_SWAP4(header.length);
AI_SWAP4(header.sceneLength);
mSceneLength = static_cast<size_t>(header.sceneLength);
mBodyOffset = sizeof(header)+mSceneLength;
mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4
mBodyLength = header.length - mBodyOffset;
}
inline void Asset::Load(const std::string& pFile, bool isBinary)
{ {
mCurrentAssetDir.clear(); mCurrentAssetDir.clear();
int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
@ -1307,16 +1000,8 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
throw DeadlyImportError("GLTF: Could not open file for reading"); throw DeadlyImportError("GLTF: Could not open file for reading");
} }
// is binary? then read the header mSceneLength = stream->FileSize();
if (isBinary) { mBodyLength = 0;
SetAsBinary(); // also creates the body buffer
ReadBinaryHeader(*stream);
}
else {
mSceneLength = stream->FileSize();
mBodyLength = 0;
}
// read the scene data // read the scene data
@ -1361,12 +1046,14 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
mDicts[i]->AttachToDocument(doc); mDicts[i]->AttachToDocument(doc);
} }
// Read the "scene" property, which specifies which scene to load // Read the "scene" property, which specifies which scene to load
// and recursively load everything referenced by it // and recursively load everything referenced by it
if (Value* scene = FindString(doc, "scene")) { if (Value* scene = FindUInt(doc, "scene")) {
this->scene = scenes.Get(scene->GetString()); unsigned int sceneIndex = scene->GetUint();
Ref<Scene> s = scenes.Retrieve(sceneIndex);
this->scene = s;
} }
// Clean up // Clean up
@ -1375,16 +1062,6 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
} }
} }
inline void Asset::SetAsBinary()
{
if (!extensionsUsed.KHR_binary_glTF) {
extensionsUsed.KHR_binary_glTF = true;
mBodyBuffer = buffers.Create("binary_glTF");
mBodyBuffer->MarkAsSpecial();
}
}
inline void Asset::ReadExtensionsUsed(Document& doc) inline void Asset::ReadExtensionsUsed(Document& doc)
{ {
Value* extsUsed = FindArray(doc, "extensionsUsed"); Value* extsUsed = FindArray(doc, "extensionsUsed");
@ -1401,8 +1078,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
#define CHECK_EXT(EXT) \ #define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
CHECK_EXT(KHR_binary_glTF); CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
CHECK_EXT(KHR_materials_common);
#undef CHECK_EXT #undef CHECK_EXT
} }

View File

@ -43,8 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Declares a class to write gltf/glb files * Declares a class to write gltf/glb files
* *
* glTF Extensions Support: * glTF Extensions Support:
* KHR_binary_glTF: full * KHR_materials_pbrSpecularGlossiness: full
* KHR_materials_common: full
*/ */
#ifndef GLTF2ASSETWRITER_H_INC #ifndef GLTF2ASSETWRITER_H_INC
#define GLTF2ASSETWRITER_H_INC #define GLTF2ASSETWRITER_H_INC
@ -82,7 +81,6 @@ public:
AssetWriter(Asset& asset); AssetWriter(Asset& asset);
void WriteFile(const char* path); void WriteFile(const char* path);
void WriteGLBFile(const char* path);
}; };
} }

View File

@ -72,6 +72,12 @@ namespace glTF2 {
return val; return val;
} }
inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& al) {
val.SetDouble(r);
return val;
}
template<class T> template<class T>
inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) { inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
if (v.empty()) return; if (v.empty()) return;
@ -91,7 +97,11 @@ namespace glTF2 {
{ {
obj.AddMember("bufferView", a.bufferView->index, w.mAl); obj.AddMember("bufferView", a.bufferView->index, w.mAl);
obj.AddMember("byteOffset", a.byteOffset, w.mAl); obj.AddMember("byteOffset", a.byteOffset, w.mAl);
obj.AddMember("byteStride", a.byteStride, w.mAl);
if (a.byteStride != 0) {
obj.AddMember("byteStride", a.byteStride, w.mAl);
}
obj.AddMember("componentType", int(a.componentType), w.mAl); obj.AddMember("componentType", int(a.componentType), w.mAl);
obj.AddMember("count", a.count, w.mAl); obj.AddMember("count", a.count, w.mAl);
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
@ -169,21 +179,7 @@ namespace glTF2 {
inline void Write(Value& obj, Image& img, AssetWriter& w) inline void Write(Value& obj, Image& img, AssetWriter& w)
{ {
std::string uri; std::string uri;
if (w.mAsset.extensionsUsed.KHR_binary_glTF && img.bufferView) { if (img.HasData()) {
Value exts, ext;
exts.SetObject();
ext.SetObject();
ext.AddMember("bufferView", img.bufferView->index, w.mAl);
if (!img.mimeType.empty())
ext.AddMember("mimeType", StringRef(img.mimeType), w.mAl);
exts.AddMember("KHR_binary_glTF", ext, w.mAl);
obj.AddMember("extensions", exts, w.mAl);
return;
}
else if (img.HasData()) {
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType); uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
uri += ";base64,"; uri += ";base64,";
Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri); Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
@ -196,51 +192,149 @@ namespace glTF2 {
} }
namespace { namespace {
inline void WriteTex(Value& obj, Ref<Texture> texture, const char* propName, MemoryPoolAllocator<>& al) inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al)
{ {
if (texture) { tex.SetObject();
tex.AddMember("index", t.texture->index, al);
if (t.texCoord != 0) {
tex.AddMember("texCoord", t.texCoord, al);
}
}
inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex; Value tex;
tex.SetObject();
tex.AddMember("index", texture->index, al); SetTexBasic(t, tex, al);
obj.AddMember(StringRef(propName), tex, al); obj.AddMember(StringRef(propName), tex, al);
} }
} }
inline void WriteColorOrTex(Value& obj, TexProperty& prop, const char* propName, MemoryPoolAllocator<>& al) inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{ {
WriteTex(obj, prop.texture, propName, al);
if (!prop.texture) { if (t.texture) {
Value col; Value tex;
obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al);
SetTexBasic(t, tex, al);
if (t.scale != 1) {
tex.AddMember("scale", t.scale, al);
}
obj.AddMember(StringRef(propName), tex, al);
} }
} }
inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex;
SetTexBasic(t, tex, al);
if (t.strength != 1) {
tex.AddMember("strength", t.strength, al);
}
obj.AddMember(StringRef(propName), tex, al);
}
}
template<size_t N>
inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al)
{
Value arr;
obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al);
}
template<size_t N>
inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al)
{
if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) {
WriteVec(obj, prop, propName, al);
}
}
inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al)
{
Value num;
obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al);
}
} }
inline void Write(Value& obj, Material& m, AssetWriter& w) inline void Write(Value& obj, Material& m, AssetWriter& w)
{ {
if (m.transparent) { Value pbrMetallicRoughness;
obj.AddMember("alphaMode", "BLEND", w.mAl); pbrMetallicRoughness.SetObject();
}
Value v;
v.SetObject();
{ {
if (m.transparent && !m.diffuse.texture) { WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl);
m.diffuse.color[3] = m.transparency; WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
} WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl);
WriteColorOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl);
WriteColorOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl);
WriteColorOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl);
WriteColorOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl);
v.AddMember("shininessFactor", m.shininess, w.mAl);
}
v.AddMember("type", "commonPhong", w.mAl);
Value ext;
ext.SetObject();
ext.AddMember("KHR_materials_common", v, w.mAl);
obj.AddMember("extensions", ext, w.mAl);
WriteTex(obj, m.normal, "normalTexture", w.mAl); if (m.pbrMetallicRoughness.metallicFactor != 1) {
WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl);
}
if (m.pbrMetallicRoughness.roughnessFactor != 1) {
WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl);
}
}
if (!pbrMetallicRoughness.ObjectEmpty()) {
obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl);
}
WriteTex(obj, m.normalTexture, "normalTexture", w.mAl);
WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl);
WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl);
WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl);
if (m.alphaCutoff != 0.5) {
WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl);
}
if (m.alphaMode != "OPAQUE") {
obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl);
}
if (m.doubleSided) {
obj.AddMember("doubleSided", m.doubleSided, w.mAl);
}
Value exts;
exts.SetObject();
if (m.pbrSpecularGlossiness.isPresent) {
Value pbrSpecularGlossiness;
pbrSpecularGlossiness.SetObject();
PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value;
//pbrSpecularGlossiness
WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl);
WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl);
if (pbrSG.glossinessFactor != 1) {
WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl);
}
WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl);
WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl);
if (!pbrSpecularGlossiness.ObjectEmpty()) {
exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl);
}
}
if (!exts.ObjectEmpty()) {
obj.AddMember("extensions", exts, w.mAl);
}
} }
namespace { namespace {
@ -263,59 +357,6 @@ namespace glTF2 {
inline void Write(Value& obj, Mesh& m, AssetWriter& w) inline void Write(Value& obj, Mesh& m, AssetWriter& w)
{ {
/********************* Name **********************/
obj.AddMember("name", m.name, w.mAl);
/**************** Mesh extensions ****************/
if(m.Extension.size() > 0)
{
Value json_extensions;
json_extensions.SetObject();
for(Mesh::SExtension* ptr_ext : m.Extension)
{
switch(ptr_ext->Type)
{
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
case Mesh::SExtension::EType::Compression_Open3DGC:
{
Value json_comp_data;
Mesh::SCompression_Open3DGC* ptr_ext_comp = (Mesh::SCompression_Open3DGC*)ptr_ext;
// filling object "compressedData"
json_comp_data.SetObject();
json_comp_data.AddMember("buffer", ptr_ext_comp->Buffer, w.mAl);
json_comp_data.AddMember("byteOffset", ptr_ext_comp->Offset, w.mAl);
json_comp_data.AddMember("componentType", 5121, w.mAl);
json_comp_data.AddMember("type", "SCALAR", w.mAl);
json_comp_data.AddMember("count", ptr_ext_comp->Count, w.mAl);
if(ptr_ext_comp->Binary)
json_comp_data.AddMember("mode", "binary", w.mAl);
else
json_comp_data.AddMember("mode", "ascii", w.mAl);
json_comp_data.AddMember("indicesCount", ptr_ext_comp->IndicesCount, w.mAl);
json_comp_data.AddMember("verticesCount", ptr_ext_comp->VerticesCount, w.mAl);
// filling object "Open3DGC-compression"
Value json_o3dgc;
json_o3dgc.SetObject();
json_o3dgc.AddMember("compressedData", json_comp_data, w.mAl);
// add member to object "extensions"
json_extensions.AddMember("Open3DGC-compression", json_o3dgc, w.mAl);
}
break;
#endif
default:
throw DeadlyImportError("GLTF: Can not write mesh: unknown mesh extension, only Open3DGC is supported.");
}// switch(ptr_ext->Type)
}// for(Mesh::SExtension* ptr_ext : m.Extension)
// Add extensions to mesh
obj.AddMember("extensions", json_extensions, w.mAl);
}// if(m.Extension.size() > 0)
/****************** Primitives *******************/ /****************** Primitives *******************/
Value primitives; Value primitives;
primitives.SetArray(); primitives.SetArray();
@ -340,10 +381,9 @@ namespace glTF2 {
WriteAttrs(w, attrs, p.attributes.position, "POSITION"); WriteAttrs(w, attrs, p.attributes.position, "POSITION");
WriteAttrs(w, attrs, p.attributes.normal, "NORMAL"); WriteAttrs(w, attrs, p.attributes.normal, "NORMAL");
WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true); WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true);
WriteAttrs(w, attrs, p.attributes.color, "COLOR"); WriteAttrs(w, attrs, p.attributes.color, "COLOR", true);
WriteAttrs(w, attrs, p.attributes.joint, "JOINT"); WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true);
WriteAttrs(w, attrs, p.attributes.jointmatrix, "JOINTMATRIX"); WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true);
WriteAttrs(w, attrs, p.attributes.weight, "WEIGHT");
} }
prim.AddMember("attributes", attrs, w.mAl); prim.AddMember("attributes", attrs, w.mAl);
} }
@ -377,7 +417,9 @@ namespace glTF2 {
AddRefsVector(obj, "children", n.children, w.mAl); AddRefsVector(obj, "children", n.children, w.mAl);
AddRefsVector(obj, "meshes", n.meshes, w.mAl); if (n.mesh) {
obj.AddMember("mesh", n.mesh->index, w.mAl);
}
AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
@ -397,17 +439,24 @@ namespace glTF2 {
inline void Write(Value& obj, Sampler& b, AssetWriter& w) inline void Write(Value& obj, Sampler& b, AssetWriter& w)
{ {
if (b.wrapS) { if (!b.name.empty()) {
obj.AddMember("wrapS", b.wrapS, w.mAl); obj.AddMember("name", b.name, w.mAl);
} }
if (b.wrapT) {
obj.AddMember("wrapT", b.wrapT, w.mAl); if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) {
obj.AddMember("wrapS", static_cast<unsigned int>(b.wrapS), w.mAl);
} }
if (b.magFilter) {
obj.AddMember("magFilter", b.magFilter, w.mAl); if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) {
obj.AddMember("wrapT", static_cast<unsigned int>(b.wrapT), w.mAl);
} }
if (b.minFilter) {
obj.AddMember("minFilter", b.minFilter, w.mAl); if (b.magFilter != SamplerMagFilter::UNSET) {
obj.AddMember("magFilter", static_cast<unsigned int>(b.magFilter), w.mAl);
}
if (b.minFilter != SamplerMinFilter::UNSET) {
obj.AddMember("minFilter", static_cast<unsigned int>(b.minFilter), w.mAl);
} }
} }
@ -444,11 +493,6 @@ namespace glTF2 {
} }
inline void Write(Value& obj, Technique& b, AssetWriter& w)
{
}
inline void Write(Value& obj, Texture& tex, AssetWriter& w) inline void Write(Value& obj, Texture& tex, AssetWriter& w)
{ {
if (tex.source) { if (tex.source) {
@ -459,11 +503,6 @@ namespace glTF2 {
} }
} }
inline void Write(Value& obj, Light& b, AssetWriter& w)
{
}
inline AssetWriter::AssetWriter(Asset& a) inline AssetWriter::AssetWriter(Asset& a)
: mDoc() : mDoc()
@ -523,88 +562,12 @@ namespace glTF2 {
} }
} }
inline void AssetWriter::WriteGLBFile(const char* path)
{
std::unique_ptr<IOStream> outfile(mAsset.OpenFile(path, "wb", true));
if (outfile == 0) {
throw DeadlyExportError("Could not open output file: " + std::string(path));
}
// we will write the header later, skip its size
outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
StringBuffer docBuffer;
Writer<StringBuffer> writer(docBuffer);
mDoc.Accept(writer);
if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
throw DeadlyExportError("Failed to write scene data!");
}
WriteBinaryData(outfile.get(), docBuffer.GetSize());
}
inline void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength)
{
//
// write the body data
//
size_t bodyLength = 0;
if (Ref<Buffer> b = mAsset.GetBodyBuffer()) {
bodyLength = b->byteLength;
if (bodyLength > 0) {
size_t bodyOffset = sizeof(GLB_Header) + sceneLength;
bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4
outfile->Seek(bodyOffset, aiOrigin_SET);
if (outfile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
throw DeadlyExportError("Failed to write body data!");
}
}
}
//
// write the header
//
GLB_Header header;
memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic));
header.version = 2;
AI_SWAP4(header.version);
header.length = uint32_t(sizeof(header) + sceneLength + bodyLength);
AI_SWAP4(header.length);
header.sceneLength = uint32_t(sceneLength);
AI_SWAP4(header.sceneLength);
header.sceneFormat = SceneFormat_JSON;
AI_SWAP4(header.sceneFormat);
outfile->Seek(0, aiOrigin_SET);
if (outfile->Write(&header, 1, sizeof(header)) != sizeof(header)) {
throw DeadlyExportError("Failed to write the header!");
}
}
inline void AssetWriter::WriteMetadata() inline void AssetWriter::WriteMetadata()
{ {
Value asset; Value asset;
asset.SetObject(); asset.SetObject();
{ asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
char versionChar[10]; asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
ai_snprintf(versionChar, sizeof(versionChar), "%.1f", mAsset.asset.version);
asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
}
mDoc.AddMember("asset", asset, mAl); mDoc.AddMember("asset", asset, mAl);
} }
@ -613,11 +576,10 @@ namespace glTF2 {
Value exts; Value exts;
exts.SetArray(); exts.SetArray();
{ {
if (false) // This is used to export pbrSpecularGlossiness materials with GLTF 2.
exts.PushBack(StringRef("KHR_binary_glTF"), mAl); if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl);
// This is used to export common materials with GLTF 2. }
exts.PushBack(StringRef("KHR_materials_common"), mAl);
} }
if (!exts.Empty()) if (!exts.Empty())

View File

@ -62,11 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "glTF2AssetWriter.h" #include "glTF2AssetWriter.h"
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
// Header files, Open3DGC.
# include <Open3DGC/o3dgcSC3DMCEncoder.h>
#endif
using namespace rapidjson; using namespace rapidjson;
using namespace Assimp; using namespace Assimp;
@ -106,16 +101,8 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
mAsset.reset( new Asset( pIOSystem ) ); mAsset.reset( new Asset( pIOSystem ) );
if (isBinary) {
mAsset->SetAsBinary();
}
ExportMetadata(); ExportMetadata();
//for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {}
//for (unsigned int i = 0; i < pScene->mNumLights; ++i) {}
ExportMaterials(); ExportMaterials();
if (mScene->mRootNode) { if (mScene->mRootNode) {
@ -124,19 +111,13 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
ExportMeshes(); ExportMeshes();
//for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {}
ExportScene(); ExportScene();
ExportAnimations(); ExportAnimations();
AssetWriter writer(*mAsset); AssetWriter writer(*mAsset);
if (isBinary) { writer.WriteFile(filename);
writer.WriteGLBFile(filename);
} else {
writer.WriteFile(filename);
}
} }
/* /*
@ -234,63 +215,86 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
return acc; return acc;
} }
namespace { inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map)
void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) { {
if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {} switch (map) {
case aiTextureMapMode_Clamp:
wrap = SamplerWrap::Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
wrap = SamplerWrap::Mirrored_Repeat;
break;
case aiTextureMapMode_Wrap:
case aiTextureMapMode_Decal:
default:
wrap = SamplerWrap::Repeat;
break;
};
}
void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
{
aiString aId;
std::string id;
if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
id = aId.C_Str();
}
if (Ref<Sampler> ref = mAsset->samplers.Get(id.c_str())) {
texture->sampler = ref;
} else {
id = mAsset->FindUniqueID(id, "sampler");
texture->sampler = mAsset->samplers.Create(id.c_str());
aiTextureMapMode mapU, mapV;
SamplerMagFilter filterMag;
SamplerMinFilter filterMin;
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
SetSamplerWrap(texture->sampler->wrapS, mapU);
}
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
SetSamplerWrap(texture->sampler->wrapT, mapV);
}
if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
texture->sampler->magFilter = filterMag;
}
if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
texture->sampler->minFilter = filterMin;
}
aiString name;
if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
texture->sampler->name = name.C_Str();
}
} }
} }
void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture) void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
{ {
std::string samplerId = mAsset->FindUniqueID("", "sampler"); std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
texture->sampler = mAsset->samplers.Create(samplerId);
aiTextureMapMode mapU, mapV; mat->Get(textureKey.c_str(), tt, slot, prop);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
switch (mapU) {
case aiTextureMapMode_Wrap:
texture->sampler->wrapS = SamplerWrap_Repeat;
break;
case aiTextureMapMode_Clamp:
texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat;
break;
case aiTextureMapMode_Decal:
default:
texture->sampler->wrapS = SamplerWrap_Repeat;
break;
};
switch (mapV) {
case aiTextureMapMode_Wrap:
texture->sampler->wrapT = SamplerWrap_Repeat;
break;
case aiTextureMapMode_Clamp:
texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat;
break;
case aiTextureMapMode_Decal:
default:
texture->sampler->wrapT = SamplerWrap_Repeat;
break;
};
// Hard coded Texture filtering options because I do not know where to find them in the aiMaterial.
texture->sampler->magFilter = SamplerMagFilter_Linear;
texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear;
} }
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt) void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
{ {
aiString tex; std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
mat->Get(textureKey.c_str(), tt, slot, prop);
}
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
{
if (mat->GetTextureCount(tt) > 0) { if (mat->GetTextureCount(tt) > 0) {
if (mat->Get(AI_MATKEY_TEXTURE(tt, 0), tex) == AI_SUCCESS) { aiString tex;
if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::string path = tex.C_Str(); std::string path = tex.C_Str();
if (path.size() > 0) { if (path.size() > 0) {
@ -325,22 +329,63 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
texture->source->uri = path; texture->source->uri = path;
} }
GetTexSampler(mat, texture); GetTexSampler(mat, texture, tt, slot);
} }
} }
} }
} }
} }
void glTF2Exporter::GetMatColorOrTex(const aiMaterial* mat, TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt) void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
{
Ref<Texture>& texture = prop.texture;
GetMatTex(mat, texture, tt, slot);
if (texture) {
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
}
}
void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
{
Ref<Texture>& texture = prop.texture;
GetMatTex(mat, texture, tt, slot);
if (texture) {
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
GetMatTexProp(mat, prop.scale, "scale", tt, slot);
}
}
void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0)
{
Ref<Texture>& texture = prop.texture;
GetMatTex(mat, texture, tt, slot);
if (texture) {
GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot);
GetMatTexProp(mat, prop.strength, "strength", tt, slot);
}
}
void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx)
{ {
aiColor4D col; aiColor4D col;
if (mat->Get(propName, type, idx, col) == AI_SUCCESS) { if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a; prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a;
} }
GetMatTex(mat, prop.texture, tt);
} }
void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx)
{
aiColor3D col;
if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
prop[0] = col.r; prop[1] = col.g; prop[2] = col.b;
}
}
void glTF2Exporter::ExportMaterials() void glTF2Exporter::ExportMaterials()
{ {
@ -348,6 +393,9 @@ void glTF2Exporter::ExportMaterials()
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
const aiMaterial* mat = mScene->mMaterials[i]; const aiMaterial* mat = mScene->mMaterials[i];
std::string id = "material_" + std::to_string(i);
Ref<Material> m = mAsset->materials.Create(id);
std::string name; std::string name;
if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
@ -355,17 +403,70 @@ void glTF2Exporter::ExportMaterials()
} }
name = mAsset->FindUniqueID(name, "material"); name = mAsset->FindUniqueID(name, "material");
Ref<Material> m = mAsset->materials.Create(name); m->name = name;
GetMatColorOrTex(mat, m->ambient, AI_MATKEY_COLOR_AMBIENT, aiTextureType_AMBIENT); GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE);
GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE); GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR); GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE);
GetMatTex(mat, m->normal, aiTextureType_NORMALS);
m->transparent = mat->Get(AI_MATKEY_OPACITY, m->transparency) == aiReturn_SUCCESS && m->transparency != 1.0; if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) {
//if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0
m->pbrMetallicRoughness.metallicFactor = 0;
}
GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS); mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor);
GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS);
GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP);
GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE);
GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE);
mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided);
mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff);
bool foundAlphaMode = false;
for (size_t i = 0; i < mat->mNumProperties; ++i) {
aiMaterialProperty *prop = mat->mProperties[i];
if (prop->mKey != aiString("$mat.gltf.alphaMode"))
continue;
std::string alphaMode;
for (size_t c = 0; c < prop->mDataLength; ++c)
alphaMode += prop->mData[c];
m->alphaMode = alphaMode;
foundAlphaMode = true;
}
if (!foundAlphaMode) {
float opacity;
if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) {
if (opacity < 1) {
m->alphaMode = "MASK";
m->pbrMetallicRoughness.baseColorFactor[3] *= opacity;
}
}
}
bool hasPbrSpecularGlossiness = false;
mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness);
if (hasPbrSpecularGlossiness) {
if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true;
}
PbrSpecularGlossiness pbrSG;
GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR);
GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR);
mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor);
GetMatTex(mat, pbrSG.diffuseTexture, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE);
GetMatTex(mat, pbrSG.specularGlossinessTexture, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE);
m->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
}
} }
} }
@ -375,16 +476,15 @@ void glTF2Exporter::ExportMaterials()
*/ */
bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID) bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& meshNode, std::string meshID)
{ {
for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) {
if (meshID.compare(nodeIn->meshes[i]->id) == 0) { if (nodeIn->mesh && meshID.compare(nodeIn->mesh->id) == 0) {
meshNode = nodeIn; meshNode = nodeIn;
return true; return true;
}
} }
for (unsigned int i = 0; i < nodeIn->children.size(); ++i) { for (unsigned int i = 0; i < nodeIn->children.size(); ++i) {
if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) { if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) {
return true; return true;
} }
} }
@ -502,15 +602,6 @@ void glTF2Exporter::ExportMeshes()
// because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification. // because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification.
typedef unsigned short IndicesType; typedef unsigned short IndicesType;
// Variables needed for compression. BEGIN.
// Indices, not pointers - because pointer to buffer is changing while writing to it.
size_t idx_srcdata_begin;// Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer.
size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals.
std::vector<size_t> idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer.
size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer.
bool comp_allow;// Point that data of current mesh can be compressed.
// Variables needed for compression. END.
std::string fname = std::string(mFilename); std::string fname = std::string(mFilename);
std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf")); std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf"));
std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str()); std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str());
@ -543,48 +634,22 @@ void glTF2Exporter::ExportMeshes()
for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) { for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) {
const aiMesh* aim = mScene->mMeshes[idx_mesh]; const aiMesh* aim = mScene->mMeshes[idx_mesh];
// Check if compressing requested and mesh can be encoded. std::string name = aim->mName.C_Str();
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
comp_allow = mProperties->GetPropertyBool("extensions.Open3DGC.use", false);
#else
comp_allow = false;
#endif
if(comp_allow && (aim->mPrimitiveTypes == aiPrimitiveType_TRIANGLE) && (aim->mNumVertices > 0) && (aim->mNumFaces > 0)) std::string meshId = mAsset->FindUniqueID(name, "mesh");
{
idx_srcdata_tc.clear();
idx_srcdata_tc.reserve(AI_MAX_NUMBER_OF_TEXTURECOORDS);
}
else
{
std::string msg;
if(aim->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
msg = "all primitives of the mesh must be a triangles.";
else
msg = "mesh must has vertices and faces.";
DefaultLogger::get()->warn("GLTF: can not use Open3DGC-compression: " + msg);
comp_allow = false;
}
std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh");
Ref<Mesh> m = mAsset->meshes.Create(meshId); Ref<Mesh> m = mAsset->meshes.Create(meshId);
m->primitives.resize(1); m->primitives.resize(1);
Mesh::Primitive& p = m->primitives.back(); Mesh::Primitive& p = m->primitives.back();
m->name = name;
p.material = mAsset->materials.Get(aim->mMaterialIndex); p.material = mAsset->materials.Get(aim->mMaterialIndex);
/******************* Vertices ********************/ /******************* Vertices ********************/
// If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored.
if(comp_allow) idx_srcdata_begin = b->byteLength;
Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if (v) p.attributes.position.push_back(v); if (v) p.attributes.position.push_back(v);
/******************** Normals ********************/ /******************** Normals ********************/
if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array.
Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if (n) p.attributes.normal.push_back(n); if (n) p.attributes.normal.push_back(n);
@ -600,16 +665,12 @@ void glTF2Exporter::ExportMeshes()
if (aim->mNumUVComponents[i] > 0) { if (aim->mNumUVComponents[i] > 0) {
AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false);
if (tc) p.attributes.texcoord.push_back(tc); if (tc) p.attributes.texcoord.push_back(tc);
} }
} }
/*************** Vertices indices ****************/ /*************** Vertices indices ****************/
idx_srcdata_ind = b->byteLength;// Store index of indices array.
if (aim->mNumFaces > 0) { if (aim->mNumFaces > 0) {
std::vector<IndicesType> indices; std::vector<IndicesType> indices;
unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices; unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices;
@ -634,104 +695,12 @@ void glTF2Exporter::ExportMeshes()
p.mode = PrimitiveMode_TRIANGLES; p.mode = PrimitiveMode_TRIANGLES;
} }
/*************** Skins ****************/ /*************** Skins ****************/
if(aim->HasBones()) { if(aim->HasBones()) {
ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData);
}
} }
/****************** Compression ******************/
///TODO: animation: weights, joints.
if(comp_allow)
{
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
// Only one type of compression supported at now - Open3DGC.
//
o3dgc::BinaryStream bs;
o3dgc::SC3DMCEncoder<IndicesType> encoder;
o3dgc::IndexedFaceSet<IndicesType> comp_o3dgc_ifs;
o3dgc::SC3DMCEncodeParams comp_o3dgc_params;
//
// Fill data for encoder.
//
// Quantization
unsigned quant_coord = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.POSITION", 12);
unsigned quant_normal = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.NORMAL", 10);
unsigned quant_texcoord = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.TEXCOORD", 10);
// Prediction
o3dgc::O3DGCSC3DMCPredictionMode prediction_position = o3dgc::O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION;
o3dgc::O3DGCSC3DMCPredictionMode prediction_normal = o3dgc::O3DGC_SC3DMC_SURF_NORMALS_PREDICTION;
o3dgc::O3DGCSC3DMCPredictionMode prediction_texcoord = o3dgc::O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION;
// IndexedFacesSet: "Crease angle", "solid", "convex" are set to default.
comp_o3dgc_ifs.SetCCW(true);
comp_o3dgc_ifs.SetIsTriangularMesh(true);
comp_o3dgc_ifs.SetNumFloatAttributes(0);
// Coordinates
comp_o3dgc_params.SetCoordQuantBits(quant_coord);
comp_o3dgc_params.SetCoordPredMode(prediction_position);
comp_o3dgc_ifs.SetNCoord(aim->mNumVertices);
comp_o3dgc_ifs.SetCoord((o3dgc::Real* const)&b->GetPointer()[idx_srcdata_begin]);
// Normals
if(idx_srcdata_normal != SIZE_MAX)
{
comp_o3dgc_params.SetNormalQuantBits(quant_normal);
comp_o3dgc_params.SetNormalPredMode(prediction_normal);
comp_o3dgc_ifs.SetNNormal(aim->mNumVertices);
comp_o3dgc_ifs.SetNormal((o3dgc::Real* const)&b->GetPointer()[idx_srcdata_normal]);
}
// Texture coordinates
for(size_t num_tc = 0; num_tc < idx_srcdata_tc.size(); num_tc++)
{
size_t num = comp_o3dgc_ifs.GetNumFloatAttributes();
comp_o3dgc_params.SetFloatAttributeQuantBits(static_cast<unsigned long>(num), quant_texcoord);
comp_o3dgc_params.SetFloatAttributePredMode(static_cast<unsigned long>(num), prediction_texcoord);
comp_o3dgc_ifs.SetNFloatAttribute(static_cast<unsigned long>(num), aim->mNumVertices);// number of elements.
comp_o3dgc_ifs.SetFloatAttributeDim(static_cast<unsigned long>(num), aim->mNumUVComponents[num_tc]);// components per element: aiVector3D => x * float
comp_o3dgc_ifs.SetFloatAttributeType(static_cast<unsigned long>(num), o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD);
comp_o3dgc_ifs.SetFloatAttribute(static_cast<unsigned long>(num), (o3dgc::Real* const)&b->GetPointer()[idx_srcdata_tc[num_tc]]);
comp_o3dgc_ifs.SetNumFloatAttributes(static_cast<unsigned long>(num + 1));
}
// Coordinates indices
comp_o3dgc_ifs.SetNCoordIndex(aim->mNumFaces);
comp_o3dgc_ifs.SetCoordIndex((IndicesType* const)&b->GetPointer()[idx_srcdata_ind]);
// Prepare to enconding
comp_o3dgc_params.SetNumFloatAttributes(comp_o3dgc_ifs.GetNumFloatAttributes());
if(mProperties->GetPropertyBool("extensions.Open3DGC.binary", true))
comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_BINARY);
else
comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_ASCII);
comp_o3dgc_ifs.ComputeMinMax(o3dgc::O3DGC_SC3DMC_MAX_ALL_DIMS);
//
// Encoding
//
encoder.Encode(comp_o3dgc_params, comp_o3dgc_ifs, bs);
// Replace data in buffer.
b->ReplaceData(idx_srcdata_begin, b->byteLength - idx_srcdata_begin, bs.GetBuffer(), bs.GetSize());
//
// Add information about extension to mesh.
//
// Create extension structure.
Mesh::SCompression_Open3DGC* ext = new Mesh::SCompression_Open3DGC;
// Fill it.
ext->Buffer = b->id;
ext->Offset = idx_srcdata_begin;
ext->Count = b->byteLength - idx_srcdata_begin;
ext->Binary = mProperties->GetPropertyBool("extensions.Open3DGC.binary");
ext->IndicesCount = comp_o3dgc_ifs.GetNCoordIndex() * 3;
ext->VerticesCount = comp_o3dgc_ifs.GetNCoord();
// And assign to mesh.
m->Extension.push_back(ext);
#endif
}// if(comp_allow)
}// for (unsigned int i = 0; i < mScene->mNumMeshes; ++i)
//---------------------------------------- //----------------------------------------
// Finish the skin // Finish the skin
// Create the Accessor for skinRef->inverseBindMatrices // Create the Accessor for skinRef->inverseBindMatrices
@ -786,8 +755,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n)
CopyValue(n->mTransformation, node->matrix.value); CopyValue(n->mTransformation, node->matrix.value);
} }
for (unsigned int i = 0; i < n->mNumMeshes; ++i) { if (n->mNumMeshes > 0) {
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); node->mesh = mAsset->meshes.Get(n->mMeshes[0]);
} }
for (unsigned int i = 0; i < n->mNumChildren; ++i) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
@ -815,8 +784,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref<Node>& parent)
CopyValue(n->mTransformation, node->matrix.value); CopyValue(n->mTransformation, node->matrix.value);
} }
for (unsigned int i = 0; i < n->mNumMeshes; ++i) { if (n->mNumMeshes > 0) {
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); node->mesh = mAsset->meshes.Get(n->mMeshes[0]);
} }
for (unsigned int i = 0; i < n->mNumChildren; ++i) { for (unsigned int i = 0; i < n->mNumChildren; ++i) {
@ -845,7 +814,7 @@ void glTF2Exporter::ExportScene()
void glTF2Exporter::ExportMetadata() void glTF2Exporter::ExportMetadata()
{ {
AssetMetadata& asset = mAsset->asset; AssetMetadata& asset = mAsset->asset;
asset.version = 2; asset.version = "2.0";
char buffer[256]; char buffer[256];
ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)", ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)",
@ -886,7 +855,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
timeData[i] = nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond; timeData[i] = nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond;
} }
Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, numKeyframes, &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT);
if (timeAccessor) animRef->Parameters.TIME = timeAccessor; if (timeAccessor) animRef->Parameters.TIME = timeAccessor;
} }
@ -899,7 +868,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue; translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue;
} }
Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, numKeyframes, translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if ( tranAccessor ) { if ( tranAccessor ) {
animRef->Parameters.translation = tranAccessor; animRef->Parameters.translation = tranAccessor;
} }
@ -915,7 +884,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue; scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue;
} }
Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, numKeyframes, scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if ( scaleAccessor ) { if ( scaleAccessor ) {
animRef->Parameters.scale = scaleAccessor; animRef->Parameters.scale = scaleAccessor;
} }
@ -934,7 +903,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w; rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w;
} }
Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, numKeyframes, rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if ( rotAccessor ) { if ( rotAccessor ) {
animRef->Parameters.rotation = rotAccessor; animRef->Parameters.rotation = rotAccessor;
} }
@ -963,7 +932,7 @@ void glTF2Exporter::ExportAnimations()
name = mAsset->FindUniqueID(name, "animation"); name = mAsset->FindUniqueID(name, "animation");
Ref<Animation> animRef = mAsset->animations.Create(name); Ref<Animation> animRef = mAsset->animations.Create(name);
/******************* Parameters ********************/ // Parameters
ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, anim->mTicksPerSecond); ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, anim->mTicksPerSecond);
for (unsigned int j = 0; j < 3; ++j) { for (unsigned int j = 0; j < 3; ++j) {
@ -989,7 +958,7 @@ void glTF2Exporter::ExportAnimations()
Animation::AnimChannel tmpAnimChannel; Animation::AnimChannel tmpAnimChannel;
Animation::AnimSampler tmpAnimSampler; Animation::AnimSampler tmpAnimSampler;
tmpAnimChannel.sampler = animRef->Samplers.size(); tmpAnimChannel.sampler = static_cast<int>(animRef->Samplers.size());
tmpAnimChannel.target.path = channelType; tmpAnimChannel.target.path = channelType;
tmpAnimSampler.output = channelType; tmpAnimSampler.output = channelType;
tmpAnimSampler.id = name + "_" + channelType; tmpAnimSampler.id = name + "_" + channelType;

View File

@ -66,8 +66,15 @@ namespace glTF2
class Asset; class Asset;
struct TexProperty; struct TexProperty;
struct TextureInfo;
struct NormalTextureInfo;
struct OcclusionTextureInfo;
struct Node; struct Node;
struct Texture; struct Texture;
// Vec/matrix types, as raw float arrays
typedef float (vec3)[3];
typedef float (vec4)[4];
} }
namespace Assimp namespace Assimp
@ -101,9 +108,15 @@ namespace Assimp
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture); void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt); void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
void GetMatColorOrTex(const aiMaterial* mat, glTF2::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt); void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
void ExportMetadata(); void ExportMetadata();
void ExportMaterials(); void ExportMaterials();
void ExportMeshes(); void ExportMeshes();

View File

@ -0,0 +1,654 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include "glTF2Importer.h"
#include "StringComparison.h"
#include "StringUtils.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h>
#include <memory>
#include "MakeVerboseFormat.h"
#include "glTF2Asset.h"
// This is included here so WriteLazyDict<T>'s definition is found.
#include "glTF2AssetWriter.h"
#include <rapidjson/document.h>
#include <rapidjson/rapidjson.h>
using namespace Assimp;
using namespace glTF2;
//
// glTF2Importer
//
static const aiImporterDesc desc = {
"glTF2 Importer",
"",
"",
"",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
0,
0,
0,
0,
"gltf glb"
};
glTF2Importer::glTF2Importer()
: BaseImporter()
, meshOffsets()
, embeddedTexIdxs()
, mScene( NULL ) {
// empty
}
glTF2Importer::~glTF2Importer() {
// empty
}
const aiImporterDesc* glTF2Importer::GetInfo() const
{
return &desc;
}
bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string &extension = GetExtension(pFile);
if (extension != "gltf") // We currently can't read glTF2 binary files (.glb), yet
return false;
if (checkSig && pIOHandler) {
glTF2::Asset asset(pIOHandler);
try {
asset.Load(pFile);
std::string version = asset.asset.version;
return !version.empty() && version[0] == '2';
} catch (...) {
return false;
}
}
return false;
}
//static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
//{
// out.r = v[0]; out.g = v[1]; out.b = v[2];
//}
static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
}
/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2];
}*/
static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
}
static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
{
out.x = v[0]; out.y = v[1]; out.z = v[2];
}
static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
{
out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
}
static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
{
o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
}
inline void SetMaterialColorProperty(Asset& r, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
{
aiColor4D col;
CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
{
aiColor4D col;
CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0)
{
if (prop.texture && prop.texture->source) {
aiString uri(prop.texture->source->uri);
int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
if (texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
}
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot);
if (prop.texture->sampler) {
Ref<Sampler> sampler = prop.texture->sampler;
aiString name(sampler->name);
aiString id(sampler->id);
mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
if (sampler->magFilter != SamplerMagFilter::UNSET) {
mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot));
}
if (sampler->minFilter != SamplerMinFilter::UNSET) {
mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot));
}
}
}
}
void glTF2Importer::ImportMaterials(glTF2::Asset& r)
{
mScene->mNumMaterials = unsigned(r.materials.Size());
mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials];
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial();
Material& mat = r.materials[i];
if (!mat.name.empty()) {
aiString str(mat.name);
aimat->AddProperty(&str, AI_MATKEY_NAME);
}
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE);
SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
aimat->AddProperty(&mat.alphaMode, 1, AI_MATKEY_GLTF_ALPHAMODE);
aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF);
//pbrSpecularGlossiness
if (mat.pbrSpecularGlossiness.isPresent) {
PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS);
SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR);
SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR);
aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE);
}
}
}
static inline void SetFace(aiFace& face, int a)
{
face.mNumIndices = 1;
face.mIndices = new unsigned int[1];
face.mIndices[0] = a;
}
static inline void SetFace(aiFace& face, int a, int b)
{
face.mNumIndices = 2;
face.mIndices = new unsigned int[2];
face.mIndices[0] = a;
face.mIndices[1] = b;
}
static inline void SetFace(aiFace& face, int a, int b, int c)
{
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
face.mIndices[0] = a;
face.mIndices[1] = b;
face.mIndices[2] = c;
}
static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts)
{
for (unsigned i = 0; i < nFaces; ++i) {
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
unsigned idx = faces[i].mIndices[j];
if (idx >= nVerts)
return false;
}
}
return true;
}
void glTF2Importer::ImportMeshes(glTF2::Asset& r)
{
std::vector<aiMesh*> meshes;
unsigned int k = 0;
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
Mesh& mesh = r.meshes[m];
meshOffsets.push_back(k);
k += unsigned(mesh.primitives.size());
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
Mesh::Primitive& prim = mesh.primitives[p];
aiMesh* aim = new aiMesh();
meshes.push_back(aim);
aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
if (mesh.primitives.size() > 1) {
size_t& len = aim->mName.length;
aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
}
switch (prim.mode) {
case PrimitiveMode_POINTS:
aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
case PrimitiveMode_LINES:
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP:
aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case PrimitiveMode_TRIANGLES:
case PrimitiveMode_TRIANGLE_STRIP:
case PrimitiveMode_TRIANGLE_FAN:
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
}
Mesh::Primitive::Attributes& attr = prim.attributes;
if (attr.position.size() > 0 && attr.position[0]) {
aim->mNumVertices = attr.position[0]->count;
attr.position[0]->ExtractData(aim->mVertices);
}
if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals);
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
aiVector3D* values = aim->mTextureCoords[tc];
for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
values[i].y = 1 - values[i].y; // Flip Y coords
}
}
if (prim.indices) {
aiFace* faces = 0;
unsigned int nFaces = 0;
unsigned int count = prim.indices->count;
Accessor::Indexer data = prim.indices->GetIndexer();
ai_assert(data.IsValid());
switch (prim.mode) {
case PrimitiveMode_POINTS: {
nFaces = count;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFace(faces[i], data.GetUInt(i));
}
break;
}
case PrimitiveMode_LINES: {
nFaces = count / 2;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1));
}
break;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1));
for (unsigned int i = 2; i < count; ++i) {
SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i));
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
if (faces) {
aim->mFaces = faces;
aim->mNumFaces = nFaces;
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
}
}
if (prim.material) {
aim->mMaterialIndex = prim.material.GetIndex();
}
}
}
meshOffsets.push_back(k);
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
}
void glTF2Importer::ImportCameras(glTF2::Asset& r)
{
if (!r.cameras.Size()) return;
mScene->mNumCameras = r.cameras.Size();
mScene->mCameras = new aiCamera*[r.cameras.Size()];
for (size_t i = 0; i < r.cameras.Size(); ++i) {
Camera& cam = r.cameras[i];
aiCamera* aicam = mScene->mCameras[i] = new aiCamera();
if (cam.type == Camera::Perspective) {
aicam->mAspect = cam.cameraProperties.perspective.aspectRatio;
aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * aicam->mAspect;
aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar;
aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear;
}
else {
// assimp does not support orthographic cameras
}
}
}
aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr)
{
Node& node = *ptr;
aiNode* ainode = new aiNode(node.id);
if (!node.children.empty()) {
ainode->mNumChildren = unsigned(node.children.size());
ainode->mChildren = new aiNode*[ainode->mNumChildren];
for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]);
child->mParent = ainode;
ainode->mChildren[i] = child;
}
}
aiMatrix4x4& matrix = ainode->mTransformation;
if (node.matrix.isPresent) {
CopyValue(node.matrix.value, matrix);
}
else {
if (node.translation.isPresent) {
aiVector3D trans;
CopyValue(node.translation.value, trans);
aiMatrix4x4 t;
aiMatrix4x4::Translation(trans, t);
matrix = t * matrix;
}
if (node.scale.isPresent) {
aiVector3D scal(1.f);
CopyValue(node.scale.value, scal);
aiMatrix4x4 s;
aiMatrix4x4::Scaling(scal, s);
matrix = s * matrix;
}
if (node.rotation.isPresent) {
aiQuaternion rot;
CopyValue(node.rotation.value, rot);
matrix = aiMatrix4x4(rot.GetMatrix()) * matrix;
}
}
if (node.mesh) {
int idx = node.mesh.GetIndex();
ai_assert(idx >= 0 && idx < meshOffsets.size());
unsigned int offBegin = meshOffsets[idx];
unsigned int offEnd = meshOffsets[idx + 1];
int k = 0;
ai_assert(offEnd >= offBegin);
ainode->mNumMeshes = offEnd - offBegin;
ainode->mMeshes = new unsigned int[ainode->mNumMeshes];
for (unsigned int j = offBegin; j < offEnd; ++j, ++k) {
ai_assert(k < ainode->mNumMeshes);
ainode->mMeshes[k] = j;
}
}
if (node.camera) {
pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
}
return ainode;
}
void glTF2Importer::ImportNodes(glTF2::Asset& r)
{
if (!r.scene) return;
std::vector< Ref<Node> > rootNodes = r.scene->nodes;
// The root nodes
unsigned int numRootNodes = unsigned(rootNodes.size());
if (numRootNodes == 1) { // a single root node: use it
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
}
else if (numRootNodes > 1) { // more than one root node: create a fake root
aiNode* root = new aiNode("ROOT");
root->mChildren = new aiNode*[numRootNodes];
for (unsigned int i = 0; i < numRootNodes; ++i) {
aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]);
node->mParent = root;
root->mChildren[root->mNumChildren++] = node;
}
mScene->mRootNode = root;
}
//if (!mScene->mRootNode) {
// mScene->mRootNode = new aiNode("EMPTY");
//}
}
void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r)
{
embeddedTexIdxs.resize(r.images.Size(), -1);
int numEmbeddedTexs = 0;
for (size_t i = 0; i < r.images.Size(); ++i) {
if (r.images[i].HasData())
numEmbeddedTexs += 1;
}
if (numEmbeddedTexs == 0)
return;
mScene->mTextures = new aiTexture*[numEmbeddedTexs];
// Add the embedded textures
for (size_t i = 0; i < r.images.Size(); ++i) {
Image img = r.images[i];
if (!img.HasData()) continue;
int idx = mScene->mNumTextures++;
embeddedTexIdxs[i] = idx;
aiTexture* tex = mScene->mTextures[idx] = new aiTexture();
size_t length = img.GetDataLength();
void* data = img.StealData();
tex->mWidth = static_cast<unsigned int>(length);
tex->mHeight = 0;
tex->pcData = reinterpret_cast<aiTexel*>(data);
if (!img.mimeType.empty()) {
const char* ext = strchr(img.mimeType.c_str(), '/') + 1;
if (ext) {
if (strcmp(ext, "jpeg") == 0) ext = "jpg";
size_t len = strlen(ext);
if (len <= 3) {
strcpy(tex->achFormatHint, ext);
}
}
}
}
}
void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
this->mScene = pScene;
// read the asset file
glTF2::Asset asset(pIOHandler);
asset.Load(pFile);
//
// Copy the data out
//
ImportEmbeddedTextures(asset);
ImportMaterials(asset);
ImportMeshes(asset);
ImportCameras(asset);
ImportNodes(asset);
// TODO: it does not split the loaded vertices, should it?
//pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
MakeVerboseFormatProcess process;
process.Execute(pScene);
if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
}
}
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER

View File

@ -0,0 +1,91 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_GLTF2IMPORTER_H_INC
#define AI_GLTF2IMPORTER_H_INC
#include "BaseImporter.h"
#include <assimp/DefaultIOSystem.h>
struct aiNode;
namespace glTF2
{
class Asset;
}
namespace Assimp {
/**
* Load the glTF2 format.
* https://github.com/KhronosGroup/glTF/tree/master/specification
*/
class glTF2Importer : public BaseImporter{
public:
glTF2Importer();
virtual ~glTF2Importer();
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
protected:
virtual const aiImporterDesc* GetInfo() const;
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
private:
std::vector<unsigned int> meshOffsets;
std::vector<int> embeddedTexIdxs;
aiScene* mScene;
void ImportEmbeddedTextures(glTF2::Asset& a);
void ImportMaterials(glTF2::Asset& a);
void ImportMeshes(glTF2::Asset& a);
void ImportCameras(glTF2::Asset& a);
void ImportLights(glTF2::Asset& a);
void ImportNodes(glTF2::Asset& a);
};
} // Namespace assimp
#endif // AI_GLTF2IMPORTER_H_INC

View File

@ -1058,13 +1058,13 @@ namespace glTF
std::string version; //!< Specifies the target rendering API (default: "1.0.3") std::string version; //!< Specifies the target rendering API (default: "1.0.3")
} profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
float version; //!< The glTF format version (should be 1.0) std::string version; //!< The glTF format version (should be 1.0)
void Read(Document& doc); void Read(Document& doc);
AssetMetadata() AssetMetadata()
: premultipliedAlpha(false) : premultipliedAlpha(false)
, version(0) , version("")
{ {
} }
}; };

View File

@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "StringUtils.h" #include "StringUtils.h"
#include <iomanip>
// Header files, Assimp // Header files, Assimp
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -128,6 +129,12 @@ namespace {
return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
} }
inline Value* FindNumber(Value& val, const char* id)
{
Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
}
inline Value* FindArray(Value& val, const char* id) inline Value* FindArray(Value& val, const char* id)
{ {
Value::MemberIterator it = val.FindMember(id); Value::MemberIterator it = val.FindMember(id);
@ -309,7 +316,9 @@ inline void Buffer::Read(Value& obj, Asset& r)
} }
else { // Local file else { // Local file
if (byteLength > 0) { if (byteLength > 0) {
IOStream* file = r.OpenFile(uri, "rb"); std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : "";
IOStream* file = r.OpenFile(dir + uri, "rb");
if (file) { if (file) {
bool ok = LoadFromStream(*file, byteLength); bool ok = LoadFromStream(*file, byteLength);
delete file; delete file;
@ -1228,13 +1237,21 @@ inline void Scene::Read(Value& obj, Asset& r)
inline void AssetMetadata::Read(Document& doc) inline void AssetMetadata::Read(Document& doc)
{ {
// read the version, etc. // read the version, etc.
float statedVersion = 0;
if (Value* obj = FindObject(doc, "asset")) { if (Value* obj = FindObject(doc, "asset")) {
ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "copyright", copyright);
ReadMember(*obj, "generator", generator); ReadMember(*obj, "generator", generator);
premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false);
statedVersion = MemberOrDefault(*obj, "version", 0);
if (Value* versionString = FindString(*obj, "version")) {
version = versionString->GetString();
} else if (Value* versionNumber = FindNumber (*obj, "version")) {
char buf[4];
ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
version = buf;
}
if (Value* profile = FindObject(*obj, "profile")) { if (Value* profile = FindObject(*obj, "profile")) {
ReadMember(*profile, "api", this->profile.api); ReadMember(*profile, "api", this->profile.api);
@ -1242,16 +1259,8 @@ inline void AssetMetadata::Read(Document& doc)
} }
} }
version = std::max(statedVersion, version); if (version.empty() || version[0] != '1') {
if (version == 0) { throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
// if missing version, we'll assume version 1...
version = 1;
}
if (version != 1) {
char msg[128];
ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %.0f", version);
throw DeadlyImportError(msg);
} }
} }
@ -1273,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream)
} }
AI_SWAP4(header.version); AI_SWAP4(header.version);
asset.version = header.version; asset.version = std::to_string(header.version);
if (header.version != 1) { if (header.version != 1) {
throw DeadlyImportError("GLTF: Unsupported binary glTF version"); throw DeadlyImportError("GLTF: Unsupported binary glTF version");
} }

View File

@ -606,13 +606,8 @@ namespace glTF {
{ {
Value asset; Value asset;
asset.SetObject(); asset.SetObject();
{ asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
char versionChar[10]; asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
ai_snprintf(versionChar, sizeof(versionChar), "%.0f", mAsset.asset.version);
asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
}
mDoc.AddMember("asset", asset, mAl); mDoc.AddMember("asset", asset, mAl);
} }

View File

@ -507,7 +507,7 @@ void glTFExporter::ExportMeshes()
// Variables needed for compression. BEGIN. // Variables needed for compression. BEGIN.
// Indices, not pointers - because pointer to buffer is changing while writing to it. // Indices, not pointers - because pointer to buffer is changing while writing to it.
size_t idx_srcdata_begin;// Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer. size_t idx_srcdata_begin = 0; // Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer.
size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals. size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals.
std::vector<size_t> idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer. std::vector<size_t> idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer.
size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer. size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer.
@ -875,7 +875,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
timeData[i] = nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond; timeData[i] = nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond;
} }
Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, numKeyframes, &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT);
if (timeAccessor) animRef->Parameters.TIME = timeAccessor; if (timeAccessor) animRef->Parameters.TIME = timeAccessor;
} }
@ -888,7 +888,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue; translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue;
} }
Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, numKeyframes, translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if ( tranAccessor ) { if ( tranAccessor ) {
animRef->Parameters.translation = tranAccessor; animRef->Parameters.translation = tranAccessor;
} }
@ -904,7 +904,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue; scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue;
} }
Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, numKeyframes, scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if ( scaleAccessor ) { if ( scaleAccessor ) {
animRef->Parameters.scale = scaleAccessor; animRef->Parameters.scale = scaleAccessor;
} }
@ -923,7 +923,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w; rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w;
} }
Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, numKeyframes, rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if ( rotAccessor ) { if ( rotAccessor ) {
animRef->Parameters.rotation = rotAccessor; animRef->Parameters.rotation = rotAccessor;
} }

View File

@ -100,24 +100,19 @@ const aiImporterDesc* glTFImporter::GetInfo() const
bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{ {
const std::string& extension = GetExtension(pFile); const std::string &extension = GetExtension(pFile);
if (extension == "gltf" || extension == "glb") if (extension != "gltf" && extension != "glb")
return true; return false;
if ((checkSig || !extension.length()) && pIOHandler) { if (checkSig && pIOHandler) {
char buffer[4]; glTF::Asset asset(pIOHandler);
try {
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile)); asset.Load(pFile, extension == "glb");
if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { std::string version = asset.asset.version;
if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { return !version.empty() && version[0] == '1';
return true; // Has GLB header } catch (...) {
} return false;
else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0
|| memcmp(buffer, "{\n ", sizeof(buffer)) == 0) {
// seems a JSON file, and we're the only format that can read them
return true;
}
} }
} }

View File

@ -8,6 +8,11 @@ set( IrrXML_SRCS
irrXML.h irrXML.h
) )
if ( MSVC )
ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif ( MSVC )
add_library(IrrXML STATIC ${IrrXML_SRCS}) add_library(IrrXML STATIC ${IrrXML_SRCS})
set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" ) set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" )
set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" ) set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" )

View File

@ -65,7 +65,7 @@ SET( TEST_SRCS
unit/ut3DSImportExport.cpp unit/ut3DSImportExport.cpp
unit/utACImportExport.cpp unit/utACImportExport.cpp
unit/utAMFImportExport.cpp unit/utAMFImportExport.cpp
unit/utASEImportExport.cpp unit/utASEImportExport.cpp
unit/utAnim.cpp unit/utAnim.cpp
unit/AssimpAPITest.cpp unit/AssimpAPITest.cpp
unit/utB3DImportExport.cpp unit/utB3DImportExport.cpp
@ -88,6 +88,7 @@ SET( TEST_SRCS
unit/utFixInfacingNormals.cpp unit/utFixInfacingNormals.cpp
unit/utGenNormals.cpp unit/utGenNormals.cpp
unit/utglTFImportExport.cpp unit/utglTFImportExport.cpp
unit/utglTF2ImportExport.cpp
unit/utHMPImportExport.cpp unit/utHMPImportExport.cpp
unit/utIFCImportExport.cpp unit/utIFCImportExport.cpp
unit/utImporter.cpp unit/utImporter.cpp
@ -146,7 +147,7 @@ add_executable( unit
) )
add_definitions(-DASSIMP_TEST_MODELS_DIR="${CMAKE_CURRENT_LIST_DIR}/models") add_definitions(-DASSIMP_TEST_MODELS_DIR="${CMAKE_CURRENT_LIST_DIR}/models")
SET_PROPERTY( TARGET assimp PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) SET_PROPERTY( TARGET assimp PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} )
IF( WIN32 ) IF( WIN32 )

View File

@ -0,0 +1,181 @@
{
"asset": {
"generator": "COLLADA2GLTF",
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
-1.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
1.0
]
},
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 2,
"TEXCOORD_0": 3
},
"indices": 0,
"mode": 4,
"material": 0
}
],
"name": "Mesh"
}
],
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 36,
"max": [
23
],
"min": [
0
],
"type": "SCALAR"
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
1.0,
1.0,
1.0
],
"min": [
-1.0,
-1.0,
-1.0
],
"type": "VEC3"
},
{
"bufferView": 1,
"byteOffset": 288,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
6.0,
1.0
],
"min": [
0.0,
0.0
],
"type": "VEC2"
}
],
"materials": [
{
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
},
"name": "Texture"
}
],
"textures": [
{
"sampler": 0,
"source": 0
}
],
"images": [
{
"uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANMAAADTCAMAAAAs2dbrAAAAsVBMVEXc3Nz8/f3+//9chyf///+VsHP4+/thiy3Z29dyl0R8nlH09vJeiCqzxZ6ft4GLqWatwZXw9vyEpFynvYxmjjTS3cNrkjvu8urn8vre7fjY6ffL08K6yqbEz7XT183K4vTQ5fW62fC/zq3J17fn7d/g6NbC3fLb5c/l5eVsrd+wzOF/t+OWw+WGu+TE099vr+CmyON5tOJ0seG50OHL1t7S2d7Z29yOv+Wdx+emzuyx1O6AHuoWAAAIi0lEQVR4XuzUS3LEIAxF0WznIYk/xun9LyxDRqnqGANq4rODW4L39d88Ho/H43HkZPzJVYgoxhiIpDJ7k2z5wJpizSkBv4vCJn1OWTZMeE9gY/Xfx3DE30Q2WfGBvOAa8lZnEKFH0JZ1GEE/MnpGw54R93Cs41ip4k6SjuWPjnC3YJZWtaJdqhJhlJDWLINgJJm/FoUxGpfJ0xAxnvMTv1UWzEF21pG8wzT+2OZIjeTxScZhLmdGz13FfHXoAGbCCmHgVCSHNVwaleSxjh8z4Yxmj09VBGtRGbAOq1G+OSlgvZC3SwLijVE2Qodot7lS4+xGSS1quyS4O/5UIegSSm/SUaENHZ1NDH1qX5SHRmdPUoJOqWPyInS6Pn6HoNlkJxh68T6fqTFXkkrERPL9en0L3ueufKkf6uxmt1EYiAN4sP7i0pNPABeItEIdeV0vJMTA+z/YaqWo3WSS1gn2lP4ewFHEfNqexLi5hAIAvTgKZZ+4myQxpsSZUtomiD75yPM5Pqg8uDK5cbORZzT+p3JDgfxma16LK3WaceLUkxQPJjj6hnGbo2sHpkkxzB4didFgcgp23OJQ5BS4Pn6TeiM5PThYCva2vQmCHDgYCmZXfCbJfMpc9PXQk6QGTE0PMNv7TDSBmaM/IXqSVeKKdsSsy6gjCfMZLijWSVaXvomkzbiwRF/jR0fS3JThXTbTw8aAVVCcbXFW2wRv8oa+hVmaumoWS88YTgKFXNpBYHrd1GXfaaCfyI0CK7u0g0DoSfMCoSduTBF6Zto3bV033ewdiel/L/9+te3G6HOR35d4p/JmcjI9rVI4e9nd0z9XSStc08tAidkmw4cs6khuK3BK6ZlS6huFC6/xZj23z3BHbSiZOceVIto2aCrcp1N1BteByXe3DfQgq/EZNVMKQwUui5ROPscXFoqvL3HLa5R0sjkg/6eGEjcVMQajXuNraqK4XA3ufoey9AhXIURmUzyDhCbUya0/nFN6SHIbyK0vERMCqZZW4ikcXCQOcQ7nlgT1gVPFjvuz+vCXX4UCl/mEd+tAXhSsSDxT9rq/tJjbasJAFEWJm2QwF6NJVNra0hptoFVsERrp/39YXwTrbDWZOcf1GrLDhrMyF45elUMAVTjlR5NvrctNIsniFDB5HVzstJWEB+MUR/I5PdVRahtQcF3hSNxEkoMGhw+SAidmU1bqLjIFI5wwS670IwhPYvzHNCRweweZBiHOeBH8yik8KnBOtWal9GUqcc4T38D6h49gM0zoNLXTlqmGBQ/fXhDOhKyUskyrChYZ78ol4cyCpn+jKlMUw6bkTpJwxjgqJZ93jHgbIQt3Ukou0zOYkDv5rUw1rpDmtE9685VpYn91ZXp1OjiFs0xMpqXUa795z7mTRnjH0jvxuh77pXkP0a/TRh7erdSDh1ItybTERQruJA5nNJTia4+16dvp4C4Th+srxfOeDKHVaccyUTiRNnan6FNNpm6fvhTCmVlil3JTqh3wvDt1ksvE5PTeu5ZM3evTh0o4MxZcY+4eO2QSdeobzpgpK6UjU/d+b68TzszmvqvUhmRa4Aal05mwdQhnClbKU6bG4AYZn91dwv94t+MepYEgCuDTzhSudIFSgKIHKtwlaIBEe5cTv/8XM8ZEIrPtGxzw9zd5TcO83SbbgjKhSsnJXyZtRZfeHOFAmKut7fgF2siFdMyd1qQ0/nB7pZbN9WUacrcPpOwd4bev1B6USeuTdnA0FZqCF67h6Rae95y0r45wTO9SR0+ZtFCR9uIIx2agUv55H5H26gnHqp7906395W/TXWBkGD/7xOGiw/2VwvNeLxhaU8Qeh6eFCrd7ugxLjsbTrWTM2IPtTbeNIdxu9myr1EnNe8lYThFvL65wLAyilcLzPg+MZRTz6gzHRoaTgWYZKxNWUlRzZbi/UpKc4MNlUrHFI0Udrg73Vyo5oKP10pZseCexeR8J9ztXKvrNfvNR/nHeK2px3jC+T2zh/kql6ebPxnhcCph3VCett/zx7dfYHT6lINxTKWWy2aurqnnHdYqrRdLJu2UiAsId+s8S0XJVmbJNTm0+iwLCPZXC0jkbZdQqkRYq3CETq3rGRltqVUhUqsI9wlYAdbqFzB4IDp8O99Ln19iIHaMHhi/N+KbCohaDFZutqUPhWB9864RnP1yQAoav5NurCrjk9dlsRJ16KnzK9zAAN/XUZ7tH6nQ56cWY7yPvWiiSku3CgAD5yy7newmrRFrUFV9jSEAhZ8Uo8P2EQfyvSoYzVtDmZFwlihJku4VM31Vvm/N1pgQVv6PnWZ//g2pby1m6my5+cls3ubHCQBCASypZbiPbIGDYAF7wXpScYO5/tCxZBgb8g78btKpdbZ6kA/708/Vah35kKrbxy+v7/9frX9dOPE/hb2KYi+V5dsYBjk+icIjhc+gZhyz1xQRp+BQ6ALUF5XFYz2eYBIfNmo/gcILnEzQ4QwzLZ2ecstVTELuWpTOCk8LEwq04batm83Zvz5I1gg+IeczftY7L2+FDHUul8DFVzWPaSc8SjTMuCIblsRt2lfSEw0WLZVmsx2Wu5Mqro9FbwR0GlqMX3OLtyztM16n6RgJ8PYu36+qph52zzEwJ7rZoZjUggnViPtohitAwl2lFLIp5NAHxdDZTO8S0GqY2OkQmqp69220T07EDkggtU2lmpOLSRKUHJCTeMro2IK25Z1xmRXqLYTxjJ8jh7QzjGAdBLhJlKu0DcpLO8F7TEJDd1lrexjhBCd7Bj7yDVivKIe56WL/t2jEKwCAMheEsYirEBgNdohl6CO9/tM6FgrRdFPJNWX/I+BIbTMao/MhKYjAlo/3LE8bCChND5RLfLXxPhNl1wMYhxXHOtktDWInWHMr2mHakkEkRVoXaaiUWyVmEqTY1hOX1+z3mnHPOXX/B0DoXjBYdAAAAAElFTkSuQmCC"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 10497,
"wrapT": 10497
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 768,
"byteLength": 72,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 576,
"byteStride": 12,
"target": 34962
},
{
"buffer": 0,
"byteOffset": 576,
"byteLength": 192,
"byteStride": 8,
"target": 34962
}
],
"buffers": [
{
"byteLength": 840,
"uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA"
}
]
}

View File

@ -0,0 +1,197 @@
{
"asset": {
"generator": "COLLADA2GLTF",
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
-1.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
1.0
]
},
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 2,
"TEXCOORD_0": 3
},
"indices": 0,
"mode": 4,
"material": 0
}
],
"name": "Mesh"
}
],
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 36,
"max": [
23
],
"min": [
0
],
"type": "SCALAR"
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
1.0,
1.0,
1.0
],
"min": [
-1.0,
-1.0,
-1.0
],
"type": "VEC3"
},
{
"bufferView": 1,
"byteOffset": 288,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
6.0,
1.0
],
"min": [
0.0,
0.0
],
"type": "VEC2"
}
],
"materials": [
{
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
},
"extensions": {
"KHR_materials_pbrSpecularGlossiness": {
"diffuseTexture": {
"index": 0
},
"specularFactor": [
0.20000000298023225,
0.20000000298023225,
0.20000000298023225
],
"glossinessFactor": 1.0
}
},
"name": "Texture"
}
],
"textures": [
{
"sampler": 0,
"source": 0
}
],
"images": [
{
"uri": "CesiumLogoFlat.png"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 10497,
"wrapT": 10497
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 768,
"byteLength": 72,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 576,
"byteStride": 12,
"target": 34962
},
{
"buffer": 0,
"byteOffset": 576,
"byteLength": 192,
"byteStride": 8,
"target": 34962
}
],
"buffers": [
{
"byteLength": 840,
"uri": "BoxTextured0.bin"
}
],
"extensionsUsed": [
"KHR_materials_pbrSpecularGlossiness"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,282 @@
{
"asset": {
"generator": "COLLADA2GLTF",
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
-1.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
1.0
]
},
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 2,
"TEXCOORD_0": 3
},
"indices": 0,
"mode": 4,
"material": 0
}
],
"name": "Mesh"
}
],
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 36,
"max": [
23
],
"min": [
0
],
"type": "SCALAR"
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
1.0,
1.0,
1.0
],
"min": [
-1.0,
-1.0,
-1.0
],
"type": "VEC3"
},
{
"bufferView": 1,
"byteOffset": 288,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
6.0,
1.0
],
"min": [
0.0,
0.0
],
"type": "VEC2"
}
],
"materials": [
{
"values": {
"diffuse": [
0
],
"specular": [
0.20000000298023225,
0.20000000298023225,
0.20000000298023225,
1.0
],
"shininess": [
256.0
],
"transparency": [
1.0
]
},
"technique": 0
}
],
"textures": [
{
"sampler": 0,
"source": 0
}
],
"images": [
{
"uri": "CesiumLogoFlat.png"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 10497,
"wrapT": 10497
}
],
"techniques": [
{
"attributes": {
"a_normal": "normal",
"a_position": "position",
"a_texcoord0": "texcoord0"
},
"parameters": {
"diffuse": {
"type": 35678
},
"modelViewMatrix": {
"semantic": "MODELVIEW",
"type": 35676
},
"normal": {
"semantic": "NORMAL",
"type": 35665
},
"normalMatrix": {
"semantic": "MODELVIEWINVERSETRANSPOSE",
"type": 35675
},
"position": {
"semantic": "POSITION",
"type": 35665
},
"projectionMatrix": {
"semantic": "PROJECTION",
"type": 35676
},
"shininess": {
"type": 5126
},
"specular": {
"type": 35666
},
"texcoord0": {
"semantic": "TEXCOORD_0",
"type": 35665
},
"transparency": {
"type": 5126
}
},
"program": 0,
"states": {
"enable": [
2884,
2929
]
},
"uniforms": {
"u_diffuse": "diffuse",
"u_modelViewMatrix": "modelViewMatrix",
"u_normalMatrix": "normalMatrix",
"u_projectionMatrix": "projectionMatrix",
"u_shininess": "shininess",
"u_specular": "specular",
"u_transparency": "transparency"
}
}
],
"programs": [
{
"attributes": [
"a_normal",
"a_position",
"a_texcoord0"
],
"fragmentShader": 1,
"vertexShader": 0
}
],
"shaders": [
{
"type": 35633,
"uri": "BoxTextured0.vert"
},
{
"type": 35632,
"uri": "BoxTextured1.frag"
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 768,
"byteLength": 72,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 576,
"byteStride": 12,
"target": 34962
},
{
"buffer": 0,
"byteOffset": 576,
"byteLength": 192,
"byteStride": 8,
"target": 34962
}
],
"buffers": [
{
"byteLength": 840,
"uri": "BoxTextured0.bin"
}
],
"extensionsRequired": [
"KHR_technique_webgl"
],
"extensionsUsed": [
"KHR_technique_webgl"
]
}

View File

@ -0,0 +1,17 @@
precision highp float;
uniform mat4 u_modelViewMatrix;
uniform mat4 u_projectionMatrix;
uniform mat3 u_normalMatrix;
attribute vec3 a_position;
varying vec3 v_position;
attribute vec3 a_normal;
varying vec3 v_normal;
attribute vec2 a_texcoord0;
varying vec2 v_texcoord0;
void main(void) {
vec4 pos = u_modelViewMatrix * vec4(a_position,1.0);
v_position = pos.xyz;
gl_Position = u_projectionMatrix * pos;
v_normal = u_normalMatrix * a_normal;
v_texcoord0 = a_texcoord0;
}

View File

@ -0,0 +1,29 @@
precision highp float;
uniform sampler2D u_diffuse;
uniform vec4 u_specular;
uniform float u_shininess;
uniform float u_transparency;
varying vec3 v_position;
varying vec3 v_normal;
varying vec2 v_texcoord0;
void main(void) {
vec3 normal = normalize(v_normal);
vec4 diffuse = texture2D(u_diffuse, v_texcoord0);
vec3 diffuseLight = vec3(0.0, 0.0, 0.0);
vec3 specular = u_specular.rgb;
vec3 specularLight = vec3(0.0, 0.0, 0.0);
vec3 ambient = diffuse.rgb;
vec3 viewDir = -normalize(v_position);
vec3 ambientLight = vec3(0.0, 0.0, 0.0);
ambientLight += vec3(0.2, 0.2, 0.2);
vec3 l = vec3(0.0, 0.0, 1.0);
diffuseLight += vec3(1.0, 1.0, 1.0) * max(dot(normal, l), 0.);
vec3 reflectDir = reflect(-l, normal);
float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess));
specularLight += vec3(1.0, 1.0, 1.0) * specularIntensity;
vec3 color = vec3(0.0, 0.0, 0.0);
color += diffuse.rgb * diffuseLight;
color += specular * specularLight;
color += ambient * ambientLight;
gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,181 @@
{
"asset": {
"generator": "COLLADA2GLTF",
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"nodes": [
{
"children": [
1
],
"matrix": [
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
-1.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
1.0
]
},
{
"mesh": 0
}
],
"meshes": [
{
"primitives": [
{
"attributes": {
"NORMAL": 1,
"POSITION": 2,
"TEXCOORD_0": 3
},
"indices": 0,
"mode": 4,
"material": 0
}
],
"name": "Mesh"
}
],
"accessors": [
{
"bufferView": 0,
"byteOffset": 0,
"componentType": 5123,
"count": 36,
"max": [
23
],
"min": [
0
],
"type": "SCALAR"
},
{
"bufferView": 1,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
1.0,
1.0,
1.0
],
"min": [
-1.0,
-1.0,
-1.0
],
"type": "VEC3"
},
{
"bufferView": 1,
"byteOffset": 288,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
6.0,
1.0
],
"min": [
0.0,
0.0
],
"type": "VEC2"
}
],
"materials": [
{
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
},
"name": "Texture"
}
],
"textures": [
{
"sampler": 0,
"source": 0
}
],
"images": [
{
"uri": "CesiumLogoFlat.png"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 10497,
"wrapT": 10497
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 768,
"byteLength": 72,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 576,
"byteStride": 12,
"target": 34962
},
{
"buffer": 0,
"byteOffset": 576,
"byteLength": 192,
"byteStride": 8,
"target": 34962
}
],
"buffers": [
{
"byteLength": 840,
"uri": "BoxTextured0.bin"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,80 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#include "UnitTestPCH.h"
#include "AbstractImportExportBase.h"
#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
using namespace Assimp;
class utglTF2ImportExport : public AbstractImportExportBase {
public:
virtual bool importerTest() {
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0);
return nullptr != scene;
}
#ifndef ASSIMP_BUILD_NO_EXPORT
virtual bool exporterTest() {
Assimp::Importer importer;
Assimp::Exporter exporter;
const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0 );
EXPECT_NE( nullptr, scene );
EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) );
return true;
}
#endif // ASSIMP_BUILD_NO_EXPORT
};
TEST_F( utglTF2ImportExport, importglTF2FromFileTest ) {
EXPECT_TRUE( importerTest() );
}
#ifndef ASSIMP_BUILD_NO_EXPORT
TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) {
EXPECT_TRUE( exporterTest() );
}
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -55,6 +55,6 @@ public:
} }
}; };
TEST_F( utglTFImportExport, importglTFromFileTest ) { TEST_F( utglTFImportExport, importglTFFromFileTest ) {
EXPECT_TRUE( importerTest() ); EXPECT_TRUE( importerTest() );
} }