Merge branch 'master' of https://github.com/assimp/assimp
commit
d27e667f1e
32
.travis.yml
32
.travis.yml
|
@ -1,6 +1,8 @@
|
|||
sudo: required
|
||||
language: cpp
|
||||
|
||||
cache: ccache
|
||||
|
||||
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" = "osx" ]; then
|
||||
|
@ -20,24 +22,33 @@ branches:
|
|||
only:
|
||||
- master
|
||||
|
||||
osx_image: xcode8.3
|
||||
os:
|
||||
- linux
|
||||
|
||||
env:
|
||||
global:
|
||||
# COVERITY_SCAN_TOKEN
|
||||
- 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}
|
||||
|
||||
matrix:
|
||||
- os: linux LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
|
||||
exclude:
|
||||
- os: linux
|
||||
env:
|
||||
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
- os: linux LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
|
||||
compiler: clang
|
||||
- os: linux LINUX=1 SHARED_BUILD=ON TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
|
||||
env: LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
- os: linux LINUX=1 SHARED_BUILD=ON TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
|
||||
compiler: clang
|
||||
- os: osx
|
||||
osx_image: xcode8.2
|
||||
env: LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
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:
|
||||
- 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_REPO_TOKEN=abc12345
|
||||
- . ./.travis.sh
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
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
|
||||
|
|
|
@ -78,6 +78,10 @@ OPTION ( ASSIMP_COVERALLS
|
|||
"Enable this to measure test coverage."
|
||||
OFF
|
||||
)
|
||||
OPTION ( ASSIMP_WERRRO
|
||||
"Treat warnings as errors."
|
||||
OFF
|
||||
)
|
||||
OPTION ( SYSTEM_IRRXML
|
||||
"Use system installed Irrlicht/IrrXML library."
|
||||
OFF
|
||||
|
@ -212,6 +216,11 @@ if (ASSIMP_COVERALLS)
|
|||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
if (ASSIMP_WERROR)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||
endif()
|
||||
|
||||
INCLUDE (FindPkgMacros)
|
||||
INCLUDE (PrecompiledHeader)
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ __Importers__:
|
|||
- DXF
|
||||
- ENFF
|
||||
- FBX
|
||||
- GLB/GLTF
|
||||
- glTF 1.0 + GLB
|
||||
- glTF 2.0
|
||||
- HMB
|
||||
- IFC-STEP
|
||||
- IRR / IRRMESH
|
||||
|
@ -106,8 +107,8 @@ __Exporters__:
|
|||
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
|
||||
- ASSBIN
|
||||
- STEP
|
||||
- glTF (partial)
|
||||
- glTF2.0
|
||||
- glTF 1.0 (partial)
|
||||
- glTF 2.0 (partial)
|
||||
|
||||
### 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.
|
||||
|
@ -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)
|
||||
* [Javascript (Alpha)](https://github.com/makc/assimp2json)
|
||||
* [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 ###
|
||||
[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
|
||||
|
|
|
@ -1381,7 +1381,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent )
|
|||
bGamma = true;
|
||||
|
||||
case Discreet3DS::CHUNK_RGBF:
|
||||
if (sizeof(ai_real) * 3 > diff) {
|
||||
if (sizeof(float) * 3 > diff) {
|
||||
*out = clrError;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -139,6 +139,17 @@ inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
|
|||
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
|
||||
template <>
|
||||
|
@ -325,7 +336,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
|
|||
{
|
||||
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<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<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
|
||||
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
|
||||
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
|
||||
Write<aiColor3D>(&chunk,l->mColorDiffuse);
|
||||
Write<aiColor3D>(&chunk,l->mColorSpecular);
|
||||
Write<aiColor3D>(&chunk,l->mColorAmbient);
|
||||
|
||||
if (l->mType == aiLightSource_SPOT) {
|
||||
Write<float>(&chunk,l->mAngleInnerCone);
|
||||
|
|
|
@ -61,6 +61,7 @@ SET( PUBLIC_HEADERS
|
|||
${HEADER_PATH}/color4.inl
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h
|
||||
${HEADER_PATH}/defs.h
|
||||
${HEADER_PATH}/Defines.h
|
||||
${HEADER_PATH}/cfileio.h
|
||||
${HEADER_PATH}/light.h
|
||||
${HEADER_PATH}/material.h
|
||||
|
@ -665,6 +666,8 @@ ADD_ASSIMP_IMPORTER( GLTF
|
|||
glTF2Asset.inl
|
||||
glTF2AssetWriter.h
|
||||
glTF2AssetWriter.inl
|
||||
glTF2Importer.cpp
|
||||
glTF2Importer.h
|
||||
glTF2Exporter.h
|
||||
glTF2Exporter.cpp
|
||||
)
|
||||
|
|
|
@ -866,8 +866,8 @@ void ColladaExporter::WriteController( size_t pIndex)
|
|||
|
||||
std::vector<ai_real> bind_poses;
|
||||
bind_poses.reserve(mesh->mNumBones * 16);
|
||||
for( size_t i = 0; i < mesh->mNumBones; ++i)
|
||||
for( size_t j = 0; j < 4; ++j)
|
||||
for(unsigned int i = 0; i < mesh->mNumBones; ++i)
|
||||
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);
|
||||
|
||||
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;
|
||||
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( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
|
||||
for( unsigned int i = 0; i < mesh->mNumBones; ++i)
|
||||
for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
if (!pIOHandler)return true;
|
||||
const char* tokens[] = {"collada"};
|
||||
const char* tokens[] = {"<collada"};
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||
}
|
||||
return false;
|
||||
|
@ -728,7 +728,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|||
? aiMorphingMethod_MORPH_RELATIVE
|
||||
: aiMorphingMethod_MORPH_NORMALIZED;
|
||||
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++)
|
||||
dstMesh->mAnimMeshes[i] = animMeshes.at(i);
|
||||
}
|
||||
|
@ -1377,9 +1377,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
{
|
||||
aiNodeAnim* dstAnim = new aiNodeAnim;
|
||||
dstAnim->mNodeName = nodeName;
|
||||
dstAnim->mNumPositionKeys = resultTrafos.size();
|
||||
dstAnim->mNumRotationKeys= resultTrafos.size();
|
||||
dstAnim->mNumScalingKeys = resultTrafos.size();
|
||||
dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
|
||||
dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
|
||||
dstAnim->mNumScalingKeys = static_cast<unsigned int>(resultTrafos.size());
|
||||
dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
|
||||
dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
|
||||
dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
|
||||
|
@ -1445,11 +1445,11 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
++morphAnimChannelIndex;
|
||||
}
|
||||
|
||||
morphAnim->mNumKeys = morphTimeValues.size();
|
||||
morphAnim->mNumKeys = static_cast<unsigned int>(morphTimeValues.size());
|
||||
morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys];
|
||||
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].mWeights = new double [morphChannels.size()];
|
||||
|
||||
|
@ -1470,13 +1470,13 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
|
|||
{
|
||||
aiAnimation* anim = new aiAnimation;
|
||||
anim->mName.Set( pName);
|
||||
anim->mNumChannels = anims.size();
|
||||
anim->mNumChannels = static_cast<unsigned int>(anims.size());
|
||||
if (anim->mNumChannels > 0)
|
||||
{
|
||||
anim->mChannels = new aiNodeAnim*[anims.size()];
|
||||
std::copy( anims.begin(), anims.end(), anim->mChannels);
|
||||
}
|
||||
anim->mNumMorphMeshChannels = morphAnims.size();
|
||||
anim->mNumMorphMeshChannels = static_cast<unsigned int>(morphAnims.size());
|
||||
if (anim->mNumMorphMeshChannels > 0)
|
||||
{
|
||||
anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];
|
||||
|
|
|
@ -87,17 +87,16 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurve::~AnimationCurve()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
|
||||
const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/)
|
||||
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name,
|
||||
const Document& doc, const char* const * target_prop_whitelist /*= NULL*/,
|
||||
size_t whitelist_size /*= 0*/)
|
||||
: Object(id, element, name)
|
||||
, target()
|
||||
, doc(doc)
|
||||
|
@ -154,14 +153,12 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
|
|||
props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurveNode::~AnimationCurveNode()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const AnimationCurveMap& AnimationCurveNode::Curves() const
|
||||
{
|
||||
|
@ -195,7 +192,6 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
|
|||
return curves;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
||||
: 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);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationLayer::~AnimationLayer()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
|
||||
size_t whitelist_size /*= 0*/) const
|
||||
|
@ -298,14 +292,13 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
AnimationStack::~AnimationStack()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
} //!FBX
|
||||
} //!Assimp
|
||||
|
||||
#endif
|
||||
#endif // ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
|
|
|
@ -66,4 +66,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // INCLUDED_AI_FBX_COMPILECONFIG_H
|
||||
|
|
|
@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "StringComparison.h"
|
||||
|
||||
#include <assimp/scene.h>
|
||||
|
||||
#include <tuple>
|
||||
#include <memory>
|
||||
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
|
@ -949,8 +949,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra
|
|||
return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
|
||||
}
|
||||
|
||||
void Converter::GenerateTransformationNodeChain( const Model& model,
|
||||
std::vector<aiNode*>& output_nodes )
|
||||
void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
|
||||
{
|
||||
const PropertyTable& props = model.Props();
|
||||
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,
|
||||
const aiVector3D& def_value,
|
||||
double& maxTime,
|
||||
|
@ -3145,7 +3143,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
|
|||
|
||||
valOut[ i ].mTime = temp[ i ].mTime;
|
||||
|
||||
|
||||
GetRotationMatrix( order, temp[ i ].mValue, 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,
|
||||
aiVectorKey* out_translation,
|
||||
const KeyFrameListList& scaling,
|
||||
|
@ -3223,7 +3219,6 @@ void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order )
|
||||
{
|
||||
aiMatrix4x4 m;
|
||||
|
@ -3232,7 +3227,6 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde
|
|||
return aiQuaternion( aiMatrix3x3( m ) );
|
||||
}
|
||||
|
||||
|
||||
void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
|
||||
int64_t start, int64_t stop,
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||
const LayerMap& /*layers*/,
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||
const LayerMap& /*layers*/,
|
||||
int64_t start, int64_t stop,
|
||||
|
@ -3294,7 +3286,8 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const Ani
|
|||
|
||||
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
|
||||
// many C++ users seem to know this, so pointing it out to avoid
|
||||
|
|
|
@ -70,13 +70,13 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
|
|||
, id(id)
|
||||
, flags()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LazyObject::~LazyObject()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -232,16 +232,15 @@ Object::Object(uint64_t id, const Element& element, const std::string& name)
|
|||
, name(name)
|
||||
, id(id)
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object::~Object()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
|
||||
: props(props)
|
||||
|
@ -361,7 +360,6 @@ void Document::ReadGlobalSettings()
|
|||
globals.reset(new FileGlobalSettings(*this, props));
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Document::ReadObjects()
|
||||
{
|
||||
|
@ -387,7 +385,6 @@ void Document::ReadObjects()
|
|||
}
|
||||
|
||||
const char* err;
|
||||
|
||||
const uint64_t id = ParseTokenAsID(*tok[0], err);
|
||||
if(err) {
|
||||
DOMError(err,el.second);
|
||||
|
@ -469,8 +466,6 @@ void Document::ReadPropertyTemplates()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Document::ReadConnections()
|
||||
{
|
||||
|
@ -482,7 +477,6 @@ void Document::ReadConnections()
|
|||
}
|
||||
|
||||
uint64_t insertionOrder = 0l;
|
||||
|
||||
const Scope& sconns = *econns->Compound();
|
||||
const ElementCollection conns = sconns.GetCollection("C");
|
||||
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
|
||||
// (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 dest = ParseTokenAsID(GetRequiredToken(el,2));
|
||||
|
@ -518,11 +514,10 @@ void Document::ReadConnections()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const std::vector<const AnimationStack*>& Document::AnimationStacks() const
|
||||
{
|
||||
if (!animationStacksResolved.empty() || !animationStacks.size()) {
|
||||
if (!animationStacksResolved.empty() || animationStacks.empty()) {
|
||||
return animationStacksResolved;
|
||||
}
|
||||
|
||||
|
@ -540,7 +535,6 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
|
|||
return animationStacksResolved;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LazyObject* Document::GetObject(uint64_t id) const
|
||||
{
|
||||
|
@ -551,8 +545,7 @@ LazyObject* Document::GetObject(uint64_t id) const
|
|||
#define MAX_CLASSNAMES 6
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
|
||||
const ConnectionMap& conns) const
|
||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
|
||||
{
|
||||
std::vector<const Connection*> temp;
|
||||
|
||||
|
@ -569,7 +562,6 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
|
|||
return temp; // NRVO should handle this
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
|
||||
const ConnectionMap& conns,
|
||||
|
@ -578,7 +570,8 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
|||
|
||||
{
|
||||
ai_assert(classnames);
|
||||
ai_assert(count != 0 && count <= MAX_CLASSNAMES);
|
||||
ai_assert( count != 0 );
|
||||
ai_assert( count <= MAX_CLASSNAMES);
|
||||
|
||||
size_t lenghts[MAX_CLASSNAMES];
|
||||
|
||||
|
@ -588,7 +581,6 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
|||
}
|
||||
|
||||
std::vector<const Connection*> temp;
|
||||
|
||||
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
|
||||
conns.equal_range(id);
|
||||
|
||||
|
@ -620,25 +612,19 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
|
|||
return temp; // NRVO should handle this
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
|
||||
{
|
||||
return GetConnectionsSequenced(source, ConnectionsBySource());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest,
|
||||
const char* classname) const
|
||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest, const char* classname) const
|
||||
{
|
||||
const char* arr[] = {classname};
|
||||
return GetConnectionsBySourceSequenced(dest, arr,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
|
||||
const char* const* classnames, size_t count) const
|
||||
|
@ -646,7 +632,6 @@ std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_
|
|||
return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
|
||||
const char* classname) const
|
||||
|
@ -655,14 +640,12 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
|
|||
return GetConnectionsByDestinationSequenced(dest, arr,1);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
|
||||
{
|
||||
return GetConnectionsSequenced(dest, ConnectionsByDestination());
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
|
||||
const char* const* classnames, size_t count) const
|
||||
|
@ -671,7 +654,6 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
|
|||
return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
|
||||
const Document& doc)
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::~Connection()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LazyObject& Connection::LazySourceObject() const
|
||||
{
|
||||
|
@ -703,7 +683,6 @@ LazyObject& Connection::LazySourceObject() const
|
|||
return *lazy;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
LazyObject& Connection::LazyDestinationObject() const
|
||||
{
|
||||
|
@ -712,7 +691,6 @@ LazyObject& Connection::LazyDestinationObject() const
|
|||
return *lazy;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const Object* Connection::SourceObject() const
|
||||
{
|
||||
|
@ -721,7 +699,6 @@ const Object* Connection::SourceObject() const
|
|||
return lazy->Get();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const Object* Connection::DestinationObject() const
|
||||
{
|
||||
|
@ -734,4 +711,3 @@ const Object* Connection::DestinationObject() const
|
|||
} // !Assimp
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -338,12 +338,7 @@ public:
|
|||
class Model : public Object
|
||||
{
|
||||
public:
|
||||
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
|
||||
virtual ~Model();
|
||||
|
||||
public:
|
||||
enum RotOrder
|
||||
{
|
||||
enum RotOrder {
|
||||
RotOrder_EulerXYZ = 0,
|
||||
RotOrder_EulerXZY,
|
||||
RotOrder_EulerYZX,
|
||||
|
@ -357,8 +352,7 @@ public:
|
|||
};
|
||||
|
||||
|
||||
enum TransformInheritance
|
||||
{
|
||||
enum TransformInheritance {
|
||||
TransformInheritance_RrSs = 0,
|
||||
TransformInheritance_RSrs,
|
||||
TransformInheritance_Rrs,
|
||||
|
@ -366,7 +360,10 @@ public:
|
|||
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(RotationOffset, aiVector3D, aiVector3D())
|
||||
|
@ -443,7 +440,6 @@ public:
|
|||
fbx_simple_property(LODBox, bool, false)
|
||||
fbx_simple_property(Freeze, bool, false)
|
||||
|
||||
public:
|
||||
const std::string& Shading() const {
|
||||
return shading;
|
||||
}
|
||||
|
@ -462,13 +458,11 @@ public:
|
|||
return materials;
|
||||
}
|
||||
|
||||
|
||||
/** Get geometry links */
|
||||
const std::vector<const Geometry*>& GetGeometry() const {
|
||||
return geometry;
|
||||
}
|
||||
|
||||
|
||||
/** Get node attachments */
|
||||
const std::vector<const NodeAttribute*>& GetAttributes() const {
|
||||
return attributes;
|
||||
|
@ -477,7 +471,6 @@ public:
|
|||
/** convenience method to check if the node has a Null node marker */
|
||||
bool IsNull() const;
|
||||
|
||||
|
||||
private:
|
||||
void ResolveLinks(const Element& element, const Document& doc);
|
||||
|
||||
|
@ -805,7 +798,6 @@ private:
|
|||
|
||||
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
|
||||
|
||||
|
||||
/** Represents a FBX animation layer (i.e. a list of node animations) */
|
||||
class AnimationLayer : public Object
|
||||
{
|
||||
|
@ -828,10 +820,8 @@ private:
|
|||
const Document& doc;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<const AnimationLayer*> AnimationLayerList;
|
||||
|
||||
|
||||
/** Represents a FBX animation stack (i.e. a list of animation layers) */
|
||||
class AnimationStack : public Object
|
||||
{
|
||||
|
@ -839,7 +829,6 @@ public:
|
|||
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
|
||||
virtual ~AnimationStack();
|
||||
|
||||
public:
|
||||
fbx_simple_property(LocalStart, int64_t, 0L)
|
||||
fbx_simple_property(LocalStop, int64_t, 0L)
|
||||
fbx_simple_property(ReferenceStart, int64_t, 0L)
|
||||
|
@ -879,7 +868,6 @@ private:
|
|||
typedef std::vector<float> WeightArray;
|
||||
typedef std::vector<unsigned int> WeightIndexArray;
|
||||
|
||||
|
||||
/** DOM class for skin deformer clusters (aka subdeformers) */
|
||||
class Cluster : public Deformer
|
||||
{
|
||||
|
@ -924,8 +912,6 @@ private:
|
|||
const Model* node;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** DOM class for skin deformers */
|
||||
class Skin : public Deformer
|
||||
{
|
||||
|
@ -1009,10 +995,8 @@ public:
|
|||
typedef std::map<uint64_t, LazyObject*> ObjectMap;
|
||||
typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
|
||||
|
||||
|
||||
typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
|
||||
|
||||
|
||||
/** DOM class for global document settings, a single instance per document can
|
||||
* be accessed via Document.Globals(). */
|
||||
class FileGlobalSettings
|
||||
|
@ -1074,9 +1058,6 @@ private:
|
|||
const Document& doc;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** DOM root for a FBX file */
|
||||
class Document
|
||||
{
|
||||
|
@ -1154,8 +1135,6 @@ private:
|
|||
const ConnectionMap&,
|
||||
const char* const* classnames,
|
||||
size_t count) const;
|
||||
|
||||
private:
|
||||
void ReadHeader();
|
||||
void ReadObjects();
|
||||
void ReadPropertyTemplates();
|
||||
|
|
|
@ -77,14 +77,12 @@ Model::Model(uint64_t id, const Element& element, const Document& doc, const std
|
|||
ResolveLinks(element,doc);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Model::~Model()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
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
|
||||
{
|
||||
|
|
|
@ -75,7 +75,7 @@ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
NodeAttribute::~NodeAttribute()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,33 +101,30 @@ CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Docume
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CameraSwitcher::~CameraSwitcher()
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Camera::~Camera()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
||||
: NodeAttribute(id,element,doc,name)
|
||||
{
|
||||
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -224,41 +224,36 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
|
|||
root.reset(new Scope(*this,true));
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Parser::~Parser()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::AdvanceToNextToken()
|
||||
{
|
||||
last = current;
|
||||
if (cursor == tokens.end()) {
|
||||
current = NULL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
current = *cursor++;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::CurrentToken() const
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
TokenPtr Parser::LastToken() const
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
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());
|
||||
ai_assert(length > 0);
|
||||
|
||||
const char* out;
|
||||
const char* out = nullptr;
|
||||
const uint64_t id = strtoul10_64(t.begin(),&out,&length);
|
||||
if (out > t.end()) {
|
||||
err_out = "failed to parse ID (text)";
|
||||
|
@ -296,7 +291,6 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
|
|||
return id;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
const char* out;
|
||||
const char* out = nullptr;
|
||||
const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
|
||||
if (out > t.end()) {
|
||||
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());
|
||||
ai_assert(length > 0);
|
||||
|
||||
const char* out;
|
||||
const char* out = nullptr;
|
||||
const int64_t id = strtol10_64(t.begin(), &out, &length);
|
||||
if (out > t.end()) {
|
||||
err_out = "failed to parse Int64 (text)";
|
||||
|
|
|
@ -85,12 +85,9 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
|
|||
class Element
|
||||
{
|
||||
public:
|
||||
|
||||
Element(const Token& key_token, Parser& parser);
|
||||
~Element();
|
||||
|
||||
public:
|
||||
|
||||
const Scope* Compound() const {
|
||||
return compound.get();
|
||||
}
|
||||
|
@ -104,14 +101,11 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
const Token& key_token;
|
||||
TokenList tokens;
|
||||
std::unique_ptr<Scope> compound;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** FBX data entity that consists of a 'scope', a collection
|
||||
* of not necessarily unique #Element instances.
|
||||
*
|
||||
|
@ -125,14 +119,10 @@ private:
|
|||
* @endverbatim */
|
||||
class Scope
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
Scope(Parser& parser, bool topLevel = false);
|
||||
~Scope();
|
||||
|
||||
public:
|
||||
|
||||
const Element* operator[] (const std::string& index) const {
|
||||
ElementMap::const_iterator it = elements.find(index);
|
||||
return it == elements.end() ? NULL : (*it).second;
|
||||
|
@ -158,28 +148,23 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
ElementMap elements;
|
||||
};
|
||||
|
||||
|
||||
/** FBX parsing class, takes a list of input tokens and generates a hierarchy
|
||||
* of nested #Scope instances, representing the fbx DOM.*/
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
|
||||
/** Parse given a token list. Does not take ownership of the tokens -
|
||||
* the objects must persist during the entire parser lifetime */
|
||||
Parser (const TokenList& tokens,bool is_binary);
|
||||
~Parser();
|
||||
|
||||
public:
|
||||
const Scope& GetRootScope() const {
|
||||
return *root.get();
|
||||
}
|
||||
|
||||
|
||||
bool IsBinary() const {
|
||||
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<int64_t>& out, const Element& el);
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -243,8 +226,6 @@ const Scope& GetRequiredScope(const Element& el);
|
|||
// get token at a particular index
|
||||
const Token& GetRequiredToken(const Element& el, unsigned int index);
|
||||
|
||||
|
||||
|
||||
// read a 4x4 matrix from an array of 16 floats
|
||||
aiMatrix4x4 ReadMatrix(const Element& element);
|
||||
|
||||
|
|
|
@ -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.vertcnt.push_back(segments);
|
||||
meshout.vertcnt.push_back(static_cast<unsigned int>(segments));
|
||||
}
|
||||
else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) {
|
||||
// construct simplified IBeam shape
|
||||
|
|
|
@ -182,6 +182,7 @@ corresponding preprocessor flag to selectively disable formats.
|
|||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
|
||||
# include "glTFImporter.h"
|
||||
# include "glTF2Importer.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
|
||||
# include "C4DImporter.h"
|
||||
|
@ -336,6 +337,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
|||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
|
||||
out.push_back( new glTFImporter() );
|
||||
out.push_back( new glTF2Importer() );
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
|
||||
out.push_back( new C4DImporter() );
|
||||
|
|
|
@ -278,7 +278,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
|
|||
bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back(
|
||||
aiVertexWeight(index, vsBDEF2_ptr->bone_weight));
|
||||
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;
|
||||
case pmx::PmxVertexSkinningType::BDEF4:
|
||||
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(
|
||||
aiVertexWeight(index, vsSDEF_ptr->bone_weight));
|
||||
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;
|
||||
case pmx::PmxVertexSkinningType::QDEF:
|
||||
const auto vsQDEF_ptr =
|
||||
|
@ -325,7 +325,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
|
|||
aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix);
|
||||
auto it = bone_vertex_map.find(ii);
|
||||
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();
|
||||
it->second.swap(*(new vector<aiVertexWeight>));
|
||||
}
|
||||
|
|
|
@ -49,17 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace pmd
|
||||
{
|
||||
/// ヘッダ
|
||||
class PmdHeader
|
||||
{
|
||||
public:
|
||||
/// モデル名
|
||||
std::string name;
|
||||
/// モデル名(英語)
|
||||
std::string name_english;
|
||||
/// コメント
|
||||
std::string comment;
|
||||
/// コメント(英語)
|
||||
std::string comment_english;
|
||||
|
||||
bool Read(std::ifstream* stream)
|
||||
|
@ -83,26 +78,19 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// 頂点
|
||||
class PmdVertex
|
||||
{
|
||||
public:
|
||||
/// 位置
|
||||
float position[3];
|
||||
|
||||
/// 法線
|
||||
float normal[3];
|
||||
|
||||
/// UV座標
|
||||
float uv[2];
|
||||
|
||||
/// 関連ボーンインデックス
|
||||
uint16_t bone_index[2];
|
||||
|
||||
/// ボーンウェイト
|
||||
uint8_t bone_weight;
|
||||
|
||||
/// エッジ不可視
|
||||
bool edge_invisible;
|
||||
|
||||
bool Read(std::ifstream* stream)
|
||||
|
@ -117,27 +105,17 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// 材質
|
||||
class PmdMaterial
|
||||
{
|
||||
public:
|
||||
/// 減衰色
|
||||
float diffuse[4];
|
||||
/// 光沢度
|
||||
float power;
|
||||
/// 光沢色
|
||||
float specular[3];
|
||||
/// 環境色
|
||||
float ambient[3];
|
||||
/// トーンインデックス
|
||||
uint8_t toon_index;
|
||||
/// エッジ
|
||||
uint8_t edge_flag;
|
||||
/// インデックス数
|
||||
uint32_t index_count;
|
||||
/// テクスチャファイル名
|
||||
std::string texture_filename;
|
||||
/// スフィアファイル名
|
||||
std::string sphere_filename;
|
||||
|
||||
bool Read(std::ifstream* stream)
|
||||
|
@ -180,23 +158,15 @@ namespace pmd
|
|||
RotationMovement
|
||||
};
|
||||
|
||||
/// ボーン
|
||||
class PmdBone
|
||||
{
|
||||
public:
|
||||
/// ボーン名
|
||||
std::string name;
|
||||
/// ボーン名(英語)
|
||||
std::string name_english;
|
||||
/// 親ボーン番号
|
||||
uint16_t parent_bone_index;
|
||||
/// 末端ボーン番号
|
||||
uint16_t tail_pos_bone_index;
|
||||
/// ボーン種類
|
||||
BoneType bone_type;
|
||||
/// IKボーン番号
|
||||
uint16_t ik_parent_bone_index;
|
||||
/// ボーンのヘッドの位置
|
||||
float bone_head_pos[3];
|
||||
|
||||
void Read(std::istream *stream)
|
||||
|
@ -219,19 +189,13 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// IK
|
||||
class PmdIk
|
||||
{
|
||||
public:
|
||||
/// IKボーン番号
|
||||
uint16_t ik_bone_index;
|
||||
/// IKターゲットボーン番号
|
||||
uint16_t target_bone_index;
|
||||
/// 再帰回数
|
||||
uint16_t interations;
|
||||
/// 角度制限
|
||||
float angle_limit;
|
||||
/// 影響下ボーン番号
|
||||
std::vector<uint16_t> ik_child_bone_index;
|
||||
|
||||
void Read(std::istream *stream)
|
||||
|
@ -303,7 +267,6 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// ボーン枠用の枠名
|
||||
class PmdBoneDispName
|
||||
{
|
||||
public:
|
||||
|
@ -338,59 +301,36 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// 衝突形状
|
||||
enum class RigidBodyShape : uint8_t
|
||||
{
|
||||
/// 球
|
||||
Sphere = 0,
|
||||
/// 直方体
|
||||
Box = 1,
|
||||
/// カプセル
|
||||
Cpusel = 2
|
||||
};
|
||||
|
||||
/// 剛体タイプ
|
||||
enum class RigidBodyType : uint8_t
|
||||
{
|
||||
/// ボーン追従
|
||||
BoneConnected = 0,
|
||||
/// 物理演算
|
||||
Physics = 1,
|
||||
/// 物理演算(Bone位置合せ)
|
||||
ConnectedPhysics = 2
|
||||
};
|
||||
|
||||
/// 剛体
|
||||
class PmdRigidBody
|
||||
{
|
||||
public:
|
||||
/// 名前
|
||||
std::string name;
|
||||
/// 関連ボーン番号
|
||||
uint16_t related_bone_index;
|
||||
/// グループ番号
|
||||
uint8_t group_index;
|
||||
/// マスク
|
||||
uint16_t mask;
|
||||
/// 形状
|
||||
RigidBodyShape shape;
|
||||
/// 大きさ
|
||||
float size[3];
|
||||
/// 位置
|
||||
float position[3];
|
||||
/// 回転
|
||||
float orientation[3];
|
||||
/// 質量
|
||||
float weight;
|
||||
/// 移動ダンピング
|
||||
float linear_damping;
|
||||
/// 回転ダンピング
|
||||
float anglar_damping;
|
||||
/// 反発係数
|
||||
float restitution;
|
||||
/// 摩擦係数
|
||||
float friction;
|
||||
/// 演算方法
|
||||
RigidBodyType rigid_type;
|
||||
|
||||
void Read(std::istream *stream)
|
||||
|
@ -414,31 +354,19 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// 剛体の拘束
|
||||
class PmdConstraint
|
||||
{
|
||||
public:
|
||||
/// 名前
|
||||
std::string name;
|
||||
/// 剛体Aのインデックス
|
||||
uint32_t rigid_body_index_a;
|
||||
/// 剛体Bのインデックス
|
||||
uint32_t rigid_body_index_b;
|
||||
/// 位置
|
||||
float position[3];
|
||||
/// 回転
|
||||
float orientation[3];
|
||||
/// 最小移動制限
|
||||
float linear_lower_limit[3];
|
||||
/// 最大移動制限
|
||||
float linear_upper_limit[3];
|
||||
/// 最小回転制限
|
||||
float angular_lower_limit[3];
|
||||
/// 最大回転制限
|
||||
float angular_upper_limit[3];
|
||||
/// 移動に対する復元力
|
||||
float linear_stiffness[3];
|
||||
/// 回転に対する復元力
|
||||
float angular_stiffness[3];
|
||||
|
||||
void Read(std::istream *stream)
|
||||
|
@ -459,7 +387,6 @@ namespace pmd
|
|||
}
|
||||
};
|
||||
|
||||
/// PMDモデル
|
||||
class PmdModel
|
||||
{
|
||||
public:
|
||||
|
@ -491,7 +418,6 @@ namespace pmd
|
|||
return result;
|
||||
}
|
||||
|
||||
/// ファイルからPmdModelを生成する
|
||||
static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
|
||||
{
|
||||
auto result = mmd::make_unique<PmdModel>();
|
||||
|
|
|
@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace pmx
|
||||
{
|
||||
/// インデックス値を読み込む
|
||||
int ReadIndex(std::istream *stream, int size)
|
||||
{
|
||||
switch (size)
|
||||
|
@ -79,7 +78,6 @@ namespace pmx
|
|||
}
|
||||
}
|
||||
|
||||
/// 文字列を読み込む
|
||||
std::string ReadString(std::istream *stream, uint8_t encoding)
|
||||
{
|
||||
int size;
|
||||
|
@ -607,7 +605,6 @@ namespace pmx
|
|||
this->joints[i].Read(stream, &setting);
|
||||
}
|
||||
|
||||
//// ソフトボディ
|
||||
//if (this->version == 2.1f)
|
||||
//{
|
||||
// stream->read((char*) &this->soft_body_count, sizeof(int));
|
||||
|
|
|
@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace pmx
|
||||
{
|
||||
/// インデックス設定
|
||||
class PmxSetting
|
||||
{
|
||||
public:
|
||||
|
@ -64,26 +63,17 @@ namespace pmx
|
|||
, rigidbody_index_size(0)
|
||||
{}
|
||||
|
||||
/// エンコード方式
|
||||
uint8_t encoding;
|
||||
/// 追加UV数
|
||||
uint8_t uv;
|
||||
/// 頂点インデックスサイズ
|
||||
uint8_t vertex_index_size;
|
||||
/// テクスチャインデックスサイズ
|
||||
uint8_t texture_index_size;
|
||||
/// マテリアルインデックスサイズ
|
||||
uint8_t material_index_size;
|
||||
/// ボーンインデックスサイズ
|
||||
uint8_t bone_index_size;
|
||||
/// モーフインデックスサイズ
|
||||
uint8_t morph_index_size;
|
||||
/// 剛体インデックスサイズ
|
||||
uint8_t rigidbody_index_size;
|
||||
void Read(std::istream *stream);
|
||||
};
|
||||
|
||||
/// 頂点スキニングタイプ
|
||||
enum class PmxVertexSkinningType : uint8_t
|
||||
{
|
||||
BDEF1 = 0,
|
||||
|
@ -93,7 +83,6 @@ namespace pmx
|
|||
QDEF = 4,
|
||||
};
|
||||
|
||||
/// 頂点スキニング
|
||||
class PmxVertexSkinning
|
||||
{
|
||||
public:
|
||||
|
@ -200,7 +189,6 @@ namespace pmx
|
|||
void Read(std::istream *stresam, PmxSetting *setting);
|
||||
};
|
||||
|
||||
/// 頂点
|
||||
class PmxVertex
|
||||
{
|
||||
public:
|
||||
|
@ -219,24 +207,16 @@ namespace pmx
|
|||
}
|
||||
}
|
||||
|
||||
/// 位置
|
||||
float position[3];
|
||||
/// 法線
|
||||
float normal[3];
|
||||
/// テクスチャ座標
|
||||
float uv[2];
|
||||
/// 追加テクスチャ座標
|
||||
float uva[4][4];
|
||||
/// スキニングタイプ
|
||||
PmxVertexSkinningType skinning_type;
|
||||
/// スキニング
|
||||
std::unique_ptr<PmxVertexSkinning> skinning;
|
||||
/// エッジ倍率
|
||||
float edge;
|
||||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
||||
/// マテリアル
|
||||
class PmxMaterial
|
||||
{
|
||||
public:
|
||||
|
@ -261,42 +241,25 @@ namespace pmx
|
|||
}
|
||||
}
|
||||
|
||||
/// モデル名
|
||||
std::string material_name;
|
||||
/// モデル英名
|
||||
std::string material_english_name;
|
||||
/// 減衰色
|
||||
float diffuse[4];
|
||||
/// 光沢色
|
||||
float specular[3];
|
||||
/// 光沢度
|
||||
float specularlity;
|
||||
/// 環境色
|
||||
float ambient[3];
|
||||
/// 描画フラグ
|
||||
uint8_t flag;
|
||||
/// エッジ色
|
||||
float edge_color[4];
|
||||
/// エッジサイズ
|
||||
float edge_size;
|
||||
/// アルベドテクスチャインデックス
|
||||
int diffuse_texture_index;
|
||||
/// スフィアテクスチャインデックス
|
||||
int sphere_texture_index;
|
||||
/// スフィアテクスチャ演算モード
|
||||
uint8_t sphere_op_mode;
|
||||
/// 共有トゥーンフラグ
|
||||
uint8_t common_toon_flag;
|
||||
/// トゥーンテクスチャインデックス
|
||||
int toon_texture_index;
|
||||
/// メモ
|
||||
std::string memo;
|
||||
/// 頂点インデックス数
|
||||
int index_count;
|
||||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
||||
/// リンク
|
||||
class PmxIkLink
|
||||
{
|
||||
public:
|
||||
|
@ -310,18 +273,13 @@ namespace pmx
|
|||
}
|
||||
}
|
||||
|
||||
/// リンクボーンインデックス
|
||||
int link_target;
|
||||
/// 角度制限
|
||||
uint8_t angle_lock;
|
||||
/// 最大制限角度
|
||||
float max_radian[3];
|
||||
/// 最小制限角度
|
||||
float min_radian[3];
|
||||
void Read(std::istream *stream, PmxSetting *settingn);
|
||||
};
|
||||
|
||||
/// ボーン
|
||||
class PmxBone
|
||||
{
|
||||
public:
|
||||
|
@ -347,43 +305,24 @@ namespace pmx
|
|||
}
|
||||
}
|
||||
|
||||
/// ボーン名
|
||||
std::string bone_name;
|
||||
/// ボーン英名
|
||||
std::string bone_english_name;
|
||||
/// 位置
|
||||
float position[3];
|
||||
/// 親ボーンインデックス
|
||||
int parent_index;
|
||||
/// 階層
|
||||
int level;
|
||||
/// ボーンフラグ
|
||||
uint16_t bone_flag;
|
||||
/// 座標オフセット(has Target)
|
||||
float offset[3];
|
||||
/// 接続先ボーンインデックス(not has Target)
|
||||
int target_index;
|
||||
/// 付与親ボーンインデックス
|
||||
int grant_parent_index;
|
||||
/// 付与率
|
||||
float grant_weight;
|
||||
/// 固定軸の方向
|
||||
float lock_axis_orientation[3];
|
||||
/// ローカル軸のX軸方向
|
||||
float local_axis_x_orientation[3];
|
||||
/// ローカル軸のY軸方向
|
||||
float local_axis_y_orientation[3];
|
||||
/// 外部親変形のkey値
|
||||
int key;
|
||||
/// IKターゲットボーン
|
||||
int ik_target_bone_index;
|
||||
/// IKループ回数
|
||||
int ik_loop;
|
||||
/// IKループ計算時の角度制限(ラジアン)
|
||||
float ik_loop_angle_limit;
|
||||
/// IKリンク数
|
||||
int ik_link_count;
|
||||
/// IKリンク
|
||||
std::unique_ptr<PmxIkLink []> ik_links;
|
||||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
@ -543,7 +482,6 @@ namespace pmx
|
|||
void Read(std::istream *stream, PmxSetting *setting); //override;
|
||||
};
|
||||
|
||||
/// モーフ
|
||||
class PmxMorph
|
||||
{
|
||||
public:
|
||||
|
@ -551,34 +489,21 @@ namespace pmx
|
|||
: offset_count(0)
|
||||
{
|
||||
}
|
||||
/// モーフ名
|
||||
std::string morph_name;
|
||||
/// モーフ英名
|
||||
std::string morph_english_name;
|
||||
/// カテゴリ
|
||||
MorphCategory category;
|
||||
/// モーフタイプ
|
||||
MorphType morph_type;
|
||||
/// オフセット数
|
||||
int offset_count;
|
||||
/// 頂点モーフ配列
|
||||
std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets;
|
||||
/// UVモーフ配列
|
||||
std::unique_ptr<PmxMorphUVOffset []> uv_offsets;
|
||||
/// ボーンモーフ配列
|
||||
std::unique_ptr<PmxMorphBoneOffset []> bone_offsets;
|
||||
/// マテリアルモーフ配列
|
||||
std::unique_ptr<PmxMorphMaterialOffset []> material_offsets;
|
||||
/// グループモーフ配列
|
||||
std::unique_ptr<PmxMorphGroupOffset []> group_offsets;
|
||||
/// フリップモーフ配列
|
||||
std::unique_ptr<PmxMorphFlipOffset []> flip_offsets;
|
||||
/// インパルスモーフ配列
|
||||
std::unique_ptr<PmxMorphImplusOffset []> implus_offsets;
|
||||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
||||
/// 枠内要素
|
||||
class PmxFrameElement
|
||||
{
|
||||
public:
|
||||
|
@ -587,14 +512,11 @@ namespace pmx
|
|||
, index(0)
|
||||
{
|
||||
}
|
||||
/// 要素対象
|
||||
uint8_t element_target;
|
||||
/// 要素対象インデックス
|
||||
int index;
|
||||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
||||
/// 表示枠
|
||||
class PmxFrame
|
||||
{
|
||||
public:
|
||||
|
@ -603,15 +525,10 @@ namespace pmx
|
|||
, element_count(0)
|
||||
{
|
||||
}
|
||||
/// 枠名
|
||||
std::string frame_name;
|
||||
/// 枠英名
|
||||
std::string frame_english_name;
|
||||
/// 特殊枠フラグ
|
||||
uint8_t frame_flag;
|
||||
/// 枠内要素数
|
||||
int element_count;
|
||||
/// 枠内要素配列
|
||||
std::unique_ptr<PmxFrameElement []> elements;
|
||||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
@ -637,17 +554,11 @@ namespace pmx
|
|||
orientation[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
/// 剛体名
|
||||
std::string girid_body_name;
|
||||
/// 剛体英名
|
||||
std::string girid_body_english_name;
|
||||
/// 関連ボーンインデックス
|
||||
int target_bone;
|
||||
/// グループ
|
||||
uint8_t group;
|
||||
/// マスク
|
||||
uint16_t mask;
|
||||
/// 形状
|
||||
uint8_t shape;
|
||||
float size[3];
|
||||
float position[3];
|
||||
|
@ -818,7 +729,6 @@ namespace pmx
|
|||
void Read(std::istream *stream, PmxSetting *setting);
|
||||
};
|
||||
|
||||
/// PMXモデル
|
||||
class PmxModel
|
||||
{
|
||||
public:
|
||||
|
@ -836,65 +746,35 @@ namespace pmx
|
|||
, soft_body_count(0)
|
||||
{}
|
||||
|
||||
/// バージョン
|
||||
float version;
|
||||
/// 設定
|
||||
PmxSetting setting;
|
||||
/// モデル名
|
||||
std::string model_name;
|
||||
/// モデル英名
|
||||
std::string model_english_name;
|
||||
/// コメント
|
||||
std::string model_comment;
|
||||
/// 英語コメント
|
||||
std::string model_english_comment;
|
||||
/// 頂点数
|
||||
int vertex_count;
|
||||
/// 頂点配列
|
||||
std::unique_ptr<PmxVertex []> vertices;
|
||||
/// インデックス数
|
||||
int index_count;
|
||||
/// インデックス配列
|
||||
std::unique_ptr<int []> indices;
|
||||
/// テクスチャ数
|
||||
int texture_count;
|
||||
/// テクスチャ配列
|
||||
std::unique_ptr< std::string []> textures;
|
||||
/// マテリアル数
|
||||
int material_count;
|
||||
/// マテリアル
|
||||
std::unique_ptr<PmxMaterial []> materials;
|
||||
/// ボーン数
|
||||
int bone_count;
|
||||
/// ボーン配列
|
||||
std::unique_ptr<PmxBone []> bones;
|
||||
/// モーフ数
|
||||
int morph_count;
|
||||
/// モーフ配列
|
||||
std::unique_ptr<PmxMorph []> morphs;
|
||||
/// 表示枠数
|
||||
int frame_count;
|
||||
/// 表示枠配列
|
||||
std::unique_ptr<PmxFrame [] > frames;
|
||||
/// 剛体数
|
||||
int rigid_body_count;
|
||||
/// 剛体配列
|
||||
std::unique_ptr<PmxRigidBody []> rigid_bodies;
|
||||
/// ジョイント数
|
||||
int joint_count;
|
||||
/// ジョイント配列
|
||||
std::unique_ptr<PmxJoint []> joints;
|
||||
/// ソフトボディ数
|
||||
int soft_body_count;
|
||||
/// ソフトボディ配列
|
||||
std::unique_ptr<PmxSoftBody []> soft_bodies;
|
||||
/// モデル初期化
|
||||
void Init();
|
||||
/// モデル読み込み
|
||||
void Read(std::istream *stream);
|
||||
///// ファイルからモデルの読み込み
|
||||
//static std::unique_ptr<PmxModel> ReadFromFile(const char *filename);
|
||||
///// 入力ストリームからモデルの読み込み
|
||||
//static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -50,19 +50,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
namespace vmd
|
||||
{
|
||||
/// ボーンフレーム
|
||||
class VmdBoneFrame
|
||||
{
|
||||
public:
|
||||
/// ボーン名
|
||||
std::string name;
|
||||
/// フレーム番号
|
||||
int frame;
|
||||
/// 位置
|
||||
float position[3];
|
||||
/// 回転
|
||||
float orientation[4];
|
||||
/// 補間曲線
|
||||
char interpolation[4][4][4];
|
||||
|
||||
void Read(std::istream* stream)
|
||||
|
@ -86,15 +80,11 @@ namespace vmd
|
|||
}
|
||||
};
|
||||
|
||||
/// 表情フレーム
|
||||
class VmdFaceFrame
|
||||
{
|
||||
public:
|
||||
/// 表情名
|
||||
std::string face_name;
|
||||
/// 表情の重み
|
||||
float weight;
|
||||
/// フレーム番号
|
||||
uint32_t frame;
|
||||
|
||||
void Read(std::istream* stream)
|
||||
|
@ -114,23 +104,15 @@ namespace vmd
|
|||
}
|
||||
};
|
||||
|
||||
/// カメラフレーム
|
||||
class VmdCameraFrame
|
||||
{
|
||||
public:
|
||||
/// フレーム番号
|
||||
int frame;
|
||||
/// 距離
|
||||
float distance;
|
||||
/// 位置
|
||||
float position[3];
|
||||
/// 回転
|
||||
float orientation[3];
|
||||
/// 補間曲線
|
||||
char interpolation[6][4];
|
||||
/// 視野角
|
||||
float angle;
|
||||
/// 不明データ
|
||||
char unknown[3];
|
||||
|
||||
void Read(std::istream *stream)
|
||||
|
@ -156,15 +138,11 @@ namespace vmd
|
|||
}
|
||||
};
|
||||
|
||||
/// ライトフレーム
|
||||
class VmdLightFrame
|
||||
{
|
||||
public:
|
||||
/// フレーム番号
|
||||
int frame;
|
||||
/// 色
|
||||
float color[3];
|
||||
/// 位置
|
||||
float position[3];
|
||||
|
||||
void Read(std::istream* stream)
|
||||
|
@ -182,7 +160,6 @@ namespace vmd
|
|||
}
|
||||
};
|
||||
|
||||
/// IKの有効無効
|
||||
class VmdIkEnable
|
||||
{
|
||||
public:
|
||||
|
@ -190,7 +167,6 @@ namespace vmd
|
|||
bool enable;
|
||||
};
|
||||
|
||||
/// IKフレーム
|
||||
class VmdIkFrame
|
||||
{
|
||||
public:
|
||||
|
@ -229,23 +205,15 @@ namespace vmd
|
|||
}
|
||||
};
|
||||
|
||||
/// VMDモーション
|
||||
class VmdMotion
|
||||
{
|
||||
public:
|
||||
/// モデル名
|
||||
std::string model_name;
|
||||
/// バージョン
|
||||
int version;
|
||||
/// ボーンフレーム
|
||||
std::vector<VmdBoneFrame> bone_frames;
|
||||
/// 表情フレーム
|
||||
std::vector<VmdFaceFrame> face_frames;
|
||||
/// カメラフレーム
|
||||
std::vector<VmdCameraFrame> camera_frames;
|
||||
/// ライトフレーム
|
||||
std::vector<VmdLightFrame> light_frames;
|
||||
/// IKフレーム
|
||||
std::vector<VmdIkFrame> ik_frames;
|
||||
|
||||
static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)
|
||||
|
|
|
@ -94,7 +94,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
{
|
||||
if (!pIOHandler)return true;
|
||||
const char* tokens[] = {"off"};
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
|
||||
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ void ObjFileMtlImporter::createMaterial()
|
|||
m_pModel->m_pCurrentMaterial = new ObjFile::Material();
|
||||
m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
|
||||
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_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
|
||||
|
|
|
@ -618,7 +618,7 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pc
|
|||
}
|
||||
|
||||
streamBuffer.getNextBlock(buffer);
|
||||
unsigned int bufferSize = buffer.size();
|
||||
unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
|
||||
const char* pCur = (char*)&buffer[0];
|
||||
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.insert(buffer.end(), nbuffer.begin(), nbuffer.end());
|
||||
nbuffer.clear();
|
||||
bufferSize = buffer.size();
|
||||
bufferSize = static_cast<unsigned int>(buffer.size());
|
||||
pCur = (char*)&buffer[0];
|
||||
}
|
||||
else
|
||||
|
|
|
@ -160,6 +160,11 @@ void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsign
|
|||
unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
|
||||
ai_assert(0 != num_ref);
|
||||
--num_ref;
|
||||
// Save the name of the last mesh
|
||||
if (num_ref==0)
|
||||
{
|
||||
pcMeshOut->mName = pcMesh->mName;
|
||||
}
|
||||
|
||||
if (identity) {
|
||||
// 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
|
||||
// flat node graph with a root node and some level 1 children
|
||||
aiNode* newRoot = new aiNode();
|
||||
newRoot->mName = pScene->mRootNode->mName;
|
||||
delete pScene->mRootNode;
|
||||
pScene->mRootNode = new aiNode();
|
||||
pScene->mRootNode->mName.Set("<dummy_root>");
|
||||
|
||||
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
|
||||
{
|
||||
|
@ -646,7 +652,7 @@ void PretransformVertices::Execute( aiScene* pScene)
|
|||
{
|
||||
aiNode* pcNode = *nodes = new aiNode();
|
||||
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
|
||||
pcNode->mNumMeshes = 1;
|
||||
|
|
|
@ -201,7 +201,7 @@ static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars)
|
|||
//ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
|
||||
//*dest = '\0';
|
||||
|
||||
str[str.size()-1] = '\0';
|
||||
str[str.size()] = '\0';
|
||||
// Return the final string.
|
||||
aiString result = aiString((const char *)&str[0]);
|
||||
//delete[] str;
|
||||
|
@ -827,7 +827,7 @@ static void ReadInstance(SIB* sib, StreamReaderLE* stream)
|
|||
static void CheckVersion(StreamReaderLE* stream)
|
||||
{
|
||||
uint32_t version = stream->GetU4();
|
||||
if ( version != 1 ) {
|
||||
if ( version < 1 || version > 2 ) {
|
||||
throw DeadlyImportError( "SIB: Unsupported file version." );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -558,7 +558,7 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector
|
|||
|
||||
WordIterator wordItBegin(val, val + strlen(val));
|
||||
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)); });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* glTF Extensions Support:
|
||||
* KHR_binary_glTF: full
|
||||
* KHR_materials_common: full
|
||||
* KHR_materials_pbrSpecularGlossiness full
|
||||
*/
|
||||
#ifndef GLTF2ASSET_H_INC
|
||||
#define GLTF2ASSET_H_INC
|
||||
|
@ -130,16 +129,13 @@ namespace glTF2
|
|||
|
||||
struct BufferView; // here due to cross-reference
|
||||
struct Texture;
|
||||
struct Light;
|
||||
struct Skin;
|
||||
|
||||
|
||||
// Vec/matrix types, as raw float arrays
|
||||
typedef float (vec3)[3];
|
||||
typedef float (vec4)[4];
|
||||
typedef float (mat4)[16];
|
||||
|
||||
|
||||
namespace Util
|
||||
{
|
||||
void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
|
||||
|
@ -168,21 +164,34 @@ namespace glTF2
|
|||
//! Magic number for GLB files
|
||||
#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
|
||||
#include "./../include/assimp/Compiler/pushpack1.h"
|
||||
#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
|
||||
#include "./../include/assimp/Compiler/poppack1.h"
|
||||
#endif
|
||||
|
@ -232,7 +241,7 @@ namespace glTF2
|
|||
case ComponentType_UNSIGNED_BYTE:
|
||||
return 1;
|
||||
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
|
||||
enum SamplerMagFilter
|
||||
enum class SamplerMagFilter: unsigned int
|
||||
{
|
||||
UNSET = 0,
|
||||
SamplerMagFilter_Nearest = 9728,
|
||||
SamplerMagFilter_Linear = 9729
|
||||
};
|
||||
|
||||
//! Values for the Sampler::minFilter field
|
||||
enum SamplerMinFilter
|
||||
enum class SamplerMinFilter: unsigned int
|
||||
{
|
||||
UNSET = 0,
|
||||
SamplerMinFilter_Nearest = 9728,
|
||||
SamplerMinFilter_Linear = 9729,
|
||||
SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
|
||||
|
@ -262,11 +273,12 @@ namespace glTF2
|
|||
};
|
||||
|
||||
//! Values for the Sampler::wrapS and Sampler::wrapT field
|
||||
enum SamplerWrap
|
||||
enum class SamplerWrap: unsigned int
|
||||
{
|
||||
SamplerWrap_Clamp_To_Edge = 33071,
|
||||
SamplerWrap_Mirrored_Repeat = 33648,
|
||||
SamplerWrap_Repeat = 10497
|
||||
UNSET = 0,
|
||||
Clamp_To_Edge = 33071,
|
||||
Mirrored_Repeat = 33648,
|
||||
Repeat = 10497
|
||||
};
|
||||
|
||||
//! Values for the Texture::format and Texture::internalFormat fields
|
||||
|
@ -382,6 +394,7 @@ namespace glTF2
|
|||
struct Object
|
||||
{
|
||||
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 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 znear; //! The floating-point distance to the near clipping plane. (required)
|
||||
} ortographic;
|
||||
};
|
||||
} cameraProperties;
|
||||
|
||||
Camera() {}
|
||||
void Read(Value& obj, Asset& r);
|
||||
|
@ -670,41 +683,66 @@ namespace glTF2
|
|||
inline void SetData(uint8_t* data, size_t length, Asset& r);
|
||||
};
|
||||
|
||||
//! Holds a material property that can be a texture or a color
|
||||
struct TexProperty
|
||||
const vec4 defaultBaseColor = {1, 1, 1, 1};
|
||||
const vec3 defaultEmissiveFactor = {0, 0, 0};
|
||||
const vec4 defaultDiffuseFactor = {1, 1, 1, 1};
|
||||
const vec3 defaultSpecularFactor = {1, 1, 1};
|
||||
|
||||
struct TextureInfo
|
||||
{
|
||||
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.
|
||||
struct Material : public Object
|
||||
{
|
||||
//Ref<Sampler> source; //!< The ID of the technique.
|
||||
//std::gltf_unordered_map<std::string, std::string> values; //!< A dictionary object of parameter values.
|
||||
|
||||
//! 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;
|
||||
//PBR metallic roughness properties
|
||||
PbrMetallicRoughness pbrMetallicRoughness;
|
||||
|
||||
//other basic material properties
|
||||
NormalTextureInfo normalTexture;
|
||||
OcclusionTextureInfo occlusionTexture;
|
||||
TextureInfo emissiveTexture;
|
||||
vec3 emissiveFactor;
|
||||
std::string alphaMode;
|
||||
float alphaCutoff;
|
||||
bool doubleSided;
|
||||
bool transparent;
|
||||
float transparency;
|
||||
float shininess;
|
||||
|
||||
Technique technique;
|
||||
//extension: KHR_materials_pbrSpecularGlossiness
|
||||
Nullable<PbrSpecularGlossiness> pbrSpecularGlossiness;
|
||||
|
||||
Material() { SetDefaults(); }
|
||||
void Read(Value& obj, Asset& r);
|
||||
|
@ -729,92 +767,21 @@ namespace glTF2
|
|||
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::list<SExtension*> Extension;///< List of extensions used in 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)
|
||||
/// 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 [out] pAsset_Root - reference to root assed where data will be stored.
|
||||
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
|
||||
{
|
||||
std::vector< Ref<Node> > children;
|
||||
std::vector< Ref<Mesh> > meshes;
|
||||
Ref<Mesh> mesh;
|
||||
|
||||
Nullable<mat4> matrix;
|
||||
Nullable<vec3> translation;
|
||||
|
@ -822,7 +789,6 @@ namespace glTF2
|
|||
Nullable<vec3> scale;
|
||||
|
||||
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.
|
||||
Ref<Skin> skin; //!< The ID of the skin referenced by this node.
|
||||
|
@ -843,12 +809,12 @@ namespace glTF2
|
|||
|
||||
struct Sampler : public Object
|
||||
{
|
||||
SamplerMagFilter magFilter; //!< The texture magnification filter. (required)
|
||||
SamplerMinFilter minFilter; //!< The texture minification filter. (required)
|
||||
SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
|
||||
SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
|
||||
SamplerMagFilter magFilter; //!< The texture magnification filter.
|
||||
SamplerMinFilter minFilter; //!< The texture minification filter.
|
||||
SamplerWrap wrapS; //!< The texture wrapping in the S direction.
|
||||
SamplerWrap wrapT; //!< The texture wrapping in the T direction.
|
||||
|
||||
Sampler() {}
|
||||
Sampler() { SetDefaults(); }
|
||||
void Read(Value& obj, Asset& r);
|
||||
void SetDefaults();
|
||||
};
|
||||
|
@ -878,27 +844,6 @@ namespace glTF2
|
|||
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.
|
||||
struct Texture : public Object
|
||||
{
|
||||
|
@ -915,35 +860,6 @@ namespace glTF2
|
|||
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 AnimSampler {
|
||||
|
@ -1025,10 +941,12 @@ namespace glTF2
|
|||
friend class Asset;
|
||||
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
|
||||
Dict mObjsById; //! The read objects accessible by id
|
||||
Dict mObjsByOIndex; //! The read objects accessible by original index
|
||||
IdDict mObjsById; //! The read objects accessible by id
|
||||
const char* mDictId; //! ID of the dictionary object
|
||||
const char* mExtId; //! ID of the extension defining the dictionary
|
||||
Value* mDict; //! JSON dictionary object
|
||||
|
@ -1046,9 +964,10 @@ namespace glTF2
|
|||
LazyDict(Asset& asset, const char* dictId, const char* extId = 0);
|
||||
~LazyDict();
|
||||
|
||||
Ref<T> Get(const char* id);
|
||||
Ref<T> Retrieve(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 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 generator; //!< Tool that generated this glTF model.Useful for debugging.
|
||||
bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false)
|
||||
|
||||
struct {
|
||||
std::string api; //!< Specifies the target rendering API (default: "WebGL")
|
||||
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: {})
|
||||
|
||||
float version; //!< The glTF format version
|
||||
std::string version; //!< The glTF format version
|
||||
|
||||
void Read(Document& doc);
|
||||
|
||||
AssetMetadata()
|
||||
: premultipliedAlpha(false)
|
||||
, version(0)
|
||||
{
|
||||
}
|
||||
AssetMetadata() : version("") {}
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -1123,8 +1037,7 @@ namespace glTF2
|
|||
//! Keeps info about the enabled extensions
|
||||
struct Extensions
|
||||
{
|
||||
bool KHR_binary_glTF;
|
||||
bool KHR_materials_common;
|
||||
bool KHR_materials_pbrSpecularGlossiness;
|
||||
|
||||
} extensionsUsed;
|
||||
|
||||
|
@ -1142,16 +1055,11 @@ namespace glTF2
|
|||
LazyDict<Material> materials;
|
||||
LazyDict<Mesh> meshes;
|
||||
LazyDict<Node> nodes;
|
||||
//LazyDict<Program> programs;
|
||||
LazyDict<Sampler> samplers;
|
||||
LazyDict<Scene> scenes;
|
||||
//LazyDict<Shader> shaders;
|
||||
LazyDict<Skin> skins;
|
||||
//LazyDict<Technique> techniques;
|
||||
LazyDict<Texture> textures;
|
||||
|
||||
LazyDict<Light> lights; // KHR_materials_common ext
|
||||
|
||||
Ref<Scene> scene;
|
||||
|
||||
public:
|
||||
|
@ -1167,23 +1075,16 @@ namespace glTF2
|
|||
, materials (*this, "materials")
|
||||
, meshes (*this, "meshes")
|
||||
, nodes (*this, "nodes")
|
||||
//, programs (*this, "programs")
|
||||
, samplers (*this, "samplers")
|
||||
, scenes (*this, "scenes")
|
||||
//, shaders (*this, "shaders")
|
||||
, skins (*this, "skins")
|
||||
//, techniques (*this, "techniques")
|
||||
, textures (*this, "textures")
|
||||
, lights (*this, "lights", "KHR_materials_common")
|
||||
{
|
||||
memset(&extensionsUsed, 0, sizeof(extensionsUsed));
|
||||
}
|
||||
|
||||
//! Main function
|
||||
void Load(const std::string& file, bool isBinary = false);
|
||||
|
||||
//! Enables the "KHR_binary_glTF" extension on the asset
|
||||
void SetAsBinary();
|
||||
void Load(const std::string& file);
|
||||
|
||||
//! Search for an available name, starting from the given strings
|
||||
std::string FindUniqueID(const std::string& str, const char* suffix);
|
||||
|
@ -1192,11 +1093,8 @@ namespace glTF2
|
|||
{ return mBodyBuffer; }
|
||||
|
||||
private:
|
||||
void ReadBinaryHeader(IOStream& stream);
|
||||
|
||||
void ReadExtensionsUsed(Document& doc);
|
||||
|
||||
|
||||
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
@ -44,11 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// Header files, Assimp
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
||||
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
|
||||
// Header files, Open3DGC.
|
||||
# include <Open3DGC/o3dgcSC3DMCDecoder.h>
|
||||
#endif
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
namespace glTF2 {
|
||||
|
@ -128,6 +123,18 @@ namespace {
|
|||
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)
|
||||
{
|
||||
Value::MemberIterator it = val.FindMember(id);
|
||||
|
@ -176,7 +183,7 @@ inline void LazyDict<T>::AttachToDocument(Document& doc)
|
|||
}
|
||||
|
||||
if (container) {
|
||||
mDict = FindObject(*container, mDictId);
|
||||
mDict = FindArray(*container, mDictId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,18 +194,11 @@ inline void LazyDict<T>::DetachFromDocument()
|
|||
}
|
||||
|
||||
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>
|
||||
Ref<T> LazyDict<T>::Get(const char* id)
|
||||
{
|
||||
id = T::TranslateId(mAsset, id);
|
||||
|
||||
typename Dict::iterator it = mObjsById.find(id);
|
||||
if (it != mObjsById.end()) { // already created?
|
||||
typename Dict::iterator it = mObjsByOIndex.find(i);
|
||||
if (it != mObjsByOIndex.end()) {// already created?
|
||||
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) + "\"");
|
||||
}
|
||||
|
||||
Value::MemberIterator obj = mDict->FindMember(id);
|
||||
if (obj == mDict->MemberEnd()) {
|
||||
throw DeadlyImportError("GLTF: Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\"");
|
||||
}
|
||||
if (!obj->value.IsObject()) {
|
||||
throw DeadlyImportError("GLTF: Object with id \"" + std::string(id) + "\" is not a JSON object");
|
||||
if (!mDict->IsArray()) {
|
||||
throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\"");
|
||||
}
|
||||
|
||||
Value &obj = (*mDict)[i];
|
||||
|
||||
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();
|
||||
inst->id = id;
|
||||
ReadMember(obj->value, "name", inst->name);
|
||||
inst->Read(obj->value, mAsset);
|
||||
inst->id = std::string(mDictId) + "_" + std::to_string(i);
|
||||
inst->oIndex = i;
|
||||
ReadMember(obj, "name", inst->name);
|
||||
inst->Read(obj, mAsset);
|
||||
|
||||
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>
|
||||
Ref<T> LazyDict<T>::Add(T* obj)
|
||||
{
|
||||
unsigned int idx = unsigned(mObjs.size());
|
||||
mObjs.push_back(obj);
|
||||
mObjsByOIndex[obj->oIndex] = idx;
|
||||
mObjsById[obj->id] = idx;
|
||||
mAsset.mUsedIds[obj->id] = true;
|
||||
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");
|
||||
}
|
||||
T* inst = new T();
|
||||
unsigned int idx = unsigned(mObjs.size());
|
||||
inst->id = id;
|
||||
inst->index = mObjs.size();
|
||||
inst->index = idx;
|
||||
inst->oIndex = idx;
|
||||
return Add(inst);
|
||||
}
|
||||
|
||||
|
@ -263,11 +290,6 @@ inline Buffer::~Buffer()
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -310,7 +332,9 @@ inline void Buffer::Read(Value& obj, Asset& r)
|
|||
}
|
||||
else { // Local file
|
||||
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) {
|
||||
bool ok = LoadFromStream(*file, byteLength);
|
||||
delete file;
|
||||
|
@ -437,9 +461,9 @@ inline void Buffer::Grow(size_t amount)
|
|||
|
||||
inline void BufferView::Read(Value& obj, Asset& r)
|
||||
{
|
||||
const char* bufferId = MemberOrDefault<const char*>(obj, "buffer", 0);
|
||||
if (bufferId) {
|
||||
buffer = r.buffers.Get(bufferId);
|
||||
|
||||
if (Value* bufferVal = FindUInt(obj, "buffer")) {
|
||||
buffer = r.buffers.Retrieve(bufferVal->GetUint());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const char* bufferViewId = MemberOrDefault<const char*>(obj, "bufferView", 0);
|
||||
if (bufferViewId) {
|
||||
bufferView = r.bufferViews.Get(bufferViewId);
|
||||
|
||||
if (Value* bufferViewVal = FindUInt(obj, "bufferView")) {
|
||||
bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint());
|
||||
}
|
||||
|
||||
byteOffset = MemberOrDefault(obj, "byteOffset", 0u);
|
||||
|
@ -601,29 +625,6 @@ inline Image::Image()
|
|||
|
||||
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 (Value* uri = FindString(obj, "uri")) {
|
||||
const char* uristr = uri->GetString();
|
||||
|
@ -671,6 +672,7 @@ inline void Sampler::Read(Value& obj, Asset& r)
|
|||
{
|
||||
SetDefaults();
|
||||
|
||||
ReadMember(obj, "name", name);
|
||||
ReadMember(obj, "magFilter", magFilter);
|
||||
ReadMember(obj, "minFilter", minFilter);
|
||||
ReadMember(obj, "wrapS", wrapS);
|
||||
|
@ -679,34 +681,61 @@ inline void Sampler::Read(Value& obj, Asset& r)
|
|||
|
||||
inline void Sampler::SetDefaults()
|
||||
{
|
||||
magFilter = SamplerMagFilter_Linear;
|
||||
minFilter = SamplerMinFilter_Linear;
|
||||
wrapS = SamplerWrap_Repeat;
|
||||
wrapT = SamplerWrap_Repeat;
|
||||
//only wrapping modes have defaults
|
||||
wrapS = SamplerWrap::Repeat;
|
||||
wrapT = SamplerWrap::Repeat;
|
||||
magFilter = SamplerMagFilter::UNSET;
|
||||
minFilter = SamplerMinFilter::UNSET;
|
||||
}
|
||||
|
||||
inline void Texture::Read(Value& obj, Asset& r)
|
||||
{
|
||||
const char* sourcestr;
|
||||
if (ReadMember(obj, "source", sourcestr)) {
|
||||
source = r.images.Get(sourcestr);
|
||||
if (Value* sourceVal = FindUInt(obj, "source")) {
|
||||
source = r.images.Retrieve(sourceVal->GetUint());
|
||||
}
|
||||
|
||||
const char* samplerstr;
|
||||
if (ReadMember(obj, "sampler", samplerstr)) {
|
||||
sampler = r.samplers.Get(samplerstr);
|
||||
if (Value* samplerVal = FindUInt(obj, "sampler")) {
|
||||
sampler = r.samplers.Retrieve(samplerVal->GetUint());
|
||||
}
|
||||
}
|
||||
|
||||
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 (prop->IsString()) {
|
||||
out.texture = r.textures.Get(prop->GetString());
|
||||
SetTextureProperties(r, prop, out);
|
||||
}
|
||||
else {
|
||||
ReadValue(*prop, out.color);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (Value* values = FindObject(material, "values")) {
|
||||
ReadMaterialProperty(r, *values, "ambient", this->ambient);
|
||||
ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
|
||||
ReadMaterialProperty(r, *values, "specular", this->specular);
|
||||
|
||||
ReadMember(*values, "transparency", transparency);
|
||||
ReadMember(*values, "shininess", shininess);
|
||||
if (Value* pbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) {
|
||||
ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor);
|
||||
ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture);
|
||||
ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture);
|
||||
ReadMember(*pbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor);
|
||||
ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor);
|
||||
}
|
||||
|
||||
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 (r.extensionsUsed.KHR_materials_common) {
|
||||
if (Value* ext = FindObject(*extensions, "KHR_materials_common")) {
|
||||
if (Value* tnq = FindString(*ext, "technique")) {
|
||||
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 (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
|
||||
if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) {
|
||||
PbrSpecularGlossiness pbrSG;
|
||||
|
||||
if (Value* values = FindObject(*ext, "values")) {
|
||||
ReadMaterialProperty(r, *values, "ambient", this->ambient);
|
||||
ReadMaterialProperty(r, *values, "diffuse", this->diffuse);
|
||||
ReadMaterialProperty(r, *values, "specular", this->specular);
|
||||
ReadMember(*pbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor);
|
||||
ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture);
|
||||
ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture);
|
||||
ReadMember(*pbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor);
|
||||
ReadMember(*pbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor);
|
||||
|
||||
ReadMember(*values, "doubleSided", doubleSided);
|
||||
ReadMember(*values, "transparent", transparent);
|
||||
ReadMember(*values, "transparency", transparency);
|
||||
ReadMember(*values, "shininess", shininess);
|
||||
}
|
||||
this->pbrSpecularGlossiness = Nullable<PbrSpecularGlossiness>(pbrSG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void SetVector(vec4& v, float x, float y, float z, float w)
|
||||
{ v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
|
||||
void SetVector(vec4& v, const float(&in)[4])
|
||||
{ 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()
|
||||
{
|
||||
SetVector(ambient.color, 0, 0, 0, 1);
|
||||
SetVector(diffuse.color, 0, 0, 0, 1);
|
||||
SetVector(specular.color, 0, 0, 0, 1);
|
||||
SetVector(emission.color, 0, 0, 0, 1);
|
||||
//pbr materials
|
||||
SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor);
|
||||
pbrMetallicRoughness.metallicFactor = 1.0;
|
||||
pbrMetallicRoughness.roughnessFactor = 1.0;
|
||||
|
||||
SetVector(emissiveFactor, defaultEmissiveFactor);
|
||||
alphaMode = "OPAQUE";
|
||||
alphaCutoff = 0.5;
|
||||
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 {
|
||||
|
@ -808,6 +845,10 @@ namespace {
|
|||
|
||||
inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
|
||||
{
|
||||
if (Value* name = FindMember(pJSON_Object, "name")) {
|
||||
this->name = name->GetString();
|
||||
}
|
||||
|
||||
/****************** Mesh primitives ******************/
|
||||
if (Value* primitives = FindArray(pJSON_Object, "primitives")) {
|
||||
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")) {
|
||||
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();
|
||||
// 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.
|
||||
|
@ -829,262 +870,22 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root)
|
|||
if (GetAttribVector(prim, attr, vec, undPos)) {
|
||||
size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0;
|
||||
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")) {
|
||||
prim.indices = pAsset_Root.accessors.Get(indices->GetString());
|
||||
if (Value* indices = FindUInt(primitive, "indices")) {
|
||||
prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint());
|
||||
}
|
||||
|
||||
if (Value* material = FindString(primitive, "material")) {
|
||||
prim.material = pAsset_Root.materials.Get(material->GetString());
|
||||
if (Value* material = FindUInt(primitive, "material")) {
|
||||
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)
|
||||
{
|
||||
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 (type == Camera::Perspective) {
|
||||
perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
|
||||
perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f);
|
||||
perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
|
||||
perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
|
||||
cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f);
|
||||
cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f);
|
||||
cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f);
|
||||
cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f);
|
||||
}
|
||||
else {
|
||||
ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
|
||||
ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
|
||||
ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
|
||||
ortographic.znear = MemberOrDefault(obj, "znear", 0.01f);
|
||||
cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f);
|
||||
cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f);
|
||||
cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f);
|
||||
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)
|
||||
{
|
||||
|
||||
if (Value* children = FindArray(obj, "children")) {
|
||||
this->children.reserve(children->Size());
|
||||
for (unsigned int i = 0; i < children->Size(); ++i) {
|
||||
Value& child = (*children)[i];
|
||||
if (child.IsString()) {
|
||||
if (child.IsUint()) {
|
||||
// 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 (Value* matrix = FindArray(obj, "matrix")) {
|
||||
ReadValue(*matrix, this->matrix);
|
||||
}
|
||||
|
@ -1178,64 +933,46 @@ inline void Node::Read(Value& obj, Asset& r)
|
|||
ReadMember(obj, "rotation", rotation);
|
||||
}
|
||||
|
||||
if (Value* meshes = FindArray(obj, "meshes")) {
|
||||
unsigned numMeshes = (unsigned)meshes->Size();
|
||||
if (Value* mesh = FindUInt(obj, "mesh")) {
|
||||
Ref<Mesh> meshRef = r.meshes.Retrieve((*mesh).GetUint());
|
||||
|
||||
std::vector<unsigned int> meshList;
|
||||
|
||||
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 (meshRef) this->mesh = meshRef;
|
||||
}
|
||||
|
||||
if (Value* camera = FindString(obj, "camera")) {
|
||||
this->camera = r.cameras.Get(camera->GetString());
|
||||
if (Value* camera = FindUInt(obj, "camera")) {
|
||||
this->camera = r.cameras.Retrieve(camera->GetUint());
|
||||
if (this->camera)
|
||||
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)
|
||||
{
|
||||
if (Value* array = FindArray(obj, "nodes")) {
|
||||
for (unsigned int i = 0; i < array->Size(); ++i) {
|
||||
if (!(*array)[i].IsString()) continue;
|
||||
Ref<Node> node = r.nodes.Get((*array)[i].GetString());
|
||||
if (!(*array)[i].IsUint()) continue;
|
||||
Ref<Node> node = r.nodes.Retrieve((*array)[i].GetUint());
|
||||
if (node)
|
||||
this->nodes.push_back(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void AssetMetadata::Read(Document& doc)
|
||||
{
|
||||
// read the version, etc.
|
||||
float statedVersion = 0;
|
||||
if (Value* obj = FindObject(doc, "asset")) {
|
||||
ReadMember(*obj, "copyright", copyright);
|
||||
ReadMember(*obj, "generator", generator);
|
||||
|
||||
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")) {
|
||||
ReadMember(*profile, "api", this->profile.api);
|
||||
|
@ -1243,60 +980,16 @@ inline void AssetMetadata::Read(Document& doc)
|
|||
}
|
||||
}
|
||||
|
||||
version = std::max(statedVersion, 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);
|
||||
if (version.empty() || version[0] != '2') {
|
||||
throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Asset methods implementation
|
||||
//
|
||||
|
||||
inline void Asset::ReadBinaryHeader(IOStream& stream)
|
||||
{
|
||||
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)
|
||||
inline void Asset::Load(const std::string& pFile)
|
||||
{
|
||||
mCurrentAssetDir.clear();
|
||||
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");
|
||||
}
|
||||
|
||||
// is binary? then read the header
|
||||
if (isBinary) {
|
||||
SetAsBinary(); // also creates the body buffer
|
||||
ReadBinaryHeader(*stream);
|
||||
}
|
||||
else {
|
||||
mSceneLength = stream->FileSize();
|
||||
mBodyLength = 0;
|
||||
}
|
||||
|
||||
|
||||
// read the scene data
|
||||
|
||||
|
@ -1361,12 +1046,14 @@ inline void Asset::Load(const std::string& pFile, bool isBinary)
|
|||
mDicts[i]->AttachToDocument(doc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Read the "scene" property, which specifies which scene to load
|
||||
// and recursively load everything referenced by it
|
||||
if (Value* scene = FindString(doc, "scene")) {
|
||||
this->scene = scenes.Get(scene->GetString());
|
||||
if (Value* scene = FindUInt(doc, "scene")) {
|
||||
unsigned int sceneIndex = scene->GetUint();
|
||||
|
||||
Ref<Scene> s = scenes.Retrieve(sceneIndex);
|
||||
|
||||
this->scene = s;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
Value* extsUsed = FindArray(doc, "extensionsUsed");
|
||||
|
@ -1401,8 +1078,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc)
|
|||
#define CHECK_EXT(EXT) \
|
||||
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
|
||||
|
||||
CHECK_EXT(KHR_binary_glTF);
|
||||
CHECK_EXT(KHR_materials_common);
|
||||
CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
|
||||
|
||||
#undef CHECK_EXT
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
* Declares a class to write gltf/glb files
|
||||
*
|
||||
* glTF Extensions Support:
|
||||
* KHR_binary_glTF: full
|
||||
* KHR_materials_common: full
|
||||
* KHR_materials_pbrSpecularGlossiness: full
|
||||
*/
|
||||
#ifndef GLTF2ASSETWRITER_H_INC
|
||||
#define GLTF2ASSETWRITER_H_INC
|
||||
|
@ -82,7 +81,6 @@ public:
|
|||
AssetWriter(Asset& asset);
|
||||
|
||||
void WriteFile(const char* path);
|
||||
void WriteGLBFile(const char* path);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -72,6 +72,12 @@ namespace glTF2 {
|
|||
return val;
|
||||
}
|
||||
|
||||
inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& al) {
|
||||
val.SetDouble(r);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
|
||||
if (v.empty()) return;
|
||||
|
@ -91,7 +97,11 @@ namespace glTF2 {
|
|||
{
|
||||
obj.AddMember("bufferView", a.bufferView->index, w.mAl);
|
||||
obj.AddMember("byteOffset", a.byteOffset, w.mAl);
|
||||
|
||||
if (a.byteStride != 0) {
|
||||
obj.AddMember("byteStride", a.byteStride, w.mAl);
|
||||
}
|
||||
|
||||
obj.AddMember("componentType", int(a.componentType), w.mAl);
|
||||
obj.AddMember("count", a.count, 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)
|
||||
{
|
||||
std::string uri;
|
||||
if (w.mAsset.extensionsUsed.KHR_binary_glTF && img.bufferView) {
|
||||
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()) {
|
||||
if (img.HasData()) {
|
||||
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
|
||||
uri += ";base64,";
|
||||
Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
|
||||
|
@ -196,51 +192,149 @@ namespace glTF2 {
|
|||
}
|
||||
|
||||
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) {
|
||||
Value tex;
|
||||
tex.SetObject();
|
||||
tex.AddMember("index", texture->index, al);
|
||||
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;
|
||||
|
||||
SetTexBasic(t, 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) {
|
||||
Value col;
|
||||
obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al);
|
||||
|
||||
if (t.texture) {
|
||||
Value tex;
|
||||
|
||||
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)
|
||||
{
|
||||
if (m.transparent) {
|
||||
obj.AddMember("alphaMode", "BLEND", w.mAl);
|
||||
}
|
||||
|
||||
Value v;
|
||||
v.SetObject();
|
||||
Value pbrMetallicRoughness;
|
||||
pbrMetallicRoughness.SetObject();
|
||||
{
|
||||
if (m.transparent && !m.diffuse.texture) {
|
||||
m.diffuse.color[3] = m.transparency;
|
||||
}
|
||||
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(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl);
|
||||
WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
|
||||
WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, 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 {
|
||||
|
@ -263,59 +357,6 @@ namespace glTF2 {
|
|||
|
||||
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 *******************/
|
||||
Value primitives;
|
||||
primitives.SetArray();
|
||||
|
@ -340,10 +381,9 @@ namespace glTF2 {
|
|||
WriteAttrs(w, attrs, p.attributes.position, "POSITION");
|
||||
WriteAttrs(w, attrs, p.attributes.normal, "NORMAL");
|
||||
WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true);
|
||||
WriteAttrs(w, attrs, p.attributes.color, "COLOR");
|
||||
WriteAttrs(w, attrs, p.attributes.joint, "JOINT");
|
||||
WriteAttrs(w, attrs, p.attributes.jointmatrix, "JOINTMATRIX");
|
||||
WriteAttrs(w, attrs, p.attributes.weight, "WEIGHT");
|
||||
WriteAttrs(w, attrs, p.attributes.color, "COLOR", true);
|
||||
WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true);
|
||||
WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true);
|
||||
}
|
||||
prim.AddMember("attributes", attrs, w.mAl);
|
||||
}
|
||||
|
@ -377,7 +417,9 @@ namespace glTF2 {
|
|||
|
||||
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);
|
||||
|
||||
|
@ -397,17 +439,24 @@ namespace glTF2 {
|
|||
|
||||
inline void Write(Value& obj, Sampler& b, AssetWriter& w)
|
||||
{
|
||||
if (b.wrapS) {
|
||||
obj.AddMember("wrapS", b.wrapS, w.mAl);
|
||||
if (!b.name.empty()) {
|
||||
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)
|
||||
{
|
||||
if (tex.source) {
|
||||
|
@ -459,11 +503,6 @@ namespace glTF2 {
|
|||
}
|
||||
}
|
||||
|
||||
inline void Write(Value& obj, Light& b, AssetWriter& w)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline AssetWriter::AssetWriter(Asset& a)
|
||||
: 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()
|
||||
{
|
||||
Value asset;
|
||||
asset.SetObject();
|
||||
{
|
||||
char versionChar[10];
|
||||
ai_snprintf(versionChar, sizeof(versionChar), "%.1f", mAsset.asset.version);
|
||||
asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
|
||||
|
||||
asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
|
||||
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
|
||||
}
|
||||
mDoc.AddMember("asset", asset, mAl);
|
||||
}
|
||||
|
||||
|
@ -613,11 +576,10 @@ namespace glTF2 {
|
|||
Value exts;
|
||||
exts.SetArray();
|
||||
{
|
||||
if (false)
|
||||
exts.PushBack(StringRef("KHR_binary_glTF"), mAl);
|
||||
|
||||
// This is used to export common materials with GLTF 2.
|
||||
exts.PushBack(StringRef("KHR_materials_common"), mAl);
|
||||
// This is used to export pbrSpecularGlossiness materials with GLTF 2.
|
||||
if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
|
||||
exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl);
|
||||
}
|
||||
}
|
||||
|
||||
if (!exts.Empty())
|
||||
|
|
|
@ -62,11 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "glTF2AssetWriter.h"
|
||||
|
||||
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
|
||||
// Header files, Open3DGC.
|
||||
# include <Open3DGC/o3dgcSC3DMCEncoder.h>
|
||||
#endif
|
||||
|
||||
using namespace rapidjson;
|
||||
|
||||
using namespace Assimp;
|
||||
|
@ -106,16 +101,8 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
|
|||
|
||||
mAsset.reset( new Asset( pIOSystem ) );
|
||||
|
||||
if (isBinary) {
|
||||
mAsset->SetAsBinary();
|
||||
}
|
||||
|
||||
ExportMetadata();
|
||||
|
||||
//for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {}
|
||||
|
||||
//for (unsigned int i = 0; i < pScene->mNumLights; ++i) {}
|
||||
|
||||
ExportMaterials();
|
||||
|
||||
if (mScene->mRootNode) {
|
||||
|
@ -124,20 +111,14 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
|
|||
|
||||
ExportMeshes();
|
||||
|
||||
//for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {}
|
||||
|
||||
ExportScene();
|
||||
|
||||
ExportAnimations();
|
||||
|
||||
AssetWriter writer(*mAsset);
|
||||
|
||||
if (isBinary) {
|
||||
writer.WriteGLBFile(filename);
|
||||
} else {
|
||||
writer.WriteFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a 4x4 matrix from struct aiMatrix to typedef mat4.
|
||||
|
@ -234,63 +215,86 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
|
|||
return acc;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
|
||||
if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {}
|
||||
}
|
||||
inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map)
|
||||
{
|
||||
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)
|
||||
void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture, aiTextureType tt, unsigned int slot)
|
||||
{
|
||||
std::string samplerId = mAsset->FindUniqueID("", "sampler");
|
||||
texture->sampler = mAsset->samplers.Create(samplerId);
|
||||
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;
|
||||
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
|
||||
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
|
||||
SamplerMagFilter filterMag;
|
||||
SamplerMinFilter filterMin;
|
||||
|
||||
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;
|
||||
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
|
||||
SetSamplerWrap(texture->sampler->wrapS, mapU);
|
||||
}
|
||||
|
||||
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt)
|
||||
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::GetMatTexProp(const aiMaterial* mat, unsigned int& 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::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
|
||||
{
|
||||
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->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();
|
||||
|
||||
if (path.size() > 0) {
|
||||
|
@ -325,22 +329,63 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
|
|||
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;
|
||||
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()
|
||||
{
|
||||
|
@ -348,6 +393,9 @@ void glTF2Exporter::ExportMaterials()
|
|||
for (unsigned int i = 0; i < mScene->mNumMaterials; ++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;
|
||||
if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) {
|
||||
|
@ -355,17 +403,70 @@ void glTF2Exporter::ExportMaterials()
|
|||
}
|
||||
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);
|
||||
GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE);
|
||||
GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR);
|
||||
GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE);
|
||||
GetMatTex(mat, m->normal, aiTextureType_NORMALS);
|
||||
GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE);
|
||||
GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
|
||||
GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE);
|
||||
|
||||
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,12 +476,11 @@ void glTF2Exporter::ExportMaterials()
|
|||
*/
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < nodeIn->children.size(); ++i) {
|
||||
if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) {
|
||||
|
@ -502,15 +602,6 @@ void glTF2Exporter::ExportMeshes()
|
|||
// because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification.
|
||||
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 bufferIdPrefix = fname.substr(0, fname.rfind(".gltf"));
|
||||
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) {
|
||||
const aiMesh* aim = mScene->mMeshes[idx_mesh];
|
||||
|
||||
// Check if compressing requested and mesh can be encoded.
|
||||
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
|
||||
comp_allow = mProperties->GetPropertyBool("extensions.Open3DGC.use", false);
|
||||
#else
|
||||
comp_allow = false;
|
||||
#endif
|
||||
std::string name = aim->mName.C_Str();
|
||||
|
||||
if(comp_allow && (aim->mPrimitiveTypes == aiPrimitiveType_TRIANGLE) && (aim->mNumVertices > 0) && (aim->mNumFaces > 0))
|
||||
{
|
||||
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");
|
||||
std::string meshId = mAsset->FindUniqueID(name, "mesh");
|
||||
Ref<Mesh> m = mAsset->meshes.Create(meshId);
|
||||
m->primitives.resize(1);
|
||||
Mesh::Primitive& p = m->primitives.back();
|
||||
|
||||
m->name = name;
|
||||
|
||||
p.material = mAsset->materials.Get(aim->mMaterialIndex);
|
||||
|
||||
/******************* 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);
|
||||
if (v) p.attributes.position.push_back(v);
|
||||
|
||||
/******************** 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);
|
||||
if (n) p.attributes.normal.push_back(n);
|
||||
|
||||
|
@ -600,16 +665,12 @@ void glTF2Exporter::ExportMeshes()
|
|||
if (aim->mNumUVComponents[i] > 0) {
|
||||
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);
|
||||
if (tc) p.attributes.texcoord.push_back(tc);
|
||||
}
|
||||
}
|
||||
|
||||
/*************** Vertices indices ****************/
|
||||
idx_srcdata_ind = b->byteLength;// Store index of indices array.
|
||||
|
||||
if (aim->mNumFaces > 0) {
|
||||
std::vector<IndicesType> indices;
|
||||
unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices;
|
||||
|
@ -638,100 +699,8 @@ void glTF2Exporter::ExportMeshes()
|
|||
if(aim->HasBones()) {
|
||||
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
|
||||
// Create the Accessor for skinRef->inverseBindMatrices
|
||||
|
@ -786,8 +755,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n)
|
|||
CopyValue(n->mTransformation, node->matrix.value);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
|
||||
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
|
||||
if (n->mNumMeshes > 0) {
|
||||
node->mesh = mAsset->meshes.Get(n->mMeshes[0]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
|
||||
node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i]));
|
||||
if (n->mNumMeshes > 0) {
|
||||
node->mesh = mAsset->meshes.Get(n->mMeshes[0]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < n->mNumChildren; ++i) {
|
||||
|
@ -845,7 +814,7 @@ void glTF2Exporter::ExportScene()
|
|||
void glTF2Exporter::ExportMetadata()
|
||||
{
|
||||
AssetMetadata& asset = mAsset->asset;
|
||||
asset.version = 2;
|
||||
asset.version = "2.0";
|
||||
|
||||
char buffer[256];
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -899,7 +868,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
|
|||
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 ) {
|
||||
animRef->Parameters.translation = tranAccessor;
|
||||
}
|
||||
|
@ -915,7 +884,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
|
|||
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 ) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
animRef->Parameters.rotation = rotAccessor;
|
||||
}
|
||||
|
@ -963,7 +932,7 @@ void glTF2Exporter::ExportAnimations()
|
|||
name = mAsset->FindUniqueID(name, "animation");
|
||||
Ref<Animation> animRef = mAsset->animations.Create(name);
|
||||
|
||||
/******************* Parameters ********************/
|
||||
// Parameters
|
||||
ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, anim->mTicksPerSecond);
|
||||
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
|
@ -989,7 +958,7 @@ void glTF2Exporter::ExportAnimations()
|
|||
Animation::AnimChannel tmpAnimChannel;
|
||||
Animation::AnimSampler tmpAnimSampler;
|
||||
|
||||
tmpAnimChannel.sampler = animRef->Samplers.size();
|
||||
tmpAnimChannel.sampler = static_cast<int>(animRef->Samplers.size());
|
||||
tmpAnimChannel.target.path = channelType;
|
||||
tmpAnimSampler.output = channelType;
|
||||
tmpAnimSampler.id = name + "_" + channelType;
|
||||
|
|
|
@ -66,8 +66,15 @@ namespace glTF2
|
|||
|
||||
class Asset;
|
||||
struct TexProperty;
|
||||
struct TextureInfo;
|
||||
struct NormalTextureInfo;
|
||||
struct OcclusionTextureInfo;
|
||||
struct Node;
|
||||
struct Texture;
|
||||
|
||||
// Vec/matrix types, as raw float arrays
|
||||
typedef float (vec3)[3];
|
||||
typedef float (vec4)[4];
|
||||
}
|
||||
|
||||
namespace Assimp
|
||||
|
@ -101,9 +108,15 @@ namespace Assimp
|
|||
|
||||
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
|
||||
|
||||
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture);
|
||||
void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt);
|
||||
void GetMatColorOrTex(const aiMaterial* mat, glTF2::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
|
||||
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
|
||||
void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
|
||||
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 ExportMaterials();
|
||||
void ExportMeshes();
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1058,13 +1058,13 @@ namespace glTF
|
|||
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: {})
|
||||
|
||||
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);
|
||||
|
||||
AssetMetadata()
|
||||
: premultipliedAlpha(false)
|
||||
, version(0)
|
||||
, version("")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "StringUtils.h"
|
||||
#include <iomanip>
|
||||
|
||||
// Header files, Assimp
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
|
@ -128,6 +129,12 @@ namespace {
|
|||
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)
|
||||
{
|
||||
Value::MemberIterator it = val.FindMember(id);
|
||||
|
@ -309,7 +316,9 @@ inline void Buffer::Read(Value& obj, Asset& r)
|
|||
}
|
||||
else { // Local file
|
||||
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) {
|
||||
bool ok = LoadFromStream(*file, byteLength);
|
||||
delete file;
|
||||
|
@ -1228,13 +1237,21 @@ inline void Scene::Read(Value& obj, Asset& r)
|
|||
inline void AssetMetadata::Read(Document& doc)
|
||||
{
|
||||
// read the version, etc.
|
||||
float statedVersion = 0;
|
||||
if (Value* obj = FindObject(doc, "asset")) {
|
||||
ReadMember(*obj, "copyright", copyright);
|
||||
ReadMember(*obj, "generator", generator);
|
||||
|
||||
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")) {
|
||||
ReadMember(*profile, "api", this->profile.api);
|
||||
|
@ -1242,16 +1259,8 @@ inline void AssetMetadata::Read(Document& doc)
|
|||
}
|
||||
}
|
||||
|
||||
version = std::max(statedVersion, version);
|
||||
if (version == 0) {
|
||||
// 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);
|
||||
if (version.empty() || version[0] != '1') {
|
||||
throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream)
|
|||
}
|
||||
|
||||
AI_SWAP4(header.version);
|
||||
asset.version = header.version;
|
||||
asset.version = std::to_string(header.version);
|
||||
if (header.version != 1) {
|
||||
throw DeadlyImportError("GLTF: Unsupported binary glTF version");
|
||||
}
|
||||
|
|
|
@ -606,13 +606,8 @@ namespace glTF {
|
|||
{
|
||||
Value asset;
|
||||
asset.SetObject();
|
||||
{
|
||||
char versionChar[10];
|
||||
ai_snprintf(versionChar, sizeof(versionChar), "%.0f", mAsset.asset.version);
|
||||
asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
|
||||
|
||||
asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
|
||||
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
|
||||
}
|
||||
mDoc.AddMember("asset", asset, mAl);
|
||||
}
|
||||
|
||||
|
|
|
@ -507,7 +507,7 @@ void glTFExporter::ExportMeshes()
|
|||
|
||||
// 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_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.
|
||||
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.
|
||||
|
@ -875,7 +875,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -888,7 +888,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
|
|||
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 ) {
|
||||
animRef->Parameters.translation = tranAccessor;
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
|
|||
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 ) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
animRef->Parameters.rotation = rotAccessor;
|
||||
}
|
||||
|
|
|
@ -102,22 +102,17 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
{
|
||||
const std::string &extension = GetExtension(pFile);
|
||||
|
||||
if (extension == "gltf" || extension == "glb")
|
||||
return true;
|
||||
if (extension != "gltf" && extension != "glb")
|
||||
return false;
|
||||
|
||||
if ((checkSig || !extension.length()) && pIOHandler) {
|
||||
char buffer[4];
|
||||
|
||||
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile));
|
||||
if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) {
|
||||
if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) {
|
||||
return true; // Has GLB header
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (checkSig && pIOHandler) {
|
||||
glTF::Asset asset(pIOHandler);
|
||||
try {
|
||||
asset.Load(pFile, extension == "glb");
|
||||
std::string version = asset.asset.version;
|
||||
return !version.empty() && version[0] == '1';
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ set( IrrXML_SRCS
|
|||
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})
|
||||
set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" )
|
||||
set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" )
|
||||
|
|
|
@ -88,6 +88,7 @@ SET( TEST_SRCS
|
|||
unit/utFixInfacingNormals.cpp
|
||||
unit/utGenNormals.cpp
|
||||
unit/utglTFImportExport.cpp
|
||||
unit/utglTF2ImportExport.cpp
|
||||
unit/utHMPImportExport.cpp
|
||||
unit/utIFCImportExport.cpp
|
||||
unit/utImporter.cpp
|
||||
|
|
Binary file not shown.
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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.
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -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"
|
||||
]
|
||||
}
|
Binary file not shown.
|
@ -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;
|
||||
}
|
|
@ -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 |
|
@ -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.
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
|
@ -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
|
|
@ -55,6 +55,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
TEST_F( utglTFImportExport, importglTFromFileTest ) {
|
||||
TEST_F( utglTFImportExport, importglTFFromFileTest ) {
|
||||
EXPECT_TRUE( importerTest() );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue