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

View File

@ -1,6 +1,8 @@
sudo: required
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
matrix:
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

View File

@ -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)

View File

@ -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.

View File

@ -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;
}

View File

@ -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);

View File

@ -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
)

View File

@ -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)
{

View File

@ -119,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
* might be NULL and it's our duty to return true here.
*/
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];

View File

@ -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,18 +153,16 @@ 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
{
if(curves.empty()) {
if ( curves.empty() ) {
// resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
@ -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

View File

@ -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

View File

@ -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

View File

@ -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,17 +570,17 @@ 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];
const size_t c = count;
for (size_t i = 0; i < c; ++i) {
lenghts[i] = strlen(classnames[i]);
lenghts[ i ] = strlen(classnames[i]);
}
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

View File

@ -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();

View File

@ -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
{

View File

@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
namespace FBX {
using namespace Util;
using namespace Util;
// ------------------------------------------------------------------------------------------------
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
@ -75,7 +75,7 @@ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document
// ------------------------------------------------------------------------------------------------
NodeAttribute::~NodeAttribute()
{
// 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
}

View File

@ -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)";

View File

@ -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);

View File

@ -128,7 +128,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
}
meshout.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

View File

@ -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() );

View File

@ -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>));
}

View File

@ -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>();

View File

@ -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));

View File

@ -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);
};
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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." );
}
}

View File

@ -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)); });
}
}

View File

@ -43,8 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Declares a glTF class to handle gltf/glb files
*
* 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);
};

View File

@ -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
}

View File

@ -43,8 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Declares a class to write gltf/glb files
*
* 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);
};
}

View File

@ -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())

View File

@ -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,19 +111,13 @@ 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);
}
}
/*
@ -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, aiTextureType tt, unsigned int slot)
{
aiString aId;
std::string id;
if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) {
id = aId.C_Str();
}
if (Ref<Sampler> ref = mAsset->samplers.Get(id.c_str())) {
texture->sampler = ref;
} else {
id = mAsset->FindUniqueID(id, "sampler");
texture->sampler = mAsset->samplers.Create(id.c_str());
aiTextureMapMode mapU, mapV;
SamplerMagFilter filterMag;
SamplerMinFilter filterMin;
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) {
SetSamplerWrap(texture->sampler->wrapS, mapU);
}
if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) {
SetSamplerWrap(texture->sampler->wrapT, mapV);
}
if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) {
texture->sampler->magFilter = filterMag;
}
if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) {
texture->sampler->minFilter = filterMin;
}
aiString name;
if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) {
texture->sampler->name = name.C_Str();
}
}
}
void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref<Texture> texture)
void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot)
{
std::string samplerId = mAsset->FindUniqueID("", "sampler");
texture->sampler = mAsset->samplers.Create(samplerId);
std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
aiTextureMapMode mapU, mapV;
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU);
aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV);
switch (mapU) {
case aiTextureMapMode_Wrap:
texture->sampler->wrapS = SamplerWrap_Repeat;
break;
case aiTextureMapMode_Clamp:
texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat;
break;
case aiTextureMapMode_Decal:
default:
texture->sampler->wrapS = SamplerWrap_Repeat;
break;
};
switch (mapV) {
case aiTextureMapMode_Wrap:
texture->sampler->wrapT = SamplerWrap_Repeat;
break;
case aiTextureMapMode_Clamp:
texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge;
break;
case aiTextureMapMode_Mirror:
texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat;
break;
case aiTextureMapMode_Decal:
default:
texture->sampler->wrapT = SamplerWrap_Repeat;
break;
};
// Hard coded Texture filtering options because I do not know where to find them in the aiMaterial.
texture->sampler->magFilter = SamplerMagFilter_Linear;
texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear;
mat->Get(textureKey.c_str(), tt, slot, prop);
}
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt)
void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot)
{
aiString tex;
std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName;
mat->Get(textureKey.c_str(), tt, slot, prop);
}
void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTextureType tt, unsigned int slot = 0)
{
if (mat->GetTextureCount(tt) > 0) {
if (mat->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;

View File

@ -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();

View File

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

View File

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

View File

@ -1058,13 +1058,13 @@ namespace glTF
std::string version; //!< Specifies the target rendering API (default: "1.0.3")
} 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("")
{
}
};

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -100,24 +100,19 @@ const aiImporterDesc* glTFImporter::GetInfo() const
bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string& extension = GetExtension(pFile);
const std::string &extension = GetExtension(pFile);
if (extension == "gltf" || extension == "glb")
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;
}
}

View File

@ -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" )

View File

@ -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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

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

View File

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