diff --git a/CMakeLists.txt b/CMakeLists.txt index 15ceb2177..fc1366a1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,6 +269,8 @@ ELSEIF(MSVC) ADD_COMPILE_OPTIONS(/wd4351) ENDIF() SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF") ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) IF(NOT ASSIMP_HUNTER_ENABLED) SET(CMAKE_CXX_STANDARD 11) diff --git a/code/AssetLib/3DS/3DSHelper.h b/code/AssetLib/3DS/3DSHelper.h index 1930c0c40..e8efbf949 100644 --- a/code/AssetLib/3DS/3DSHelper.h +++ b/code/AssetLib/3DS/3DSHelper.h @@ -348,16 +348,16 @@ struct Texture { // empty } - Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)), + Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend), mMapName(std::move(other.mMapName)), - mOffsetU(std::move(other.mOffsetU)), - mOffsetV(std::move(other.mOffsetV)), - mScaleU(std::move(other.mScaleU)), - mScaleV(std::move(other.mScaleV)), - mRotation(std::move(other.mRotation)), - mMapMode(std::move(other.mMapMode)), - bPrivate(std::move(other.bPrivate)), - iUVSrc(std::move(other.iUVSrc)) { + mOffsetU(other.mOffsetU), + mOffsetV(other.mOffsetV), + mScaleU(other.mScaleU), + mScaleV(other.mScaleV), + mRotation(other.mRotation), + mMapMode(other.mMapMode), + bPrivate(other.bPrivate), + iUVSrc(other.iUVSrc) { // empty } @@ -366,16 +366,16 @@ struct Texture { return *this; } - mTextureBlend = std::move(other.mTextureBlend); + mTextureBlend = other.mTextureBlend; mMapName = std::move(other.mMapName); - mOffsetU = std::move(other.mOffsetU); - mOffsetV = std::move(other.mOffsetV); - mScaleU = std::move(other.mScaleU); - mScaleV = std::move(other.mScaleV); - mRotation = std::move(other.mRotation); - mMapMode = std::move(other.mMapMode); - bPrivate = std::move(other.bPrivate); - iUVSrc = std::move(other.iUVSrc); + mOffsetU = other.mOffsetU; + mOffsetV = other.mOffsetV; + mScaleU = other.mScaleU; + mScaleV = other.mScaleV; + mRotation = other.mRotation; + mMapMode = other.mMapMode; + bPrivate = other.bPrivate; + iUVSrc = other.iUVSrc; return *this; } @@ -461,13 +461,13 @@ struct Material { //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), - mDiffuse(std::move(other.mDiffuse)), - mSpecularExponent(std::move(other.mSpecularExponent)), - mShininessStrength(std::move(other.mShininessStrength)), - mSpecular(std::move(other.mSpecular)), - mAmbient(std::move(other.mAmbient)), - mShading(std::move(other.mShading)), - mTransparency(std::move(other.mTransparency)), + mDiffuse(other.mDiffuse), + mSpecularExponent(other.mSpecularExponent), + mShininessStrength(other.mShininessStrength), + mSpecular(other.mSpecular), + mAmbient(other.mAmbient), + mShading(other.mShading), + mTransparency(other.mTransparency), sTexDiffuse(std::move(other.sTexDiffuse)), sTexOpacity(std::move(other.sTexOpacity)), sTexSpecular(std::move(other.sTexSpecular)), @@ -475,10 +475,10 @@ struct Material { sTexBump(std::move(other.sTexBump)), sTexEmissive(std::move(other.sTexEmissive)), sTexShininess(std::move(other.sTexShininess)), - mBumpHeight(std::move(other.mBumpHeight)), - mEmissive(std::move(other.mEmissive)), + mBumpHeight(other.mBumpHeight), + mEmissive(other.mEmissive), sTexAmbient(std::move(other.sTexAmbient)), - mTwoSided(std::move(other.mTwoSided)) { + mTwoSided(other.mTwoSided) { // empty } @@ -488,13 +488,13 @@ struct Material { } mName = std::move(other.mName); - mDiffuse = std::move(other.mDiffuse); - mSpecularExponent = std::move(other.mSpecularExponent); - mShininessStrength = std::move(other.mShininessStrength), - mSpecular = std::move(other.mSpecular); - mAmbient = std::move(other.mAmbient); - mShading = std::move(other.mShading); - mTransparency = std::move(other.mTransparency); + mDiffuse = other.mDiffuse; + mSpecularExponent = other.mSpecularExponent; + mShininessStrength = other.mShininessStrength, + mSpecular = other.mSpecular; + mAmbient = other.mAmbient; + mShading = other.mShading; + mTransparency = other.mTransparency; sTexDiffuse = std::move(other.sTexDiffuse); sTexOpacity = std::move(other.sTexOpacity); sTexSpecular = std::move(other.sTexSpecular); @@ -502,10 +502,10 @@ struct Material { sTexBump = std::move(other.sTexBump); sTexEmissive = std::move(other.sTexEmissive); sTexShininess = std::move(other.sTexShininess); - mBumpHeight = std::move(other.mBumpHeight); - mEmissive = std::move(other.mEmissive); + mBumpHeight = other.mBumpHeight; + mEmissive = other.mEmissive; sTexAmbient = std::move(other.sTexAmbient); - mTwoSided = std::move(other.mTwoSided); + mTwoSided = other.mTwoSided; return *this; } diff --git a/code/AssetLib/ASE/ASEParser.h b/code/AssetLib/ASE/ASEParser.h index d04fc0662..f49cfc36f 100644 --- a/code/AssetLib/ASE/ASEParser.h +++ b/code/AssetLib/ASE/ASEParser.h @@ -95,8 +95,8 @@ struct Material : public D3DS::Material { Material(Material &&other) AI_NO_EXCEPT : D3DS::Material(std::move(other)), avSubMaterials(std::move(other.avSubMaterials)), - pcInstance(std::move(other.pcInstance)), - bNeed(std::move(other.bNeed)) { + pcInstance(other.pcInstance), + bNeed(other.bNeed) { other.pcInstance = nullptr; } @@ -108,8 +108,8 @@ struct Material : public D3DS::Material { //D3DS::Material::operator=(std::move(other)); avSubMaterials = std::move(other.avSubMaterials); - pcInstance = std::move(other.pcInstance); - bNeed = std::move(other.bNeed); + pcInstance = other.pcInstance; + bNeed = other.bNeed; other.pcInstance = nullptr; diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index 3d9a5075a..11f7bcd14 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -143,7 +143,7 @@ AI_WONT_RETURN void B3DImporter::Oops() { } // ------------------------------------------------------------------------------------------------ -AI_WONT_RETURN void B3DImporter::Fail(string str) { +AI_WONT_RETURN void B3DImporter::Fail(const string &str) { #ifdef DEBUG_B3D ASSIMP_LOG_ERROR("Error in B3D file data: ", str); #endif diff --git a/code/AssetLib/B3D/B3DImporter.h b/code/AssetLib/B3D/B3DImporter.h index e2a75abdf..a7ed65c3b 100644 --- a/code/AssetLib/B3D/B3DImporter.h +++ b/code/AssetLib/B3D/B3DImporter.h @@ -96,7 +96,7 @@ private: }; AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX; - AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX; + AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX; void ReadTEXS(); void ReadBRUS(); diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 7cf4e070e..42a7a1723 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -679,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) { BuildDefaultMaterial(conv_data); - for (std::shared_ptr mat : conv_data.materials_raw) { + for (const std::shared_ptr &mat : conv_data.materials_raw) { // reset per material global counters for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) { diff --git a/code/AssetLib/COB/COBLoader.cpp b/code/AssetLib/COB/COBLoader.cpp index 94327c683..822bce16d 100644 --- a/code/AssetLib/COB/COBLoader.cpp +++ b/code/AssetLib/COB/COBLoader.cpp @@ -230,7 +230,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } // ------------------------------------------------------------------------------------------------ -void ConvertTexture(std::shared_ptr tex, aiMaterial *out, aiTextureType type) { +void ConvertTexture(const std::shared_ptr &tex, aiMaterial *out, aiTextureType type) { const aiString path(tex->path); out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0)); out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0)); diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index 5dbf0a567..3166136b2 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -453,7 +453,7 @@ void ColladaParser::PostProcessRootAnimations() { temp.mSubAnims.push_back(clip); - for (std::string animationID : it.second) { + for (const std::string &animationID : it.second) { AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID); if (animation != mAnimationLibrary.end()) { diff --git a/code/AssetLib/DXF/DXFLoader.cpp b/code/AssetLib/DXF/DXFLoader.cpp index 5d32ed121..49d572b0b 100644 --- a/code/AssetLib/DXF/DXFLoader.cpp +++ b/code/AssetLib/DXF/DXFLoader.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index a564b3e9b..f489e37a4 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -1766,6 +1766,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap // XXX handle all kinds of UV transformations uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mTranslation = tex->UVTranslation(); + uvTrafo.mRotation = tex->UVRotation(); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0); const PropertyTable &props = tex->Props(); @@ -1885,6 +1886,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex // XXX handle all kinds of UV transformations uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mTranslation = tex->UVTranslation(); + uvTrafo.mRotation = tex->UVRotation(); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex); const PropertyTable &props = tex->Props(); @@ -2324,6 +2326,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa // XXX handle all kinds of UV transformations uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mTranslation = tex->UVTranslation(); + uvTrafo.mRotation = tex->UVRotation(); out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0); int uvIndex = 0; @@ -2599,7 +2602,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) { anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels]; anim->mNumMorphMeshChannels = numMorphMeshChannels; unsigned int i = 0; - for (auto morphAnimIt : morphAnimDatas) { + for (const auto &morphAnimIt : morphAnimDatas) { morphAnimData *animData = morphAnimIt.second; unsigned int numKeys = static_cast(animData->size()); aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim(); diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index 7adaadf6c..0c4435348 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -57,9 +57,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include #include #include +#include +#include namespace Assimp { namespace FBX { @@ -248,10 +249,8 @@ Object::~Object() } // ------------------------------------------------------------------------------------------------ -FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr props) -: props(props) -, doc(doc) -{ +FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr props) : + props(std::move(props)), doc(doc) { // empty } diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index 69cda1c1a..1ee526368 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -500,6 +500,10 @@ public: return uvScaling; } + const ai_real &UVRotation() const { + return uvRotation; + } + const PropertyTable& Props() const { ai_assert(props.get()); return *props.get(); @@ -517,6 +521,7 @@ public: private: aiVector2D uvTrans; aiVector2D uvScaling; + ai_real uvRotation; std::string type; std::string relativeFileName; diff --git a/code/AssetLib/FBX/FBXExportNode.cpp b/code/AssetLib/FBX/FBXExportNode.cpp index 91e421420..817308ec8 100644 --- a/code/AssetLib/FBX/FBXExportNode.cpp +++ b/code/AssetLib/FBX/FBXExportNode.cpp @@ -144,9 +144,8 @@ void FBX::Node::AddP70time( // public member functions for writing nodes to stream void FBX::Node::Dump( - std::shared_ptr outfile, - bool binary, int indent -) { + const std::shared_ptr &outfile, + bool binary, int indent) { if (binary) { Assimp::StreamWriterLE outstream(outfile); DumpBinary(outstream); diff --git a/code/AssetLib/FBX/FBXExportNode.h b/code/AssetLib/FBX/FBXExportNode.h index c5f29ef0f..6ef27972d 100644 --- a/code/AssetLib/FBX/FBXExportNode.h +++ b/code/AssetLib/FBX/FBXExportNode.h @@ -157,9 +157,8 @@ public: // member functions for writing data to a file or stream // write the full node to the given file or stream void Dump( - std::shared_ptr outfile, - bool binary, int indent - ); + const std::shared_ptr &outfile, + bool binary, int indent); void Dump(Assimp::StreamWriterLE &s, bool binary, int indent); // these other functions are for writing data piece by piece. diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp index e519f7e77..ccff15c15 100644 --- a/code/AssetLib/FBX/FBXExporter.cpp +++ b/code/AssetLib/FBX/FBXExporter.cpp @@ -541,10 +541,17 @@ void FBXExporter::WriteReferences () // (before any actual data is written) // --------------------------------------------------------------- -size_t count_nodes(const aiNode* n) { - size_t count = 1; +size_t count_nodes(const aiNode* n, const aiNode* root) { + size_t count; + if (n == root) { + count = n->mNumMeshes; // (not counting root node) + } else if (n->mNumMeshes > 1) { + count = n->mNumMeshes + 1; + } else { + count = 1; + } for (size_t i = 0; i < n->mNumChildren; ++i) { - count += count_nodes(n->mChildren[i]); + count += count_nodes(n->mChildren[i], root); } return count; } @@ -714,7 +721,7 @@ void FBXExporter::WriteDefinitions () // Model / FbxNode // <~~ node hierarchy - count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node) + count = int32_t(count_nodes(mScene->mRootNode, mScene->mRootNode)); if (count) { n = FBX::Node("ObjectType", "Model"); n.AddChild("Count", count); @@ -1681,6 +1688,10 @@ void FBXExporter::WriteObjects () // link the image data to the texture connections.emplace_back("C", "OO", image_uid, texture_uid); + aiUVTransform trafo; + unsigned int max = sizeof(aiUVTransform); + aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (float *)&trafo, &max); + // now write the actual texture node FBX::Node tnode("Texture"); // TODO: some way to determine texture name? @@ -1691,6 +1702,9 @@ void FBXExporter::WriteObjects () tnode.AddChild("Version", int32_t(202)); tnode.AddChild("TextureName", texture_name); FBX::Node p("Properties70"); + p.AddP70vectorA("Translation", trafo.mTranslation[0], trafo.mTranslation[1], 0.0); + p.AddP70vectorA("Rotation", 0, 0, trafo.mRotation); + p.AddP70vectorA("Scaling", trafo.mScaling[0], trafo.mScaling[1], 0.0); p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify //p.AddP70string("UVSet", ""); // TODO: how should this work? p.AddP70bool("UseMaterial", 1); @@ -2196,7 +2210,65 @@ void FBXExporter::WriteObjects () bpnode.Dump(outstream, binary, indent); }*/ - // TODO: cameras, lights + // lights + indent = 1; + lights_uids.clear(); + for (size_t li = 0; li < mScene->mNumLights; ++li) { + aiLight* l = mScene->mLights[li]; + + int64_t uid = generate_uid(); + const std::string lightNodeAttributeName = l->mName.C_Str() + FBX::SEPARATOR + "NodeAttribute"; + + FBX::Node lna("NodeAttribute"); + lna.AddProperties(uid, lightNodeAttributeName, "Light"); + FBX::Node lnap("Properties70"); + + // Light color. + lnap.AddP70colorA("Color", l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b); + + // TODO Assimp light description is quite concise and do not handle light intensity. + // Default value to 1000W. + lnap.AddP70numberA("Intensity", 1000); + + // FBXLight::EType conversion + switch (l->mType) { + case aiLightSource_POINT: + lnap.AddP70enum("LightType", 0); + break; + case aiLightSource_DIRECTIONAL: + lnap.AddP70enum("LightType", 1); + break; + case aiLightSource_SPOT: + lnap.AddP70enum("LightType", 2); + lnap.AddP70numberA("InnerAngle", AI_RAD_TO_DEG(l->mAngleInnerCone)); + lnap.AddP70numberA("OuterAngle", AI_RAD_TO_DEG(l->mAngleOuterCone)); + break; + // TODO Assimp do not handle 'area' nor 'volume' lights, but FBX does. + /*case aiLightSource_AREA: + lnap.AddP70enum("LightType", 3); + lnap.AddP70enum("AreaLightShape", 0); // 0=Rectangle, 1=Sphere + break; + case aiLightSource_VOLUME: + lnap.AddP70enum("LightType", 4); + break;*/ + default: + break; + } + + // Did not understood how to configure the decay so disabling attenuation. + lnap.AddP70enum("DecayType", 0); + + // Dump to FBX stream + lna.AddChild(lnap); + lna.AddChild("TypeFlags", FBX::FBXExportProperty("Light")); + lna.AddChild("GeometryVersion", FBX::FBXExportProperty(int32_t(124))); + lna.Dump(outstream, binary, indent); + + // Store name and uid (will be used later when parsing scene nodes) + lights_uids[l->mName.C_Str()] = uid; + } + + // TODO: cameras // write nodes (i.e. model hierarchy) // start at root node @@ -2600,10 +2672,19 @@ void FBXExporter::WriteModelNodes( // and connect them connections.emplace_back("C", "OO", node_attribute_uid, node_uid); } else { - // generate a null node so we can add children to it - WriteModelNode( - outstream, binary, node, node_uid, "Null", transform_chain - ); + const auto& lightIt = lights_uids.find(node->mName.C_Str()); + if(lightIt != lights_uids.end()) { + // Node has a light connected to it. + WriteModelNode( + outstream, binary, node, node_uid, "Light", transform_chain + ); + connections.emplace_back("C", "OO", lightIt->second, node_uid); + } else { + // generate a null node so we can add children to it + WriteModelNode( + outstream, binary, node, node_uid, "Null", transform_chain + ); + } } // if more than one child mesh, make nodes for each mesh @@ -2625,17 +2706,14 @@ void FBXExporter::WriteModelNodes( ], new_node_uid ); - // write model node - FBX::Node m("Model"); + + aiNode new_node; // take name from mesh name, if it exists - std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str(); - name += FBX::SEPARATOR + "Model"; - m.AddProperties(new_node_uid, name, "Mesh"); - m.AddChild("Version", int32_t(232)); - FBX::Node p("Properties70"); - p.AddP70enum("InheritType", 1); - m.AddChild(p); - m.Dump(outstream, binary, 1); + new_node.mName = mScene->mMeshes[node->mMeshes[i]]->mName; + // write model node + WriteModelNode( + outstream, binary, &new_node, new_node_uid, "Mesh", std::vector>() + ); } } @@ -2647,16 +2725,14 @@ void FBXExporter::WriteModelNodes( } } - void FBXExporter::WriteAnimationCurveNode( - StreamWriterLE& outstream, - int64_t uid, - const std::string& name, // "T", "R", or "S" - aiVector3D default_value, - std::string property_name, // "Lcl Translation" etc - int64_t layer_uid, - int64_t node_uid -) { + StreamWriterLE &outstream, + int64_t uid, + const std::string &name, // "T", "R", or "S" + aiVector3D default_value, + const std::string &property_name, // "Lcl Translation" etc + int64_t layer_uid, + int64_t node_uid) { FBX::Node n("AnimationCurveNode"); n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", ""); FBX::Node p("Properties70"); @@ -2671,7 +2747,6 @@ void FBXExporter::WriteAnimationCurveNode( this->connections.emplace_back("C", "OP", uid, node_uid, property_name); } - void FBXExporter::WriteAnimationCurve( StreamWriterLE& outstream, double default_value, diff --git a/code/AssetLib/FBX/FBXExporter.h b/code/AssetLib/FBX/FBXExporter.h index dcd1d2727..d249b7bee 100644 --- a/code/AssetLib/FBX/FBXExporter.h +++ b/code/AssetLib/FBX/FBXExporter.h @@ -63,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiScene; struct aiNode; -//struct aiMaterial; +struct aiLight; -namespace Assimp -{ +namespace Assimp { class IOSystem; class IOStream; class ExportProperties; @@ -95,6 +94,7 @@ namespace Assimp std::vector mesh_uids; std::vector material_uids; std::map node_uids; + std::map lights_uids; // this crude unique-ID system is actually fine int64_t last_uid = 999999; @@ -154,14 +154,13 @@ namespace Assimp FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs ); void WriteAnimationCurveNode( - StreamWriterLE& outstream, - int64_t uid, - const std::string& name, // "T", "R", or "S" - aiVector3D default_value, - std::string property_name, // "Lcl Translation" etc - int64_t animation_layer_uid, - int64_t node_uid - ); + StreamWriterLE &outstream, + int64_t uid, + const std::string &name, // "T", "R", or "S" + aiVector3D default_value, + const std::string &property_name, // "Lcl Translation" etc + int64_t animation_layer_uid, + int64_t node_uid); void WriteAnimationCurve( StreamWriterLE& outstream, double default_value, diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp index 6ada9630b..aaa043c12 100644 --- a/code/AssetLib/FBX/FBXMaterial.cpp +++ b/code/AssetLib/FBX/FBXMaterial.cpp @@ -210,6 +210,11 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const uvTrans.y = trans.y; } + const aiVector3D &rotation = PropertyGet(*props, "Rotation", ok); + if (ok) { + uvRotation = rotation.z; + } + // resolve video links if(doc.Settings().readTextures) { const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID()); diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index 1a5ebffd1..c3f4de260 100644 --- a/code/AssetLib/FBX/FBXProperties.cpp +++ b/code/AssetLib/FBX/FBXProperties.cpp @@ -52,6 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXDocumentUtil.h" #include "FBXProperties.h" +#include + namespace Assimp { namespace FBX { @@ -172,10 +174,8 @@ PropertyTable::PropertyTable() } // ------------------------------------------------------------------------------------------------ -PropertyTable::PropertyTable(const Element& element, std::shared_ptr templateProps) -: templateProps(templateProps) -, element(&element) -{ +PropertyTable::PropertyTable(const Element &element, std::shared_ptr templateProps) : + templateProps(std::move(templateProps)), element(&element) { const Scope& scope = GetRequiredScope(element); for(const ElementMap::value_type& v : scope.Elements()) { if(v.first != "P") { @@ -199,7 +199,6 @@ PropertyTable::PropertyTable(const Element& element, std::shared_ptr meshtmp = std::make_shared(); if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr()) { - for(std::shared_ptr shell :shellmod->SbsmBoundary) { + for (const std::shared_ptr &shell : shellmod->SbsmBoundary) { try { const ::Assimp::STEP::EXPRESS::ENTITY& e = shell->To<::Assimp::STEP::EXPRESS::ENTITY>(); const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To(); diff --git a/code/AssetLib/IFC/IFCMaterial.cpp b/code/AssetLib/IFC/IFCMaterial.cpp index 2a79f0754..c26a3aa0a 100644 --- a/code/AssetLib/IFC/IFCMaterial.cpp +++ b/code/AssetLib/IFC/IFCMaterial.cpp @@ -75,7 +75,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle* mat->AddProperty(&name,AI_MATKEY_NAME); // now see which kinds of surface information are present - for(std::shared_ptr< const IFC::Schema_2x3::IfcSurfaceStyleElementSelect > sel2 : surf->Styles) { + for (const std::shared_ptr &sel2 : surf->Styles) { if (const IFC::Schema_2x3::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr(conv.db)) { aiColor4D col_base,col; @@ -124,7 +124,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle* } } } - } + } } } @@ -134,7 +134,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat for(;range.first != range.second; ++range.first) { if(const IFC::Schema_2x3::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr()) { for(const IFC::Schema_2x3::IfcPresentationStyleAssignment& as : styled->Styles) { - for(std::shared_ptr sel : as.Styles) { + for (const std::shared_ptr &sel : as.Styles) { if( const IFC::Schema_2x3::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr(conv.db) ) { // try to satisfy from cache diff --git a/code/AssetLib/IFC/IFCUtil.h b/code/AssetLib/IFC/IFCUtil.h index a1190746b..b18f35052 100644 --- a/code/AssetLib/IFC/IFCUtil.h +++ b/code/AssetLib/IFC/IFCUtil.h @@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + struct aiNode; namespace Assimp { @@ -137,14 +139,10 @@ struct TempOpening } // ------------------------------------------------------------------------------ - TempOpening(const IFC::Schema_2x3::IfcSolidModel* solid,IfcVector3 extrusionDir, - std::shared_ptr profileMesh, - std::shared_ptr profileMesh2D) - : solid(solid) - , extrusionDir(extrusionDir) - , profileMesh(profileMesh) - , profileMesh2D(profileMesh2D) - { + TempOpening(const IFC::Schema_2x3::IfcSolidModel *solid, IfcVector3 extrusionDir, + std::shared_ptr profileMesh, + std::shared_ptr profileMesh2D) : + solid(solid), extrusionDir(extrusionDir), profileMesh(std::move(profileMesh)), profileMesh2D(std::move(profileMesh2D)) { } // ------------------------------------------------------------------------------ diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index d469a1064..01a50b6e4 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -318,7 +318,7 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) { } else { ++s; } - std::string::size_type t = src.path.substr(s).find_last_of("."); + std::string::size_type t = src.path.substr(s).find_last_of('.'); nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); return; diff --git a/code/AssetLib/M3D/M3DImporter.cpp b/code/AssetLib/M3D/M3DImporter.cpp index 38bbd1d4a..4b2f9bd77 100644 --- a/code/AssetLib/M3D/M3DImporter.cpp +++ b/code/AssetLib/M3D/M3DImporter.cpp @@ -655,7 +655,7 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in // ------------------------------------------------------------------------------------------------ // find a node by name -aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) { +aiNode *M3DImporter::findNode(aiNode *pNode, const aiString &name) { ai_assert(pNode != nullptr); ai_assert(mScene != nullptr); diff --git a/code/AssetLib/M3D/M3DImporter.h b/code/AssetLib/M3D/M3DImporter.h index 7a2a9fbd3..05e8ced7b 100644 --- a/code/AssetLib/M3D/M3DImporter.h +++ b/code/AssetLib/M3D/M3DImporter.h @@ -89,8 +89,8 @@ private: // helper functions aiColor4D mkColor(uint32_t c); void convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid); - aiNode *findNode(aiNode *pNode, aiString name); - void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); + aiNode *findNode(aiNode *pNode, const aiString &name); + void calculateOffsetMatrix(aiNode *pNode, aiMatrix4x4 *m); void populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector *faces, std::vector *verteces, std::vector *normals, std::vector *texcoords, std::vector *colors, std::vector *vertexids); diff --git a/code/AssetLib/Ogre/OgreMaterial.cpp b/code/AssetLib/Ogre/OgreMaterial.cpp index 295dedde6..6da82f89c 100644 --- a/code/AssetLib/Ogre/OgreMaterial.cpp +++ b/code/AssetLib/Ogre/OgreMaterial.cpp @@ -415,8 +415,8 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr // User defined Assimp config property to detect texture type from filename. if (m_detectTextureTypeFromFilename) { - size_t posSuffix = textureRef.find_last_of("."); - size_t posUnderscore = textureRef.find_last_of("_"); + size_t posSuffix = textureRef.find_last_of('.'); + size_t posUnderscore = textureRef.find_last_of('_'); if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index becfa41fc..a1da8fd74 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -99,7 +99,7 @@ static void extractIds(const std::string &key, int &id1, int &id2) { return; } - const std::string::size_type pos = key.find("."); + const std::string::size_type pos = key.find('.'); if (std::string::npos == pos) { return; } @@ -208,7 +208,7 @@ void Q3BSPFileImporter::separateMapName(const std::string &importName, std::stri return; } - const std::string::size_type pos = importName.rfind(","); + const std::string::size_type pos = importName.rfind(','); if (std::string::npos == pos) { archiveName = importName; return; diff --git a/code/AssetLib/STEPParser/STEPFileReader.cpp b/code/AssetLib/STEPParser/STEPFileReader.cpp index e97ea1e28..ac6d83672 100644 --- a/code/AssetLib/STEPParser/STEPFileReader.cpp +++ b/code/AssetLib/STEPParser/STEPFileReader.cpp @@ -49,8 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "STEPFileEncoding.h" #include #include -#include #include +#include +#include using namespace Assimp; @@ -87,7 +88,7 @@ static const char *ISO_Token = "ISO-10303-21;"; static const char *FILE_SCHEMA_Token = "FILE_SCHEMA"; // ------------------------------------------------------------------------------------------------ STEP::DB* STEP::ReadFileHeader(std::shared_ptr stream) { - std::shared_ptr reader = std::shared_ptr(new StreamReaderLE(stream)); + std::shared_ptr reader = std::shared_ptr(new StreamReaderLE(std::move(stream))); std::unique_ptr db = std::unique_ptr(new STEP::DB(reader)); LineSplitter &splitter = db->GetSplitter(); diff --git a/code/AssetLib/Step/STEPFile.h b/code/AssetLib/Step/STEPFile.h index 90eaef5f3..e09faad98 100644 --- a/code/AssetLib/Step/STEPFile.h +++ b/code/AssetLib/Step/STEPFile.h @@ -634,7 +634,7 @@ private: }; template -inline bool operator==(std::shared_ptr lo, T whatever) { +inline bool operator==(const std::shared_ptr &lo, T whatever) { return *lo == whatever; // XXX use std::forward if we have 0x } @@ -816,7 +816,7 @@ public: typedef std::pair RefMapRange; private: - DB(std::shared_ptr reader) : + DB(const std::shared_ptr &reader) : reader(reader), splitter(*reader, true, true), evaluated_count(), schema(nullptr) {} public: diff --git a/code/AssetLib/X/XFileExporter.cpp b/code/AssetLib/X/XFileExporter.cpp index da20b935a..bd997a3c5 100644 --- a/code/AssetLib/X/XFileExporter.cpp +++ b/code/AssetLib/X/XFileExporter.cpp @@ -530,8 +530,8 @@ void XFileExporter::writePath(const aiString &path) while( str.find( "\\\\") != std::string::npos) str.replace( str.find( "\\\\"), 2, "\\"); - while( str.find( "\\") != std::string::npos) - str.replace( str.find( "\\"), 1, "/"); + while (str.find('\\') != std::string::npos) + str.replace(str.find('\\'), 1, "/"); mOutput << str; diff --git a/code/AssetLib/X3D/X3DExporter.hpp b/code/AssetLib/X3D/X3DExporter.hpp index 00115e0b6..fefaba9f3 100644 --- a/code/AssetLib/X3D/X3DExporter.hpp +++ b/code/AssetLib/X3D/X3DExporter.hpp @@ -63,9 +63,9 @@ class X3DExporter { // empty } - SAttribute(SAttribute && rhs) : - Name(std::move(rhs.Name)), - Value(std::move(rhs.Value)) { + SAttribute(SAttribute &&rhs) AI_NO_EXCEPT : + Name(rhs.Name), + Value(rhs.Value) { // empty } }; diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index da49a1737..4cef646d2 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -456,11 +456,10 @@ namespace glTF /// \param [in] pDecodedData - pointer to decoded data array. /// \param [in] pDecodedData_Length - size of encoded region, in bytes. /// \param [in] pID - ID of the region. - SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID) - : Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) - {} + SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) : + Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {} - /// \fn ~SEncodedRegion() + /// \fn ~SEncodedRegion() /// Destructor. ~SEncodedRegion() { delete [] DecodedData; } }; @@ -1149,8 +1148,7 @@ namespace glTF void ReadExtensionsUsed(Document& doc); - - IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); + IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false); }; } diff --git a/code/AssetLib/glTF/glTFAsset.inl b/code/AssetLib/glTF/glTFAsset.inl index 6e1e60846..e915a3aee 100644 --- a/code/AssetLib/glTF/glTFAsset.inl +++ b/code/AssetLib/glTF/glTFAsset.inl @@ -1377,7 +1377,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) { #undef CHECK_EXT } -inline IOStream *Asset::OpenFile(std::string path, const char *mode, bool absolute) { +inline IOStream *Asset::OpenFile(const std::string& path, const char *mode, bool absolute) { #ifdef ASSIMP_API (void)absolute; return mIOSystem->Open(path, mode); diff --git a/code/AssetLib/glTF/glTFExporter.cpp b/code/AssetLib/glTF/glTFExporter.cpp index 5e1992319..810263f52 100644 --- a/code/AssetLib/glTF/glTFExporter.cpp +++ b/code/AssetLib/glTF/glTFExporter.cpp @@ -405,8 +405,7 @@ void glTFExporter::ExportMaterials() * Search through node hierarchy and find the node containing the given meshID. * Returns true on success, and false otherwise. */ -bool FindMeshNode(Ref& nodeIn, Ref& meshNode, std::string meshID) -{ +bool FindMeshNode(Ref &nodeIn, Ref &meshNode, const std::string &meshID) { for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) { if (meshID.compare(nodeIn->meshes[i]->id) == 0) { meshNode = nodeIn; diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 6aa0f92ed..bb97e3732 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -356,6 +356,53 @@ struct Nullable { isPresent(true) {} }; +struct CustomExtension { + // + // A struct containing custom extension data added to a glTF2 file + // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum + // String, Double, Uint64, and Int64 are stored in the Nullables + // Object and Array are stored in the std::vector + // + std::string name; + + Nullable mStringValue; + Nullable mDoubleValue; + Nullable mUint64Value; + Nullable mInt64Value; + Nullable mBoolValue; + + // std::vector handles both Object and Array + Nullable> mValues; + + operator bool() const { + return Size() != 0; + } + + size_t Size() const { + if (mValues.isPresent) { + return mValues.value.size(); + } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) { + return 1; + } + return 0; + } + + CustomExtension() = default; + + ~CustomExtension() = default; + + CustomExtension(const CustomExtension &other) : + name(other.name), + mStringValue(other.mStringValue), + mDoubleValue(other.mDoubleValue), + mUint64Value(other.mUint64Value), + mInt64Value(other.mInt64Value), + mBoolValue(other.mBoolValue), + mValues(other.mValues) { + // empty + } +}; + //! Base class for all glTF top-level objects struct Object { int index; //!< The index of this object within its property container @@ -363,6 +410,9 @@ struct Object { std::string id; //!< The globally unique ID used to reference this object std::string name; //!< The user-defined name of this object + CustomExtension customExtensions; + CustomExtension extras; + //! Objects marked as special are not exported (used to emulate the binary body buffer) virtual bool IsSpecial() const { return false; } @@ -377,6 +427,9 @@ struct Object { inline Value *FindArray(Value &val, const char *id); inline Value *FindObject(Value &val, const char *id); inline Value *FindExtension(Value &val, const char *extensionId); + + inline void ReadExtensions(Value &val); + inline void ReadExtras(Value &val); }; // @@ -408,7 +461,7 @@ public: /// \param [in] pDecodedData - pointer to decoded data array. /// \param [in] pDecodedData_Length - size of encoded region, in bytes. /// \param [in] pID - ID of the region. - SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string pID) : + SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) : Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), @@ -834,50 +887,6 @@ struct Mesh : public Object { void Read(Value &pJSON_Object, Asset &pAsset_Root); }; -struct CustomExtension : public Object { - // - // A struct containing custom extension data added to a glTF2 file - // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum - // String, Double, Uint64, and Int64 are stored in the Nullables - // Object and Array are stored in the std::vector - // - - Nullable mStringValue; - Nullable mDoubleValue; - Nullable mUint64Value; - Nullable mInt64Value; - Nullable mBoolValue; - - // std::vector handles both Object and Array - Nullable> mValues; - - operator bool() const { - return Size() != 0; - } - - size_t Size() const { - if (mValues.isPresent) { - return mValues.value.size(); - } else if (mStringValue.isPresent || mDoubleValue.isPresent || mUint64Value.isPresent || mInt64Value.isPresent || mBoolValue.isPresent) { - return 1; - } - return 0; - } - - CustomExtension() = default; - - CustomExtension(const CustomExtension &other) - : Object(other) - , mStringValue(other.mStringValue) - , mDoubleValue(other.mDoubleValue) - , mUint64Value(other.mUint64Value) - , mInt64Value(other.mInt64Value) - , mBoolValue(other.mBoolValue) - , mValues(other.mValues) - { - } -}; - struct Node : public Object { std::vector> children; std::vector> meshes; @@ -896,8 +905,6 @@ struct Node : public Object { Ref parent; //!< This is not part of the glTF specification. Used as a helper. - CustomExtension extensions; - Node() {} void Read(Value &obj, Asset &r); }; @@ -1188,7 +1195,7 @@ private: void ReadExtensionsUsed(Document &doc); void ReadExtensionsRequired(Document &doc); - IOStream *OpenFile(std::string path, const char *mode, bool absolute = false); + IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false); }; inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) { diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index b51ac20c2..fd509bada 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -304,6 +303,43 @@ inline Value *FindObject(Document &doc, const char *memberId) { inline Value *FindExtension(Value &val, const char *extensionId) { return FindExtensionInContext(val, extensionId, "the document"); } + +inline CustomExtension ReadExtensions(const char *name, Value &obj) { + CustomExtension ret; + ret.name = name; + if (obj.IsObject()) { + ret.mValues.isPresent = true; + for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { + auto &val = it->value; + ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); + } + } else if (obj.IsArray()) { + ret.mValues.value.reserve(obj.Size()); + ret.mValues.isPresent = true; + for (unsigned int i = 0; i < obj.Size(); ++i) { + ret.mValues.value.push_back(ReadExtensions(name, obj[i])); + } + } else if (obj.IsNumber()) { + if (obj.IsUint64()) { + ret.mUint64Value.value = obj.GetUint64(); + ret.mUint64Value.isPresent = true; + } else if (obj.IsInt64()) { + ret.mInt64Value.value = obj.GetInt64(); + ret.mInt64Value.isPresent = true; + } else if (obj.IsDouble()) { + ret.mDoubleValue.value = obj.GetDouble(); + ret.mDoubleValue.isPresent = true; + } + } else if (obj.IsString()) { + ReadValue(obj, ret.mStringValue); + ret.mStringValue.isPresent = true; + } else if (obj.IsBool()) { + ret.mBoolValue.value = obj.GetBool(); + ret.mBoolValue.isPresent = true; + } + return ret; +} + } // namespace inline Value *Object::FindString(Value &val, const char *memberId) { @@ -330,6 +366,18 @@ inline Value *Object::FindExtension(Value &val, const char *extensionId) { return FindExtensionInContext(val, extensionId, id.c_str(), name.c_str()); } +inline void Object::ReadExtensions(Value &val) { + if (Value *curExtensions = FindObject(val, "extensions")) { + this->customExtensions = glTF2::ReadExtensions("extensions", *curExtensions); + } +} + +inline void Object::ReadExtras(Value &val) { + if (Value *curExtras = FindObject(val, "extras")) { + this->extras = glTF2::ReadExtensions("extras", *curExtras); + } +} + #ifdef ASSIMP_ENABLE_DRACO template @@ -569,6 +617,8 @@ Ref LazyDict::Retrieve(unsigned int i) { inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); + inst->ReadExtensions(obj); + inst->ReadExtras(obj); Ref result = Add(inst.release()); mRecursiveReferenceCheck.erase(i); @@ -733,12 +783,13 @@ inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncod } inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) { - if ((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return; + if ((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) { + return; + } for (SEncodedRegion *reg : EncodedRegion_List) { if (reg->ID == pID) { EncodedRegion_Current = reg; - return; } } @@ -788,10 +839,13 @@ inline bool Buffer::ReplaceData_joint(const size_t pBufferData_Offset, const siz } inline size_t Buffer::AppendData(uint8_t *data, size_t length) { - size_t offset = this->byteLength; + const size_t offset = this->byteLength; + // Force alignment to 4 bits - Grow((length + 3) & ~3); + const size_t paddedLength = (length + 3) & ~3; + Grow(paddedLength); memcpy(mData.get() + offset, data, length); + memset(mData.get() + offset + length, 0, paddedLength - length); return offset; } @@ -820,9 +874,7 @@ inline void Buffer::Grow(size_t amount) { // // struct BufferView // - inline void BufferView::Read(Value &obj, Asset &r) { - if (Value *bufferVal = FindUInt(obj, "buffer")) { buffer = r.buffers.Retrieve(bufferVal->GetUint()); } @@ -842,16 +894,21 @@ inline void BufferView::Read(Value &obj, Asset &r) { } inline uint8_t *BufferView::GetPointer(size_t accOffset) { - if (!buffer) return nullptr; + if (!buffer) { + return nullptr; + } uint8_t *basePtr = buffer->GetPointer(); - if (!basePtr) return nullptr; + if (!basePtr) { + return nullptr; + } size_t offset = accOffset + byteOffset; if (buffer->EncodedRegion_Current != nullptr) { const size_t begin = buffer->EncodedRegion_Current->Offset; const size_t end = begin + buffer->EncodedRegion_Current->DecodedData_Length; - if ((offset >= begin) && (offset < end)) + if ((offset >= begin) && (offset < end)) { return &buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } } return basePtr + offset; @@ -877,18 +934,18 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) { while (pIndices != indicesEnd) { size_t offset; switch (indicesType) { - case ComponentType_UNSIGNED_BYTE: - offset = *pIndices; - break; - case ComponentType_UNSIGNED_SHORT: - offset = *reinterpret_cast(pIndices); - break; - case ComponentType_UNSIGNED_INT: - offset = *reinterpret_cast(pIndices); - break; - default: - // have fun with float and negative values from signed types as indices. - throw DeadlyImportError("Unsupported component type in index."); + case ComponentType_UNSIGNED_BYTE: + offset = *pIndices; + break; + case ComponentType_UNSIGNED_SHORT: + offset = *reinterpret_cast(pIndices); + break; + case ComponentType_UNSIGNED_INT: + offset = *reinterpret_cast(pIndices); + break; + default: + // have fun with float and negative values from signed types as indices. + throw DeadlyImportError("Unsupported component type in index."); } offset *= elementSize; @@ -900,7 +957,6 @@ inline void Accessor::Sparse::PatchData(unsigned int elementSize) { } inline void Accessor::Read(Value &obj, Asset &r) { - if (Value *bufferViewVal = FindUInt(obj, "bufferView")) { bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); } @@ -1612,9 +1668,9 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) { } } - Value *extras = FindObject(pJSON_Object, "extras"); - if (nullptr != extras) { - if (Value *curTargetNames = FindArray(*extras, "targetNames")) { + Value *curExtras = FindObject(pJSON_Object, "extras"); + if (nullptr != curExtras) { + if (Value *curTargetNames = FindArray(*curExtras, "targetNames")) { this->targetNames.resize(curTargetNames->Size()); for (unsigned int i = 0; i < curTargetNames->Size(); ++i) { Value &targetNameValue = (*curTargetNames)[i]; @@ -1683,42 +1739,6 @@ inline void Light::Read(Value &obj, Asset & /*r*/) { } } -inline CustomExtension ReadExtensions(const char *name, Value &obj) { - CustomExtension ret; - ret.name = name; - if (obj.IsObject()) { - ret.mValues.isPresent = true; - for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) { - auto &val = it->value; - ret.mValues.value.push_back(ReadExtensions(it->name.GetString(), val)); - } - } else if (obj.IsArray()) { - ret.mValues.value.reserve(obj.Size()); - ret.mValues.isPresent = true; - for (unsigned int i = 0; i < obj.Size(); ++i) { - ret.mValues.value.push_back(ReadExtensions(name, obj[i])); - } - } else if (obj.IsNumber()) { - if (obj.IsUint64()) { - ret.mUint64Value.value = obj.GetUint64(); - ret.mUint64Value.isPresent = true; - } else if (obj.IsInt64()) { - ret.mInt64Value.value = obj.GetInt64(); - ret.mInt64Value.isPresent = true; - } else if (obj.IsDouble()) { - ret.mDoubleValue.value = obj.GetDouble(); - ret.mDoubleValue.isPresent = true; - } - } else if (obj.IsString()) { - ReadValue(obj, ret.mStringValue); - ret.mStringValue.isPresent = true; - } else if (obj.IsBool()) { - ret.mBoolValue.value = obj.GetBool(); - ret.mBoolValue.isPresent = true; - } - return ret; -} - inline void Node::Read(Value &obj, Asset &r) { if (name.empty()) { name = id; @@ -1775,8 +1795,6 @@ inline void Node::Read(Value &obj, Asset &r) { Value *curExtensions = FindObject(obj, "extensions"); if (nullptr != curExtensions) { - this->extensions = ReadExtensions("extensions", *curExtensions); - if (r.extensionsUsed.KHR_lights_punctual) { if (Value *ext = FindObject(*curExtensions, "KHR_lights_punctual")) { Value *curLight = FindUInt(*ext, "light"); @@ -2132,7 +2150,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) { #undef CHECK_EXT } -inline IOStream *Asset::OpenFile(std::string path, const char *mode, bool /*absolute*/) { +inline IOStream *Asset::OpenFile(const std::string& path, const char *mode, bool /*absolute*/) { #ifdef ASSIMP_API return mIOSystem->Open(path, mode); #else diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 751508225..02c3233f3 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -118,14 +118,14 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportScene(); ExportAnimations(); - + // export extras if(mProperties->HasPropertyCallback("extras")) { std::function ExportExtras = mProperties->GetPropertyCallback("extras"); mAsset->extras = (rapidjson::Value*)ExportExtras(0); } - + AssetWriter writer(*mAsset); if (isBinary) { @@ -436,11 +436,11 @@ inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map) }; } -void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, aiTextureType tt, unsigned int slot) +void glTF2Exporter::GetTexSampler(const aiMaterial& mat, Ref texture, aiTextureType tt, unsigned int slot) { aiString aId; std::string id; - if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) { + if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) { id = aId.C_Str(); } @@ -455,49 +455,52 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, a SamplerMagFilter filterMag; SamplerMinFilter filterMin; - if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) { + 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) { + 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) { + 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) { + 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) { + if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) { texture->sampler->name = name.C_Str(); } } } -void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) +void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) { std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; - mat->Get(textureKey.c_str(), tt, slot, prop); + mat.Get(textureKey.c_str(), tt, slot, prop); } -void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot) +void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot) { std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; - mat->Get(textureKey.c_str(), tt, slot, prop); + mat.Get(textureKey.c_str(), tt, slot, prop); } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt, unsigned int slot = 0) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, Ref& texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) { - if (mat->GetTextureCount(tt) > 0) { + if (mat.GetTextureCount(tt) > 0) { aiString tex; - if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { + // Read texcoord (UV map index) + mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord); + + if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { std::string path = tex.C_Str(); if (path.size() > 0) { @@ -515,11 +518,10 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe std::string imgId = mAsset->FindUniqueID("", "image"); texture->source = mAsset->images.Create(imgId); - if (path[0] == '*') { // embedded - aiTexture* curTex = mScene->mTextures[atoi(&path[1])]; - + const aiTexture* curTex = mScene->GetEmbeddedTexture(path.c_str()); + if (curTex != nullptr) { // embedded texture->source->name = curTex->mFilename.C_Str(); - + //basisu: embedded ktx2, bu if (curTex->achFormatHint[0]) { std::string mimeType = "image/"; @@ -541,7 +543,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe mimeType += curTex->achFormatHint; texture->source->mimeType = mimeType; } - + // The asset has its own buffer, see Image::SetData //basisu: "image/ktx2", "image/basis" as is texture->source->SetData(reinterpret_cast(curTex->pcData), curTex->mWidth, *mAsset); @@ -554,7 +556,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe useBasisUniversal = true; } } - + //basisu if(useBasisUniversal) { mAsset->extensionsUsed.KHR_texture_basisu = true; @@ -568,45 +570,45 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe } } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0) { Ref& texture = prop.texture; - GetMatTex(mat, texture, tt, slot); + GetMatTex(mat, texture, prop.texCoord, tt, slot); - if (texture) { - GetMatTexProp(mat, prop.texCoord, "texCoord", 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) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) { Ref& texture = prop.texture; - GetMatTex(mat, texture, tt, slot); + GetMatTex(mat, texture, prop.texCoord, tt, slot); if (texture) { - GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + //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) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) { Ref& texture = prop.texture; - GetMatTex(mat, texture, tt, slot); + GetMatTex(mat, texture, prop.texCoord, tt, slot); if (texture) { - GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + //GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); GetMatTexProp(mat, prop.strength, "strength", tt, slot); } } -aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx) +aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec4& prop, const char* propName, int type, int idx) const { aiColor4D col; - aiReturn result = mat->Get(propName, type, idx, col); + aiReturn result = mat.Get(propName, type, idx, col); if (result == AI_SUCCESS) { prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a; @@ -615,37 +617,116 @@ aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const cha return result; } -aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx) +aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec3& prop, const char* propName, int type, int idx) const { aiColor3D col; - aiReturn result = mat->Get(propName, type, idx, col); + aiReturn result = mat.Get(propName, type, idx, col); if (result == AI_SUCCESS) { - prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; + prop[0] = col.r; + prop[1] = col.g; + prop[2] = col.b; } return result; } +bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlossiness &pbrSG) { + bool result = false; + // If has Glossiness, a Specular Color or Specular Texture, use the KHR_materials_pbrSpecularGlossiness extension + // NOTE: This extension is being considered for deprecation (Dec 2020), may be replaced by KHR_material_specular + + if (mat.Get(AI_MATKEY_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) == AI_SUCCESS) { + result = true; + } else { + // Don't have explicit glossiness, convert from pbr roughness or legacy shininess + float shininess; + if (mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, shininess) == AI_SUCCESS) { + pbrSG.glossinessFactor = 1.0f - shininess; // Extension defines this way + } else if (mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) { + pbrSG.glossinessFactor = shininess / 1000; + } + } + + if (GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR) == AI_SUCCESS) { + result = true; + } + // Add any appropriate textures + GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR); + + result = result || pbrSG.specularGlossinessTexture.texture; + + if (result) { + // Likely to always have diffuse + GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE); + GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE); + } + + return result; +} + +bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) { + // Return true if got any valid Sheen properties or textures + if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS) + return false; + + // Default Sheen color factor {0,0,0} disables Sheen, so do not export + if (sheen.sheenColorFactor == defaultSheenFactor) + return false; + + mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor); + + GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_SHEEN_COLOR_TEXTURE); + GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE); + + return true; +} + +bool glTF2Exporter::GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat) { + if (mat.Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor) != aiReturn_SUCCESS) { + return false; + } + + // Clearcoat factor of zero disables Clearcoat, so do not export + if (clearcoat.clearcoatFactor == 0.0f) + return false; + + mat.Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor); + + GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_CLEARCOAT_TEXTURE); + GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE); + GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE); + + return true; +} + +bool glTF2Exporter::GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission) { + bool result = mat.Get(AI_MATKEY_TRANSMISSION_FACTOR, transmission.transmissionFactor) == aiReturn_SUCCESS; + GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_TRANSMISSION_TEXTURE); + return result || transmission.transmissionTexture.texture; +} + void glTF2Exporter::ExportMaterials() { aiString aiName; for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { - const aiMaterial* mat = mScene->mMaterials[i]; + ai_assert(mScene->mMaterials[i] != nullptr); + + const aiMaterial & mat = *(mScene->mMaterials[i]); std::string id = "material_" + ai_to_string(i); Ref m = mAsset->materials.Create(id); std::string name; - if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { + if (mat.Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { name = aiName.C_Str(); } name = mAsset->FindUniqueID(name, "material"); m->name = name; - GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_BASE_COLOR); if (!m->pbrMetallicRoughness.baseColorTexture.texture) { //if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture @@ -654,26 +735,26 @@ void glTF2Exporter::ExportMaterials() GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); - if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR) != AI_SUCCESS) { + if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_BASE_COLOR) != AI_SUCCESS) { // if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material. //a fallback to any diffuse color should be used instead GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); } - if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) { + if (mat.Get(AI_MATKEY_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; } // get roughness if source is gltf2 file - if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) { + if (mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) { // otherwise, try to derive and convert from specular + shininess values aiColor4D specularColor; ai_real shininess; if ( - mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && - mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS + mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && + mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS ) { // convert specular color to luminance float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; @@ -694,103 +775,60 @@ void glTF2Exporter::ExportMaterials() 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); + mat.Get(AI_MATKEY_TWOSIDED, m->doubleSided); + mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); + float opacity; aiString alphaMode; - if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) { + if (mat.Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { + if (opacity < 1) { + m->alphaMode = "BLEND"; + m->pbrMetallicRoughness.baseColorFactor[3] *= opacity; + } + } + if (mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) { m->alphaMode = alphaMode.C_Str(); - } else { - float opacity; - - if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { - if (opacity < 1) { - m->alphaMode = "BLEND"; - 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; - } - + { + // KHR_materials_pbrSpecularGlossiness extension + // NOTE: This extension is being considered for deprecation (Dec 2020) PbrSpecularGlossiness pbrSG; - - GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE); - GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR); - - if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) { - float shininess; - - if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) { - pbrSG.glossinessFactor = shininess / 1000; - } + if (GetMatSpecGloss(mat, pbrSG)) { + mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true; + m->pbrSpecularGlossiness = Nullable(pbrSG); } - - GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE); - GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR); - - m->pbrSpecularGlossiness = Nullable(pbrSG); } - bool unlit; - if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) { + // glTFv2 is either PBR or Unlit + aiShadingMode shadingMode = aiShadingMode_PBR_BRDF; + mat.Get(AI_MATKEY_SHADING_MODEL, shadingMode); + if (shadingMode == aiShadingMode_Unlit) { mAsset->extensionsUsed.KHR_materials_unlit = true; m->unlit = true; - } + } else { + // These extensions are not compatible with KHR_materials_unlit or KHR_materials_pbrSpecularGlossiness + if (!m->pbrSpecularGlossiness.isPresent) { + // Sheen + MaterialSheen sheen; + if (GetMatSheen(mat, sheen)) { + mAsset->extensionsUsed.KHR_materials_sheen = true; + m->materialSheen = Nullable(sheen); + } - bool hasMaterialSheen = false; - mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN, hasMaterialSheen); + MaterialClearcoat clearcoat; + if (GetMatClearcoat(mat, clearcoat)) { + mAsset->extensionsUsed.KHR_materials_clearcoat = true; + m->materialClearcoat = Nullable(clearcoat); + } - if (hasMaterialSheen) { - mAsset->extensionsUsed.KHR_materials_sheen = true; - - MaterialSheen sheen; - - GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR); - mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor); - GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE); - GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE); - - m->materialSheen = Nullable(sheen); - } - - bool hasMaterialClearcoat = false; - mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT, hasMaterialClearcoat); - - if (hasMaterialClearcoat) { - mAsset->extensionsUsed.KHR_materials_clearcoat= true; - - MaterialClearcoat clearcoat; - - mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor); - mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor); - GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE); - GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE); - GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE); - - m->materialClearcoat = Nullable(clearcoat); - } - - bool hasMaterialTransmission = false; - mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION, hasMaterialTransmission); - - if (hasMaterialTransmission) { - mAsset->extensionsUsed.KHR_materials_transmission = true; - - MaterialTransmission transmission; - - mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR, transmission.transmissionFactor); - GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE); - - m->materialTransmission = Nullable(transmission); + MaterialTransmission transmission; + if (GetMatTransmission(mat, transmission)) { + mAsset->extensionsUsed.KHR_materials_transmission = true; + m->materialTransmission = Nullable(transmission); + } + } } } } @@ -799,8 +837,7 @@ void glTF2Exporter::ExportMaterials() * Search through node hierarchy and find the node containing the given meshID. * Returns true on success, and false otherwise. */ -bool FindMeshNode(Ref& nodeIn, Ref& meshNode, std::string meshID) -{ +bool FindMeshNode(Ref &nodeIn, Ref &meshNode, const std::string &meshID) { for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) { if (meshID.compare(nodeIn->meshes[i]->id) == 0) { meshNode = nodeIn; diff --git a/code/AssetLib/glTF2/glTF2Exporter.h b/code/AssetLib/glTF2/glTF2Exporter.h index 86497516a..f5238297f 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.h +++ b/code/AssetLib/glTF2/glTF2Exporter.h @@ -72,6 +72,10 @@ namespace glTF2 struct OcclusionTextureInfo; struct Node; struct Texture; + struct PbrSpecularGlossiness; + struct MaterialSheen; + struct MaterialClearcoat; + struct MaterialTransmission; // Vec/matrix types, as raw float arrays typedef float (vec2)[2]; @@ -97,15 +101,19 @@ namespace Assimp protected: void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); - void GetTexSampler(const aiMaterial* mat, glTF2::Ref 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& 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); - aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx); - aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx); + void GetTexSampler(const aiMaterial& mat, glTF2::Ref 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& texture, unsigned int &texCoord, 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); + aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec4& prop, const char* propName, int type, int idx) const; + aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec3& prop, const char* propName, int type, int idx) const; + bool GetMatSpecGloss(const aiMaterial& mat, glTF2::PbrSpecularGlossiness& pbrSG); + bool GetMatSheen(const aiMaterial& mat, glTF2::MaterialSheen& sheen); + bool GetMatClearcoat(const aiMaterial& mat, glTF2::MaterialClearcoat& clearcoat); + bool GetMatTransmission(const aiMaterial& mat, glTF2::MaterialTransmission& transmission); void ExportMetadata(); void ExportMaterials(); void ExportMeshes(); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index c62989c3b..d80df97d2 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -165,7 +165,8 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset } mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); - mat->AddProperty(&prop.texCoord, 1, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(texType, texSlot)); + const int uvIndex = static_cast(prop.texCoord); + mat->AddProperty(&uvIndex, 1, AI_MATKEY_UVWSRC(texType, texSlot)); if (prop.textureTransformSupported) { aiUVTransform transform; @@ -208,6 +209,11 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset if (sampler->minFilter != SamplerMinFilter::UNSET) { mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); } + } else { + // Use glTFv2 default sampler + const aiTextureMapMode default_wrap = aiTextureMapMode_Wrap; + mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); } } } @@ -238,16 +244,18 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M aimat->AddProperty(&str, AI_MATKEY_NAME); } + // Set Assimp DIFFUSE and BASE COLOR to the pbrMetallicRoughness base color and texture for backwards compatibility + // Technically should not load any pbrMetallicRoughness if extensionsRequired contains KHR_materials_pbrSpecularGlossiness SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR); + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_BASE_COLOR); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR); 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); + aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR); float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor; roughnessAsShininess *= roughnessAsShininess * 1000; @@ -259,6 +267,7 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE); aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); + aimat->AddProperty(&mat.pbrMetallicRoughness.baseColorFactor[3], 1, AI_MATKEY_OPACITY); aiString alphaMode(mat.alphaMode); aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE); @@ -268,52 +277,58 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M 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_COLOR_DIFFUSE); SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR); float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f; aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS); - aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR); + aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLOSSINESS_FACTOR); SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE); SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); } + + // glTFv2 is either PBR or Unlit + aiShadingMode shadingMode = aiShadingMode_PBR_BRDF; if (mat.unlit) { - aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT); + shadingMode = aiShadingMode_Unlit; } - //KHR_materials_sheen + aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL); + + + // KHR_materials_sheen if (mat.materialSheen.isPresent) { MaterialSheen &sheen = mat.materialSheen.value; - - aimat->AddProperty(&mat.materialSheen.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN); - SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR); - aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE); + // Default value {0,0,0} disables Sheen + if (sheen.sheenColorFactor != defaultSheenFactor) { + SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_SHEEN_COLOR_FACTOR); + aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_SHEEN_ROUGHNESS_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_SHEEN_COLOR_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE); + } } - //KHR_materials_clearcoat + // KHR_materials_clearcoat if (mat.materialClearcoat.isPresent) { MaterialClearcoat &clearcoat = mat.materialClearcoat.value; - - aimat->AddProperty(&mat.materialClearcoat.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT); - aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR); - aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE); + // Default value 0.0 disables clearcoat + if (clearcoat.clearcoatFactor != 0.0f) { + aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_CLEARCOAT_FACTOR); + aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_CLEARCOAT_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE); + } } - //KHR_materials_transmission + // KHR_materials_transmission if (mat.materialTransmission.isPresent) { MaterialTransmission &transmission = mat.materialTransmission.value; - aimat->AddProperty(&mat.materialTransmission.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION); - aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE); + aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_TRANSMISSION_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE); } return aimat; @@ -489,7 +504,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { "\" does not match the vertex count"); continue; } - + auto componentType = attr.color[c]->componentType; if (componentType == glTF2::ComponentType_FLOAT) { attr.color[c]->ExtractData(aim->mColors[c]); @@ -984,6 +999,14 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) { } } +void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) { + if (extension.mValues.isPresent) { + for (size_t i = 0; i < extension.mValues.value.size(); ++i) { + ParseExtensions(metadata, extension.mValues.value[i]); + } + } +} + aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector &meshOffsets, glTF2::Ref &ptr) { Node &node = *ptr; @@ -1002,9 +1025,14 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & } } - if (node.extensions) { + if (node.customExtensions || node.extras) { ainode->mMetaData = new aiMetadata; - ParseExtensions(ainode->mMetaData, node.extensions); + if (node.customExtensions) { + ParseExtensions(ainode->mMetaData, node.customExtensions); + } + if (node.extras) { + ParseExtras(ainode->mMetaData, node.extras); + } } GetNodeTransform(ainode->mTransformation, node); @@ -1498,7 +1526,8 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { const bool hasVersion = !a.asset.version.empty(); const bool hasGenerator = !a.asset.generator.empty(); const bool hasCopyright = !a.asset.copyright.empty(); - if (hasVersion || hasGenerator || hasCopyright) { + const bool hasSceneMetadata = a.scene->customExtensions; + if (hasVersion || hasGenerator || hasCopyright || hasSceneMetadata) { mScene->mMetaData = new aiMetadata; if (hasVersion) { mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT_VERSION, aiString(a.asset.version)); @@ -1509,6 +1538,9 @@ void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { if (hasCopyright) { mScene->mMetaData->Add(AI_METADATA_SOURCE_COPYRIGHT, aiString(a.asset.copyright)); } + if (hasSceneMetadata) { + ParseExtensions(mScene->mMetaData, a.scene->customExtensions); + } } } diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index 555d46b6a..8f10d6308 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -406,11 +406,25 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector, // where n is the index of the texture. - aiString &s = *((aiString *)prop->mData); + // Copy here because we overwrite the string data in-place and the buffer inside of aiString + // will be a lie if we just reinterpret from prop->mData. The size of mData is not guaranteed to be + // MAXLEN in size. + aiString s(*(aiString *)prop->mData); if ('*' == s.data[0]) { // Offset the index and write it back .. const unsigned int idx = strtoul10(&s.data[1]) + offset[n]; - ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx); + const unsigned int oldLen = s.length; + + s.length = 1 + ASSIMP_itoa10(&s.data[1], sizeof(s.data) - 1, idx); + + // The string changed in size so we need to reallocate the buffer for the property. + if (oldLen < s.length) { + prop->mDataLength += s.length - oldLen; + delete[] prop->mData; + prop->mData = new char[prop->mDataLength]; + } + + memcpy(prop->mData, static_cast(&s), prop->mDataLength); } } diff --git a/code/Common/material.cpp b/code/Common/material.cpp index 5230c8b43..6c90e66f0 100644 --- a/code/Common/material.cpp +++ b/code/Common/material.cpp @@ -47,10 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // ------------------------------------------------------------------------------- -const char* TextureTypeToString(aiTextureType in) -{ - switch (in) - { +const char *TextureTypeToString(aiTextureType in) { + switch (in) { case aiTextureType_NONE: return "n/a"; case aiTextureType_DIFFUSE: @@ -87,6 +85,12 @@ const char* TextureTypeToString(aiTextureType in) return "DiffuseRoughness"; case aiTextureType_AMBIENT_OCCLUSION: return "AmbientOcclusion"; + case aiTextureType_SHEEN: + return "Sheen"; + case aiTextureType_CLEARCOAT: + return "Clearcoat"; + case aiTextureType_TRANSMISSION: + return "Transmission"; case aiTextureType_UNKNOWN: return "Unknown"; default: diff --git a/code/Pbrt/PbrtExporter.cpp b/code/Pbrt/PbrtExporter.cpp index 35b108702..260d90322 100644 --- a/code/Pbrt/PbrtExporter.cpp +++ b/code/Pbrt/PbrtExporter.cpp @@ -105,14 +105,13 @@ void ExportScenePbrt ( } // end of namespace Assimp // Constructor -PbrtExporter::PbrtExporter ( - const aiScene* pScene, IOSystem* pIOSystem, - const std::string path, const std::string file) -: mScene(pScene), - mIOSystem(pIOSystem), - mPath(path), - mFile(file) -{ +PbrtExporter::PbrtExporter( + const aiScene *pScene, IOSystem *pIOSystem, + const std::string &path, const std::string &file) : + mScene(pScene), + mIOSystem(pIOSystem), + mPath(path), + mFile(file) { // Export embedded textures. if (mScene->mNumTextures > 0) if (!mIOSystem->CreateDirectory("textures")) @@ -209,12 +208,12 @@ void PbrtExporter::WriteMetaData() { aiString* value = static_cast(pMetaData->mValues[i].mData); std::string svalue = value->C_Str(); - std::size_t found = svalue.find_first_of("\n"); + std::size_t found = svalue.find_first_of('\n'); mOutput << "\n"; while (found != std::string::npos) { mOutput << "# " << svalue.substr(0, found) << "\n"; svalue = svalue.substr(found + 1); - found = svalue.find_first_of("\n"); + found = svalue.find_first_of('\n'); } mOutput << "# " << svalue << "\n"; break; @@ -595,8 +594,8 @@ void PbrtExporter::WriteMaterial(int m) { } mOutput << "\n"; - auto White = [](aiColor3D c) { return c.r == 1 && c.g == 1 && c.b == 1; }; - auto Black = [](aiColor3D c) { return c.r == 0 && c.g == 0 && c.b == 0; }; + auto White = [](const aiColor3D &c) { return c.r == 1 && c.g == 1 && c.b == 1; }; + auto Black = [](const aiColor3D &c) { return c.r == 0 && c.g == 0 && c.b == 0; }; aiColor3D diffuse, specular, transparency; bool constantDiffuse = (material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse) == AI_SUCCESS && diff --git a/code/Pbrt/PbrtExporter.h b/code/Pbrt/PbrtExporter.h index 167f318fc..e8ff03ccb 100644 --- a/code/Pbrt/PbrtExporter.h +++ b/code/Pbrt/PbrtExporter.h @@ -74,8 +74,8 @@ class PbrtExporter { public: /// Constructor for a specific scene to export - PbrtExporter(const aiScene* pScene, IOSystem* pIOSystem, - const std::string path, const std::string file); + PbrtExporter(const aiScene *pScene, IOSystem *pIOSystem, + const std::string &path, const std::string &file); /// Destructor virtual ~PbrtExporter(); diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index 7e435e556..500032c39 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "EmbedTexturesProcess.h" +#include +#include #include #include "ProcessHelper.h" @@ -48,11 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; -EmbedTexturesProcess::EmbedTexturesProcess() -: BaseProcess() { +EmbedTexturesProcess::EmbedTexturesProcess() : + BaseProcess() { + // empty } EmbedTexturesProcess::~EmbedTexturesProcess() { + // empty } bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const { @@ -62,15 +65,16 @@ bool EmbedTexturesProcess::IsActive(unsigned int pFlags) const { void EmbedTexturesProcess::SetupProperties(const Importer* pImp) { mRootPath = pImp->GetPropertyString("sourceFilePath"); mRootPath = mRootPath.substr(0, mRootPath.find_last_of("\\/") + 1u); + mIOHandler = pImp->GetIOHandler(); } void EmbedTexturesProcess::Execute(aiScene* pScene) { - if (pScene == nullptr || pScene->mRootNode == nullptr) return; + if (pScene == nullptr || pScene->mRootNode == nullptr || mIOHandler == nullptr){ + return; + } aiString path; - uint32_t embeddedTexturesCount = 0u; - for (auto matId = 0u; matId < pScene->mNumMaterials; ++matId) { auto material = pScene->mMaterials[matId]; @@ -96,32 +100,36 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { ASSIMP_LOG_INFO("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." ); } -bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { +bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path) const { std::streampos imageSize = 0; std::string imagePath = path; // Test path directly - std::ifstream file(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == std::streampos(-1)) { + if (!mIOHandler->Exists(imagePath)) { ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); // Test path in root path imagePath = mRootPath + path; - file.open(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == std::streampos(-1)) { + if (!mIOHandler->Exists(imagePath)) { // Test path basename in root path imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); - file.open(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == std::streampos(-1)) { + if (!mIOHandler->Exists(imagePath)) { ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, "."); return false; } } } + IOStream* pFile = mIOHandler->Open(imagePath); + if (pFile == nullptr) { + ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, "."); + return false; + } + imageSize = pFile->FileSize(); aiTexel* imageContent = new aiTexel[ 1ul + static_cast( imageSize ) / sizeof(aiTexel)]; - file.seekg(0, std::ios::beg); - file.read(reinterpret_cast(imageContent), imageSize); + pFile->Seek(0, aiOrigin_SET); + pFile->Read(reinterpret_cast(imageContent), imageSize, 1); + mIOHandler->Close(pFile); // Enlarging the textures table unsigned int textureId = pScene->mNumTextures++; diff --git a/code/PostProcessing/EmbedTexturesProcess.h b/code/PostProcessing/EmbedTexturesProcess.h index 90970937a..b33968850 100644 --- a/code/PostProcessing/EmbedTexturesProcess.h +++ b/code/PostProcessing/EmbedTexturesProcess.h @@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiNode; +class IOSystem; + namespace Assimp { /** @@ -76,10 +78,11 @@ public: private: // Resolve the path and add the file content to the scene as a texture. - bool addTexture(aiScene* pScene, std::string path) const; + bool addTexture(aiScene *pScene, const std::string &path) const; private: std::string mRootPath; + IOSystem* mIOHandler = nullptr; }; } // namespace Assimp diff --git a/contrib/draco/.ruby-version b/contrib/draco/.ruby-version deleted file mode 100644 index 276cbf9e2..000000000 --- a/contrib/draco/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.3.0 diff --git a/contrib/draco/.travis.yml b/contrib/draco/.travis.yml deleted file mode 100644 index e9ef7123f..000000000 --- a/contrib/draco/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -cache: ccache -language: cpp -matrix: - include: - - os: linux - dist: xenial - compiler: clang - - os: linux - dist: xenial - compiler: gcc - - os: osx - compiler: clang - -addons: - apt: - packages: - - cmake - -script: - # Output version info for compilers, cmake, and make - - ${CC} -v - - ${CXX} -v - - cmake --version - - make --version - # Clone googletest - - pushd .. && git clone https://github.com/google/googletest.git && popd - # Configure and build - - mkdir _travis_build && cd _travis_build - - cmake -G "Unix Makefiles" -DENABLE_TESTS=ON .. - - make -j10 - - ./draco_tests diff --git a/contrib/draco/CMakeLists.txt b/contrib/draco/CMakeLists.txt index 3da2c664a..5526e7f60 100644 --- a/contrib/draco/CMakeLists.txt +++ b/contrib/draco/CMakeLists.txt @@ -804,7 +804,7 @@ else() draco_points_enc) # Library targets that consume the object collections. - if(MSVC OR WIN32) + if(MSVC) # In order to produce a DLL and import library the Windows tools require # that the exported symbols are part of the DLL target. The unfortunate side # effect of this is that a single configuration cannot output both the @@ -889,9 +889,6 @@ else() # For Mac, we need to build a .bundle for the unity plugin. if(APPLE) set_target_properties(dracodec_unity PROPERTIES BUNDLE true) - elseif(NOT unity_decoder_lib_type STREQUAL STATIC) - set_target_properties(dracodec_unity - PROPERTIES SOVERSION ${DRACO_SOVERSION}) endif() endif() @@ -916,9 +913,6 @@ else() # For Mac, we need to build a .bundle for the plugin. if(APPLE) set_target_properties(draco_maya_wrapper PROPERTIES BUNDLE true) - else() - set_target_properties(draco_maya_wrapper - PROPERTIES SOVERSION ${DRACO_SOVERSION}) endif() endif() diff --git a/contrib/draco/README.md b/contrib/draco/README.md index add66edcb..0d980b387 100644 --- a/contrib/draco/README.md +++ b/contrib/draco/README.md @@ -2,16 +2,16 @@

-![Build Status: master](https://travis-ci.org/google/draco.svg?branch=master) +[![Build Status](https://github.com/google/draco/workflows/Build/badge.svg)](https://github.com/google/draco/actions?query=workflow%3ABuild) News ======= ### Version 1.4.1 release -* Using the versioned gstatic.com WASM and Javascript decoders is now +* Using the versioned www.gstatic.com WASM and Javascript decoders is now recommended. To use v1.4.1, use this URL: * https://www.gstatic.com/draco/versioned/decoders/1.4.1/* * Replace the * with the files to load. E.g. - * https://gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js + * https://www.gstatic.com/draco/versioned/decoders/1.4.1/draco_decoder.js * This works with the v1.3.6 and v1.4.0 releases, and will work with future Draco releases. * Bug fixes diff --git a/contrib/draco/cmake/draco_build_definitions.cmake b/contrib/draco/cmake/draco_build_definitions.cmake index c1ada6206..f7354c15f 100644 --- a/contrib/draco/cmake/draco_build_definitions.cmake +++ b/contrib/draco/cmake/draco_build_definitions.cmake @@ -6,7 +6,7 @@ set(DRACO_CMAKE_DRACO_BUILD_DEFINITIONS_CMAKE_ 1) # Utility for controlling the main draco library dependency. This changes in # shared builds, and when an optional target requires a shared library build. macro(set_draco_target) - if(MSVC OR WIN32) + if(MSVC) set(draco_dependency draco) set(draco_plugin_dependency ${draco_dependency}) else() @@ -63,6 +63,11 @@ macro(draco_set_build_definitions) if(BUILD_SHARED_LIBS) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) endif() + else() + if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + # Ensure 64-bit platforms can support large files. + list(APPEND draco_defines "_LARGEFILE_SOURCE" "_FILE_OFFSET_BITS=64") + endif() endif() if(ANDROID) @@ -114,4 +119,6 @@ macro(draco_set_build_definitions) draco_check_emscripten_environment() draco_get_required_emscripten_flags(FLAG_LIST_VAR draco_base_cxx_flags) endif() + + draco_configure_sanitizer() endmacro() diff --git a/contrib/draco/cmake/draco_features.cmake b/contrib/draco/cmake/draco_features.cmake deleted file mode 100644 index be444bf24..000000000 --- a/contrib/draco/cmake/draco_features.cmake +++ /dev/null @@ -1,63 +0,0 @@ -if(DRACO_CMAKE_DRACO_FEATURES_CMAKE_) - return() -endif() -set(DRACO_CMAKE_DRACO_FEATURES_CMAKE_ 1) - -set(draco_features_file_name "${draco_build_dir}/draco/draco_features.h") -set(draco_features_list) - -# Macro that handles tracking of Draco preprocessor symbols for the purpose of -# producing draco_features.h. -# -# draco_enable_feature(FEATURE [TARGETS ]) FEATURE -# is required. It should be a Draco preprocessor symbol. TARGETS is optional. It -# can be one or more draco targets. -# -# When the TARGETS argument is not present the preproc symbol is added to -# draco_features.h. When it is draco_features.h is unchanged, and -# target_compile_options() is called for each target specified. -macro(draco_enable_feature) - set(def_flags) - set(def_single_arg_opts FEATURE) - set(def_multi_arg_opts TARGETS) - cmake_parse_arguments(DEF "${def_flags}" "${def_single_arg_opts}" - "${def_multi_arg_opts}" ${ARGN}) - if("${DEF_FEATURE}" STREQUAL "") - message(FATAL_ERROR "Empty FEATURE passed to draco_enable_feature().") - endif() - - # Do nothing/return early if $DEF_FEATURE is already in the list. - list(FIND draco_features_list ${DEF_FEATURE} df_index) - if(NOT df_index EQUAL -1) - return() - endif() - - list(LENGTH DEF_TARGETS df_targets_list_length) - if(${df_targets_list_length} EQUAL 0) - list(APPEND draco_features_list ${DEF_FEATURE}) - else() - foreach(target ${DEF_TARGETS}) - target_compile_definitions(${target} PRIVATE ${DEF_FEATURE}) - endforeach() - endif() -endmacro() - -# Function for generating draco_features.h. -function(draco_generate_features_h) - file(WRITE "${draco_features_file_name}.new" - "// GENERATED FILE -- DO NOT EDIT\n\n" "#ifndef DRACO_FEATURES_H_\n" - "#define DRACO_FEATURES_H_\n\n") - - foreach(feature ${draco_features_list}) - file(APPEND "${draco_features_file_name}.new" "#define ${feature}\n") - endforeach() - - file(APPEND "${draco_features_file_name}.new" - "\n#endif // DRACO_FEATURES_H_") - - # Will replace ${draco_features_file_name} only if the file content has - # changed. This prevents forced Draco rebuilds after CMake runs. - configure_file("${draco_features_file_name}.new" - "${draco_features_file_name}") - file(REMOVE "${draco_features_file_name}.new") -endfunction() diff --git a/contrib/draco/cmake/draco_flags.cmake b/contrib/draco/cmake/draco_flags.cmake index cb9d489e6..0397859a4 100644 --- a/contrib/draco/cmake/draco_flags.cmake +++ b/contrib/draco/cmake/draco_flags.cmake @@ -80,6 +80,12 @@ macro(draco_test_cxx_flag) # Run the actual compile test. unset(draco_all_cxx_flags_pass CACHE) message("--- Running combined CXX flags test, flags: ${all_cxx_flags}") + + # check_cxx_compiler_flag() requires that the flags are a string. When flags + # are passed as a list it will remove the list separators, and attempt to run + # a compile command using list entries concatenated together as a single + # argument. Avoid the problem by forcing the argument to be a string. + draco_set_and_stringify(SOURCE_VARS all_cxx_flags DEST all_cxx_flags) check_cxx_compiler_flag("${all_cxx_flags}" draco_all_cxx_flags_pass) if(cxx_test_FLAG_REQUIRED AND NOT draco_all_cxx_flags_pass) @@ -194,6 +200,9 @@ macro(draco_test_exe_linker_flag) else() unset(CMAKE_EXE_LINKER_FLAGS) endif() + + list(APPEND DRACO_EXE_LINKER_FLAGS ${${link_FLAG_LIST_VAR_NAME}}) + list(REMOVE_DUPLICATES DRACO_EXE_LINKER_FLAGS) endmacro() # Runs the draco compiler tests. This macro builds up the list of list var(s) diff --git a/contrib/draco/cmake/draco_install.cmake b/contrib/draco/cmake/draco_install.cmake index 5c63ecb4a..09bfb591d 100644 --- a/contrib/draco/cmake/draco_install.cmake +++ b/contrib/draco/cmake/draco_install.cmake @@ -55,7 +55,7 @@ macro(draco_setup_install_target) install(TARGETS draco_encoder DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}") - if(WIN32) + if(MSVC) install(TARGETS draco DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") else() diff --git a/contrib/draco/cmake/draco_sanitizer.cmake b/contrib/draco/cmake/draco_sanitizer.cmake index ca8e23176..d2e41a6cb 100644 --- a/contrib/draco/cmake/draco_sanitizer.cmake +++ b/contrib/draco/cmake/draco_sanitizer.cmake @@ -5,28 +5,28 @@ set(DRACO_CMAKE_DRACO_SANITIZER_CMAKE_ 1) # Handles the details of enabling sanitizers. macro(draco_configure_sanitizer) - if(DRACO_SANITIZE AND NOT MSVC) + if(DRACO_SANITIZE AND NOT EMSCRIPTEN AND NOT MSVC) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(DRACO_SANITIZE MATCHES "cfi") - list(APPEND DRACO_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi") - list(APPEND DRACO_EXE_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi" + list(APPEND SAN_CXX_FLAGS "-flto" "-fno-sanitize-trap=cfi") + list(APPEND SAN_LINKER_FLAGS "-flto" "-fno-sanitize-trap=cfi" "-fuse-ld=gold") endif() if(${CMAKE_SIZEOF_VOID_P} EQUAL 4 AND DRACO_SANITIZE MATCHES "integer|undefined") - list(APPEND DRACO_EXE_LINKER_FLAGS "--rtlib=compiler-rt" "-lgcc_s") + list(APPEND SAN_LINKER_FLAGS "--rtlib=compiler-rt" "-lgcc_s") endif() endif() - list(APPEND DRACO_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}") - list(APPEND DRACO_EXE_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}") + list(APPEND SAN_CXX_FLAGS "-fsanitize=${DRACO_SANITIZE}") + list(APPEND SAN_LINKER_FLAGS "-fsanitize=${DRACO_SANITIZE}") # Make sanitizer callstacks accurate. - list(APPEND DRACO_CXX_FLAGS "-fno-omit-frame-pointer" - "-fno-optimize-sibling-calls") + list(APPEND SAN_CXX_FLAGS "-fno-omit-frame-pointer") + list(APPEND SAN_CXX_FLAGS "-fno-optimize-sibling-calls") - draco_test_cxx_flag(FLAG_LIST_VAR_NAMES DRACO_CXX_FLAGS FLAG_REQUIRED) - draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME DRACO_EXE_LINKER_FLAGS) + draco_test_cxx_flag(FLAG_LIST_VAR_NAMES SAN_CXX_FLAGS FLAG_REQUIRED) + draco_test_exe_linker_flag(FLAG_LIST_VAR_NAME SAN_LINKER_FLAGS) endif() endmacro() diff --git a/contrib/draco/cmake/draco_targets.cmake b/contrib/draco/cmake/draco_targets.cmake index 6dfa6a0c4..0456c4d7b 100644 --- a/contrib/draco/cmake/draco_targets.cmake +++ b/contrib/draco/cmake/draco_targets.cmake @@ -87,6 +87,7 @@ macro(draco_add_executable) endif() add_executable(${exe_NAME} ${exe_SOURCES}) + set_target_properties(${exe_NAME} PROPERTIES VERSION ${DRACO_VERSION}) if(exe_OUTPUT_NAME) set_target_properties(${exe_NAME} PROPERTIES OUTPUT_NAME ${exe_OUTPUT_NAME}) @@ -109,10 +110,11 @@ macro(draco_add_executable) if(exe_LINK_FLAGS OR DRACO_EXE_LINKER_FLAGS) if(${CMAKE_VERSION} VERSION_LESS "3.13") - set(link_flags ${exe_LINK_FLAGS} ${DRACO_EXE_LINKER_FLAGS}) + list(APPEND exe_LINK_FLAGS "${DRACO_EXE_LINKER_FLAGS}") + # LINK_FLAGS is managed as a string. + draco_set_and_stringify(SOURCE "${exe_LINK_FLAGS}" DEST exe_LINK_FLAGS) set_target_properties(${exe_NAME} - PROPERTIES LINK_FLAGS ${exe_LINK_FLAGS} - ${DRACO_EXE_LINKER_FLAGS}) + PROPERTIES LINK_FLAGS "${exe_LINK_FLAGS}") else() target_link_options(${exe_NAME} PRIVATE ${exe_LINK_FLAGS} ${DRACO_EXE_LINKER_FLAGS}) @@ -130,7 +132,7 @@ macro(draco_add_executable) endif() if(BUILD_SHARED_LIBS AND (MSVC OR WIN32)) - target_compile_definitions(${lib_NAME} PRIVATE "DRACO_BUILDING_DLL=0") + target_compile_definitions(${exe_NAME} PRIVATE "DRACO_BUILDING_DLL=0") endif() if(exe_LIB_DEPS) @@ -163,8 +165,8 @@ endmacro() # cmake-format: off # - OUTPUT_NAME: Override output file basename. Target basename defaults to # NAME. OUTPUT_NAME is ignored when BUILD_SHARED_LIBS is enabled and CMake -# is generating a build for which MSVC or WIN32 are true. This is to avoid -# output basename collisions with DLL import libraries. +# is generating a build for which MSVC is true. This is to avoid output +# basename collisions with DLL import libraries. # - TEST: Flag. Presence means treat library as a test. # - DEFINES: List of preprocessor macro definitions. # - INCLUDES: list of include directories for the target. @@ -259,7 +261,7 @@ macro(draco_add_library) endif() if(lib_OUTPUT_NAME) - if(NOT (BUILD_SHARED_LIBS AND (MSVC OR WIN32))) + if(NOT (BUILD_SHARED_LIBS AND MSVC)) set_target_properties(${lib_NAME} PROPERTIES OUTPUT_NAME ${lib_OUTPUT_NAME}) endif() @@ -318,8 +320,12 @@ macro(draco_add_library) set_target_properties(${lib_NAME} PROPERTIES PREFIX "") endif() - if(lib_TYPE STREQUAL SHARED AND NOT MSVC) - set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION}) + # VERSION and SOVERSION as necessary + if(NOT lib_TYPE STREQUAL STATIC AND NOT lib_TYPE STREQUAL MODULE) + set_target_properties(${lib_NAME} PROPERTIES VERSION ${DRACO_VERSION}) + if(NOT MSVC) + set_target_properties(${lib_NAME} PROPERTIES SOVERSION ${DRACO_SOVERSION}) + endif() endif() if(BUILD_SHARED_LIBS AND (MSVC OR WIN32)) diff --git a/contrib/draco/src/draco/core/cycle_timer.cc b/contrib/draco/src/draco/core/cycle_timer.cc index 94b4b28b2..58df4df77 100644 --- a/contrib/draco/src/draco/core/cycle_timer.cc +++ b/contrib/draco/src/draco/core/cycle_timer.cc @@ -17,31 +17,31 @@ namespace draco { void DracoTimer::Start() { #ifdef _WIN32 - QueryPerformanceCounter(&tv_start); + QueryPerformanceCounter(&tv_start_); #else - gettimeofday(&tv_start, nullptr); + gettimeofday(&tv_start_, nullptr); #endif } void DracoTimer::Stop() { #ifdef _WIN32 - QueryPerformanceCounter(&tv_end); + QueryPerformanceCounter(&tv_end_); #else - gettimeofday(&tv_end, nullptr); + gettimeofday(&tv_end_, nullptr); #endif } int64_t DracoTimer::GetInMs() { #ifdef _WIN32 LARGE_INTEGER elapsed = {0}; - elapsed.QuadPart = tv_end.QuadPart - tv_start.QuadPart; + elapsed.QuadPart = tv_end_.QuadPart - tv_start_.QuadPart; LARGE_INTEGER frequency = {0}; QueryPerformanceFrequency(&frequency); return elapsed.QuadPart * 1000 / frequency.QuadPart; #else - const int64_t seconds = (tv_end.tv_sec - tv_start.tv_sec) * 1000; - const int64_t milliseconds = (tv_end.tv_usec - tv_start.tv_usec) / 1000; + const int64_t seconds = (tv_end_.tv_sec - tv_start_.tv_sec) * 1000; + const int64_t milliseconds = (tv_end_.tv_usec - tv_start_.tv_usec) / 1000; return seconds + milliseconds; #endif } diff --git a/contrib/draco/src/draco/core/cycle_timer.h b/contrib/draco/src/draco/core/cycle_timer.h index 172f1c2e9..f480cc9d3 100644 --- a/contrib/draco/src/draco/core/cycle_timer.h +++ b/contrib/draco/src/draco/core/cycle_timer.h @@ -20,9 +20,10 @@ #define WIN32_LEAN_AND_MEAN #endif #include -typedef LARGE_INTEGER timeval; +typedef LARGE_INTEGER DracoTimeVal; #else #include +typedef timeval DracoTimeVal; #endif #include @@ -39,8 +40,8 @@ class DracoTimer { int64_t GetInMs(); private: - timeval tv_start; - timeval tv_end; + DracoTimeVal tv_start_; + DracoTimeVal tv_end_; }; typedef DracoTimer CycleTimer; diff --git a/contrib/draco/src/draco/io/parser_utils.cc b/contrib/draco/src/draco/io/parser_utils.cc index 4f95f6f84..12afacff6 100644 --- a/contrib/draco/src/draco/io/parser_utils.cc +++ b/contrib/draco/src/draco/io/parser_utils.cc @@ -18,6 +18,7 @@ #include #include #include +#include namespace draco { namespace parser { @@ -252,7 +253,7 @@ DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) { std::string ToLower(const std::string &str) { std::string out; - std::transform(str.begin(), str.end(), std::back_inserter(out), [](unsigned char c){return tolower(c);}); + std::transform(str.begin(), str.end(), std::back_inserter(out), tolower); return out; } diff --git a/contrib/draco/src/draco/io/ply_reader.cc b/contrib/draco/src/draco/io/ply_reader.cc index cb32df225..ea7f2689a 100644 --- a/contrib/draco/src/draco/io/ply_reader.cc +++ b/contrib/draco/src/draco/io/ply_reader.cc @@ -268,14 +268,14 @@ std::vector PlyReader::SplitWords(const std::string &line) { while ((end = line.find_first_of(" \t\n\v\f\r", start)) != std::string::npos) { const std::string word(line.substr(start, end - start)); - if (!std::all_of(word.begin(), word.end(), [](unsigned char c){return isspace(c);})) { + if (!std::all_of(word.begin(), word.end(), isspace)) { output.push_back(word); } start = end + 1; } const std::string last_word(line.substr(start)); - if (!std::all_of(last_word.begin(), last_word.end(), [](unsigned char c){return isspace(c);})) { + if (!std::all_of(last_word.begin(), last_word.end(), isspace)) { output.push_back(last_word); } return output; diff --git a/contrib/draco/src/draco/io/stdio_file_reader.cc b/contrib/draco/src/draco/io/stdio_file_reader.cc index 560c3e9e8..a99c96f8f 100644 --- a/contrib/draco/src/draco/io/stdio_file_reader.cc +++ b/contrib/draco/src/draco/io/stdio_file_reader.cc @@ -87,7 +87,14 @@ size_t StdioFileReader::GetFileSize() { return false; } +#if _FILE_OFFSET_BITS == 64 + const size_t file_size = static_cast(ftello(file_)); +#elif defined _WIN64 + const size_t file_size = static_cast(_ftelli64(file_)); +#else const size_t file_size = static_cast(ftell(file_)); +#endif + rewind(file_); return file_size; diff --git a/contrib/poly2tri/poly2tri/sweep/sweep.cc b/contrib/poly2tri/poly2tri/sweep/sweep.cc index 23aeb6b57..8e3d794c0 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep.cc +++ b/contrib/poly2tri/poly2tri/sweep/sweep.cc @@ -129,7 +129,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl EdgeEvent( tcx, ep, *p1, triangle, *p1 ); } else { // ASSIMP_CHANGE (aramis_acg) - std::runtime_error("EdgeEvent - collinear points not supported"); + throw std::runtime_error("EdgeEvent - collinear points not supported"); } return; } diff --git a/include/assimp/material.h b/include/assimp/material.h index 08c0491c0..f0207c6de 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -144,7 +144,7 @@ enum aiTextureMapMode { enum aiTextureMapping { /** The mapping coordinates are taken from an UV channel. * - * The #AI_MATKEY_UVWSRC key specifies from which UV channel + * #AI_MATKEY_UVWSRC property specifies from which UV channel * the texture coordinates are to be taken from (remember, * meshes can have more than one UV channel). */ @@ -202,11 +202,15 @@ enum aiTextureType { /** The texture is combined with the result of the diffuse * lighting equation. + * OR + * PBR Specular/Glossiness */ aiTextureType_DIFFUSE = 1, /** The texture is combined with the result of the specular * lighting equation. + * OR + * PBR Specular/Glossiness */ aiTextureType_SPECULAR = 2, @@ -288,6 +292,32 @@ enum aiTextureType { aiTextureType_DIFFUSE_ROUGHNESS = 16, aiTextureType_AMBIENT_OCCLUSION = 17, + /** PBR Material Modifiers + * Some modern renderers have further PBR modifiers that may be overlaid + * on top of the 'base' PBR materials for additional realism. + * These use multiple texture maps, so only the base type is directly defined + */ + + /** Sheen + * Generally used to simulate textiles that are covered in a layer of microfibers + * eg velvet + * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen + */ + aiTextureType_SHEEN = 19, + + /** Clearcoat + * Simulates a layer of 'polish' or 'laquer' layered on top of a PBR substrate + * https://autodesk.github.io/standard-surface/#closures/coating + * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat + */ + aiTextureType_CLEARCOAT = 20, + + /** Transmission + * Simulates transmission through the surface + * May include further information such as wall thickness + */ + aiTextureType_TRANSMISSION = 21, + /** Unknown texture * * A texture reference that does not match any of the definitions @@ -309,7 +339,9 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in); // --------------------------------------------------------------------------- /** @brief Defines all shading models supported by the library - * + * + * Property: #AI_MATKEY_SHADING_MODEL + * * The list of shading modes has been taken from Blender. * See Blender documentation for more information. The API does * not distinguish between "specular" and "diffuse" shaders (thus the @@ -318,6 +350,7 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in); * Again, this value is just a hint. Assimp tries to select the shader whose * most common implementation matches the original rendering results of the * 3D modeler which wrote a particular model as closely as possible. + * */ enum aiShadingMode { /** Flat shading. Shading is done on per-face base, @@ -364,13 +397,28 @@ enum aiShadingMode { aiShadingMode_CookTorrance = 0x8, /** No shading at all. Constant light influence of 1.0. + * Also known as "Unlit" */ aiShadingMode_NoShading = 0x9, + aiShadingMode_Unlit = aiShadingMode_NoShading, // Alias /** Fresnel shading */ aiShadingMode_Fresnel = 0xa, + /** Physically-Based Rendering (PBR) shading using + * Bidirectional scattering/reflectance distribution function (BSDF/BRDF) + * There are multiple methods under this banner, and model files may provide + * data for more than one PBR-BRDF method. + * Applications should use the set of provided properties to determine which + * of their preferred PBR rendering methods are likely to be available + * eg: + * - If AI_MATKEY_METALLIC_FACTOR is set, then a Metallic/Roughness is available + * - If AI_MATKEY_GLOSSINESS_FACTOR is set, then a Specular/Glossiness is available + * Note that some PBR methods allow layering of techniques + */ + aiShadingMode_PBR_BRDF = 0xb, + #ifndef SWIG _aiShadingMode_Force32Bit = INT_MAX #endif @@ -922,12 +970,66 @@ extern "C" { // --------------------------------------------------------------------------- // PBR material support +// -------------------- +// Properties defining PBR rendering techniques #define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0 + +// Metallic/Roughness Workflow +// --------------------------- +// Base RGBA color factor. Will be multiplied by final base color texture values if extant +// Note: Importers may choose to copy this into AI_MATKEY_COLOR_DIFFUSE for compatibility +// with renderers and formats that do not support Metallic/Roughness PBR #define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0 +#define AI_MATKEY_BASE_COLOR_TEXTURE aiTextureType_BASE_COLOR, 0 #define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0 +// Metallic factor. 0.0 = Full Dielectric, 1.0 = Full Metal #define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0 +#define AI_MATKEY_METALLIC_TEXTURE aiTextureType_METALNESS, 0 #define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0 +// Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough #define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0 +#define AI_MATKEY_ROUGHNESS_TEXTURE aiTextureType_DIFFUSE_ROUGHNESS, 0 + +// Specular/Glossiness Workflow +// --------------------------- +// Diffuse/Albedo Color. Note: Pure Metals have a diffuse of {0,0,0} +// AI_MATKEY_COLOR_DIFFUSE +// Specular Color. +// Note: Metallic/Roughness may also have a Specular Color +// AI_MATKEY_COLOR_SPECULAR +#define AI_MATKEY_SPECULAR_FACTOR "$mat.specularFactor", 0, 0 +// Glossiness factor. 0.0 = Completely Rough, 1.0 = Perfectly Smooth +#define AI_MATKEY_GLOSSINESS_FACTOR "$mat.glossinessFactor", 0, 0 + +// Sheen +// ----- +// Sheen base RGB color. Default {0,0,0} +#define AI_MATKEY_SHEEN_COLOR_FACTOR "$clr.sheen.factor", 0, 0 +// Sheen Roughness Factor. +#define AI_MATKEY_SHEEN_ROUGHNESS_FACTOR "$mat.sheen.roughnessFactor", 0, 0 +#define AI_MATKEY_SHEEN_COLOR_TEXTURE aiTextureType_SHEEN, 0 +#define AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE aiTextureType_SHEEN, 1 + +// Clearcoat +// --------- +// Clearcoat layer intensity. 0.0 = none (disabled) +#define AI_MATKEY_CLEARCOAT_FACTOR "$mat.clearcoat.factor", 0, 0 +#define AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR "$mat.clearcoat.roughnessFactor", 0, 0 +#define AI_MATKEY_CLEARCOAT_TEXTURE aiTextureType_CLEARCOAT, 0 +#define AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_CLEARCOAT, 1 +#define AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE aiTextureType_CLEARCOAT, 2 + +// Transmission +// ------------ +// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission +// Base percentage of light transmitted through the surface. 0.0 = Opaque, 1.0 = Fully transparent +#define AI_MATKEY_TRANSMISSION_FACTOR "$mat.transmission.factor", 0, 0 +// Texture defining percentage of light transmitted through the surface. +// Multiplied by AI_MATKEY_TRANSMISSION_FACTOR +#define AI_MATKEY_TRANSMISSION_TEXTURE aiTextureType_TRANSMISSION, 0 + +// Emissive +// -------- #define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0 #define AI_MATKEY_EMISSIVE_INTENSITY "$mat.emissiveIntensity", 0, 0 #define AI_MATKEY_USE_AO_MAP "$mat.useAOMap", 0, 0 @@ -1397,8 +1499,6 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray( ai_real *pOut, unsigned int *pMax); -#ifdef __cplusplus - // --------------------------------------------------------------------------- /** @brief Retrieve a single float property with a specific key from the material. * @@ -1418,7 +1518,7 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray( * @return Specifies whether the key has been found. If not, the output * float remains unmodified.*/ // --------------------------------------------------------------------------- -inline aiReturn aiGetMaterialFloat(const aiMaterial *pMat, +inline aiReturn aiGetMaterialFloat(const C_STRUCT aiMaterial *pMat, const char *pKey, unsigned int type, unsigned int index, @@ -1426,14 +1526,6 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial *pMat, return aiGetMaterialFloatArray(pMat, pKey, type, index, pOut, (unsigned int *)0x0); } -#else - -// Use our friend, the C preprocessor -#define aiGetMaterialFloat (pMat, type, index, pKey, pOut) \ - aiGetMaterialFloatArray(pMat, type, index, pKey, pOut, NULL) - -#endif //!__cplusplus - // --------------------------------------------------------------------------- /** @brief Retrieve an array of integer values with a specific key * from a material @@ -1446,8 +1538,6 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial * int *pOut, unsigned int *pMax); -#ifdef __cplusplus - // --------------------------------------------------------------------------- /** @brief Retrieve an integer property with a specific key from a material * @@ -1461,14 +1551,6 @@ inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial *pMat, return aiGetMaterialIntegerArray(pMat, pKey, type, index, pOut, (unsigned int *)0x0); } -#else - -// use our friend, the C preprocessor -#define aiGetMaterialInteger (pMat, type, index, pKey, pOut) \ - aiGetMaterialIntegerArray(pMat, type, index, pKey, pOut, NULL) - -#endif //!__cplusplus - // --------------------------------------------------------------------------- /** @brief Retrieve a color value from the material property table * diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 551a9aba4..57fedfbfc 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -432,7 +432,7 @@ struct aiMetadata { /// Check whether there is a metadata entry for the given key. /// \param [in] Key - the key value value to check for. - inline bool HasKey(const char *key) { + inline bool HasKey(const char *key) const { if (nullptr == key) { return false; } diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h index 2e41b8b6d..93e7e3095 100644 --- a/include/assimp/pbrmaterial.h +++ b/include/assimp/pbrmaterial.h @@ -50,32 +50,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # pragma GCC system_header #endif -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 -#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_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 +//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 +//#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_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 #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_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 -#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1 -#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5 +//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 +//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 +//#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1 +//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5 -#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" +//#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" @@ -83,7 +83,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale" #define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength" -#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N +//#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _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 diff --git a/include/assimp/scene.h b/include/assimp/scene.h index 769499a27..522ddc6dc 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2021, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -397,22 +395,35 @@ struct aiScene //! Returns an embedded texture const aiTexture* GetEmbeddedTexture(const char* filename) const { + return GetEmbeddedTextureAndIndex(filename).first; + } + + //! Returns an embedded texture and its index + std::pair GetEmbeddedTextureAndIndex(const char* filename) const { + if(nullptr==filename) { + return std::make_pair(nullptr, -1); + } // lookup using texture ID (if referenced like: "*1", "*2", etc.) if ('*' == *filename) { int index = std::atoi(filename + 1); - if (0 > index || mNumTextures <= static_cast(index)) - return nullptr; - return mTextures[index]; + if (0 > index || mNumTextures <= static_cast(index)) { + return std::make_pair(nullptr, -1); + } + return std::make_pair(mTextures[index], index); } // lookup using filename const char* shortFilename = GetShortFilename(filename); + if (nullptr == shortFilename) { + return std::make_pair(nullptr, -1); + } + for (unsigned int i = 0; i < mNumTextures; i++) { const char* shortTextureFilename = GetShortFilename(mTextures[i]->mFilename.C_Str()); if (strcmp(shortTextureFilename, shortFilename) == 0) { - return mTextures[i]; + return std::make_pair(mTextures[i], i); } } - return nullptr; + return std::make_pair(nullptr, -1); } #endif // __cplusplus diff --git a/test/models/glTF2/ClearCoat-glTF/ClearCoatLabels.png b/test/models/glTF2/ClearCoat-glTF/ClearCoatLabels.png new file mode 100644 index 000000000..d47f2f5e1 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/ClearCoatLabels.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.bin b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.bin new file mode 100644 index 000000000..e7c6a93a4 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.bin differ diff --git a/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.gltf b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.gltf new file mode 100644 index 000000000..ae12bfc11 --- /dev/null +++ b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.gltf @@ -0,0 +1,1669 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v1.2.8 with hand-edits for clearcoat", + "version" : "2.0" + }, + "extensionsUsed": [ + "KHR_materials_clearcoat" + ], + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 3, + 7, + 11, + 15, + 19, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 1, + "name" : "ClearCoatSample" + }, + { + "mesh" : 2, + "name" : "CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 0, + 1, + 2 + ], + "name" : "R0_SimpleCoatTest", + "translation" : [ + 0, + 5.25, + 0 + ] + }, + { + "mesh" : 3, + "name" : "R1_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 4, + "name" : "R1_ClearCoatSample" + }, + { + "mesh" : 5, + "name" : "R1_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 4, + 5, + 6 + ], + "name" : "R1_PartialCoatTest", + "translation" : [ + 0, + 3.1500000953674316, + 0 + ] + }, + { + "mesh" : 6, + "name" : "R2_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 7, + "name" : "R2_ClearCoatSample" + }, + { + "mesh" : 8, + "name" : "R2_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 8, + 9, + 10 + ], + "name" : "R2_RoughnessVariations", + "translation" : [ + 0, + 1.0499999523162842, + 0 + ] + }, + { + "mesh" : 9, + "name" : "R3_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 10, + "name" : "R3_ClearCoatSample" + }, + { + "mesh" : 11, + "name" : "R3_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 12, + 13, + 14 + ], + "name" : "R3_BaseNormals", + "translation" : [ + 0, + -1.0499999523162842, + 0 + ] + }, + { + "mesh" : 12, + "name" : "R4_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 13, + "name" : "R4_ClearCoatSample" + }, + { + "mesh" : 14, + "name" : "R4_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 16, + 17, + 18 + ], + "name" : "R4_CoatNormals", + "translation" : [ + 0, + -5.25, + 0 + ] + }, + { + "mesh" : 15, + "name" : "R5_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 16, + "name" : "R5_ClearCoatSample" + }, + { + "mesh" : 17, + "name" : "R5_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 20, + 21, + 22 + ], + "name" : "R5_SharedNormals", + "translation" : [ + 0, + -3.1500000953674316, + 0 + ] + }, + { + "mesh" : 18, + "name" : "X2_Label_CoatingOnly", + "translation" : [ + 2.0712804794311523, + 6.619500160217285, + 0 + ] + }, + { + "mesh" : 19, + "name" : "Y0_Label_SimpleCoating", + "translation" : [ + -5.3578033447265625, + 5.25, + 0 + ] + }, + { + "mesh" : 20, + "name" : "Y1_Label_PartialCoating", + "translation" : [ + -5.3578033447265625, + 3.1673200130462646, + 0 + ] + }, + { + "mesh" : 21, + "name" : "Y2_Label_Roughness", + "translation" : [ + -5.3578033447265625, + 1.1383899450302124, + 0 + ] + }, + { + "mesh" : 22, + "name" : "Y3_Label_BaseNormals", + "translation" : [ + -5.3578033447265625, + -1.099429965019226, + 0 + ] + }, + { + "mesh" : 23, + "name" : "Y4_Label_CoatNormals", + "translation" : [ + -5.3578033447265625, + -5.252500057220459, + 0 + ] + }, + { + "mesh" : 24, + "name" : "Y5_Label_SharedNormals", + "translation" : [ + -5.3578033447265625, + -3.1963000297546387, + 0 + ] + }, + { + "mesh" : 25, + "name" : "X0_Label_BaseLayer", + "translation" : [ + -2.087031602859497, + 6.616230010986328, + 0 + ] + }, + { + "mesh" : 26, + "name" : "X1_Label_Coated", + "translation" : [ + 0, + 6.614150047302246, + 0 + ] + } + ], + "materials" : [ + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Simple_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.5, + 0.019999999552965164, + 0.009999999776482582, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Simple_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.5, + 0.019999999552965164, + 0.009999999776482582, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03 + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Simple_Coating", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Partial_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Partial_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03, + "clearcoatTexture": { + "index": 0, + "texCoord": 0 + } + } + } + }, + { + "alphaMode" : "BLEND", + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Partial_Coating", + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 1, + "texCoord" : 0 + }, + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "RoughVariations_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.6000000238418579 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "RoughVariations_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.6000000238418579 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 1, + "clearcoatRoughnessTexture": { + "index": 2, + "texCoord": 0 + } + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "RoughVariations_Coating", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "metallicRoughnessTexture" : { + "index" : 2, + "texCoord" : 0 + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "BaseNorm_Base", + "normalTexture" : { + "index" : 3, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "BaseNorm_Coated", + "normalTexture" : { + "index" : 4, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012848637998104095, + 0.021861059591174126, + 0.11068868637084961, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03 + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "BaseNorm_Coating", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "CoatNorm_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "CoatNorm_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03, + "clearcoatNormalTexture": { + "index": 5, + "texCoord": 0, + "scale": 1 + } + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "CoatNorm_Coating", + "normalTexture" : { + "index" : 5, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "SharedNorm_Base", + "normalTexture" : { + "index" : 6, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "SharedNorm_Coated", + "normalTexture" : { + "index" : 7, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03, + "clearcoatNormalTexture": { + "index": 7, + "texCoord": 0 + } + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "SharedNorm_Coating", + "normalTexture" : { + "index" : 8, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 1, + 1, + 1 + ], + "emissiveTexture" : { + "index" : 9, + "texCoord" : 0 + }, + "name" : "LabelMaterial", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.8999999761581421 + } + } + ], + "meshes" : [ + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 0 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 1 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 2 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 3 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 4 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 5 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 6 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 7 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 8 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 9 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 10 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 11 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 12 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 13 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 14 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 15 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 16 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 17 + } + ] + }, + { + "name" : "Labels_Mesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 4, + "NORMAL" : 5, + "TEXCOORD_0" : 6 + }, + "indices" : 7, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.001", + "primitives" : [ + { + "attributes" : { + "POSITION" : 8, + "NORMAL" : 9, + "TEXCOORD_0" : 10 + }, + "indices" : 7, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.002", + "primitives" : [ + { + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "TEXCOORD_0" : 13 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.003", + "primitives" : [ + { + "attributes" : { + "POSITION" : 15, + "NORMAL" : 16, + "TEXCOORD_0" : 17 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.004", + "primitives" : [ + { + "attributes" : { + "POSITION" : 18, + "NORMAL" : 19, + "TEXCOORD_0" : 20 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.005", + "primitives" : [ + { + "attributes" : { + "POSITION" : 21, + "NORMAL" : 22, + "TEXCOORD_0" : 23 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.006", + "primitives" : [ + { + "attributes" : { + "POSITION" : 24, + "NORMAL" : 25, + "TEXCOORD_0" : 26 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.007", + "primitives" : [ + { + "attributes" : { + "POSITION" : 27, + "NORMAL" : 28, + "TEXCOORD_0" : 29 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.008", + "primitives" : [ + { + "attributes" : { + "POSITION" : 30, + "NORMAL" : 31, + "TEXCOORD_0" : 32 + }, + "indices" : 7, + "material" : 18 + } + ] + } + ], + "textures" : [ + { + "source" : 0 + }, + { + "source" : 1 + }, + { + "source" : 2 + }, + { + "source" : 3 + }, + { + "source" : 3 + }, + { + "source" : 4 + }, + { + "source" : 3 + }, + { + "source" : 3 + }, + { + "source" : 3 + }, + { + "source" : 5 + } + ], + "images" : [ + { + "mimeType" : "image/png", + "name" : "PartialCoating", + "uri" : "PartialCoating.png" + }, + { + "mimeType" : "image/png", + "name" : "PartialCoating_Alpha", + "uri" : "PartialCoating_Alpha.png" + }, + { + "mimeType" : "image/png", + "name" : "RoughnessStripes", + "uri" : "RoughnessStripes.png" + }, + { + "mimeType" : "image/png", + "name" : "RibsNormal", + "uri" : "RibsNormal.png" + }, + { + "mimeType" : "image/jpeg", + "name" : "PlasticWrap_normals", + "uri" : "PlasticWrap_normals.jpg" + }, + { + "mimeType" : "image/png", + "name" : "ClearCoatLabels", + "uri" : "ClearCoatLabels.png" + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 1113, + "max" : [ + 1, + 1, + 1.0499999523162842 + ], + "min" : [ + -1, + -1, + -0.06000000983476639 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 1113, + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 1113, + "type" : "VEC2" + }, + { + "bufferView" : 3, + "componentType" : 5123, + "count" : 6180, + "type" : "SCALAR" + }, + { + "bufferView" : 4, + "componentType" : 5126, + "count" : 8, + "max" : [ + 1.0280373096466064, + 0.23501670360565186, + 3.8289083903464416e-08 + ], + "min" : [ + -0.968224287033081, + -0.2350165843963623, + -0.010000125505030155 + ], + "type" : "VEC3" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 7, + "componentType" : 5123, + "count" : 12, + "type" : "SCALAR" + }, + { + "bufferView" : 8, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.23026323318481445, + 3.751463495405005e-08 + ], + "min" : [ + -2, + -0.23026317358016968, + -0.010000579059123993 + ], + "type" : "VEC3" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 10, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 11, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.2302631139755249, + 3.7514624295909016e-08 + ], + "min" : [ + -2, + -0.23026323318481445, + -0.010000428184866905 + ], + "type" : "VEC3" + }, + { + "bufferView" : 12, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 13, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 14, + "componentType" : 5123, + "count" : 12, + "type" : "SCALAR" + }, + { + "bufferView" : 15, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.22039484977722168, + 3.590687924770464e-08 + ], + "min" : [ + -2, + -0.22039473056793213, + -0.010000280104577541 + ], + "type" : "VEC3" + }, + { + "bufferView" : 16, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 17, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 18, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.21764808893203735, + 3.545937588000925e-08 + ], + "min" : [ + -2, + -0.21764802932739258, + -0.010000137612223625 + ], + "type" : "VEC3" + }, + { + "bufferView" : 19, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 20, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 21, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.20775499939918518, + 3.3847587843638394e-08 + ], + "min" : [ + -2, + -0.20775499939918518, + -0.009999996051192284 + ], + "type" : "VEC3" + }, + { + "bufferView" : 22, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 23, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 24, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.22341907024383545, + 3.6399587344249085e-08 + ], + "min" : [ + -2, + -0.22341907024383545, + -0.009999859146773815 + ], + "type" : "VEC3" + }, + { + "bufferView" : 25, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 26, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 27, + "componentType" : 5126, + "count" : 8, + "max" : [ + 0.9169960618019104, + 0.22670458257198334, + 3.69348676088066e-08 + ], + "min" : [ + -0.9199233651161194, + -0.22670456767082214, + -0.010000176727771759 + ], + "type" : "VEC3" + }, + { + "bufferView" : 28, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 29, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 30, + "componentType" : 5126, + "count" : 8, + "max" : [ + 0.8968609571456909, + 0.20853587985038757, + 3.397480696776256e-08 + ], + "min" : [ + -0.9147982001304626, + -0.2085357904434204, + -0.010000113397836685 + ], + "type" : "VEC3" + }, + { + "bufferView" : 31, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 32, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 13356, + "byteOffset" : 0 + }, + { + "buffer" : 0, + "byteLength" : 13356, + "byteOffset" : 13356 + }, + { + "buffer" : 0, + "byteLength" : 8904, + "byteOffset" : 26712 + }, + { + "buffer" : 0, + "byteLength" : 12360, + "byteOffset" : 35616 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 47976 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48072 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48168 + }, + { + "buffer" : 0, + "byteLength" : 24, + "byteOffset" : 48232 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48256 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48352 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48448 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48512 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48608 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48704 + }, + { + "buffer" : 0, + "byteLength" : 24, + "byteOffset" : 48768 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48792 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48888 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48984 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49048 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49144 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 49240 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49304 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49400 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 49496 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49560 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49656 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 49752 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49816 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49912 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 50008 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 50072 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 50168 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 50264 + } + ], + "buffers" : [ + { + "byteLength" : 50328, + "uri" : "ClearCoatTest.bin" + } + ] +} diff --git a/test/models/glTF2/ClearCoat-glTF/PartialCoating.png b/test/models/glTF2/ClearCoat-glTF/PartialCoating.png new file mode 100644 index 000000000..d579bbebb Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/PartialCoating.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/PartialCoating_Alpha.png b/test/models/glTF2/ClearCoat-glTF/PartialCoating_Alpha.png new file mode 100644 index 000000000..b1911d9f0 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/PartialCoating_Alpha.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/PlasticWrap_normals.jpg b/test/models/glTF2/ClearCoat-glTF/PlasticWrap_normals.jpg new file mode 100644 index 000000000..73e6260ef Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/PlasticWrap_normals.jpg differ diff --git a/test/models/glTF2/ClearCoat-glTF/RibsNormal.png b/test/models/glTF2/ClearCoat-glTF/RibsNormal.png new file mode 100644 index 000000000..30c393dd7 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/RibsNormal.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/RoughnessStripes.png b/test/models/glTF2/ClearCoat-glTF/RoughnessStripes.png new file mode 100644 index 000000000..f3ab3570f Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/RoughnessStripes.png differ diff --git a/test/unit/utTypes.cpp b/test/unit/utTypes.cpp index cc354eb3d..1ac9a1d5e 100644 --- a/test/unit/utTypes.cpp +++ b/test/unit/utTypes.cpp @@ -53,8 +53,8 @@ class utTypes : public ::testing::Test { TEST_F( utTypes, Color3dCpmpareOpTest ) { aiColor3D col1( 1, 2, 3 ); aiColor3D col2( 4, 5, 6 ); - aiColor3D col3( col1 ); - + const aiColor3D &col3(col1); + EXPECT_FALSE( col1 == col2 ); EXPECT_FALSE( col2 == col3 ); EXPECT_TRUE( col1 == col3 ); diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 4110edcfc..2c000bb37 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -57,10 +57,9 @@ using namespace Assimp; class utglTF2ImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { + virtual bool importerMatTest(const char *file, bool spec_gloss, std::array exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", - aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); EXPECT_NE(scene, nullptr); if (!scene) { return false; @@ -72,13 +71,49 @@ public: } const aiMaterial *material = scene->mMaterials[0]; + // This Material should be a PBR + aiShadingMode shadingMode; + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_SHADING_MODEL, shadingMode)); + EXPECT_EQ(aiShadingMode_PBR_BRDF, shadingMode); + + // Should import the texture as diffuse and as base color aiString path; - aiTextureMapMode modes[2]; + std::array modes; EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, - nullptr, nullptr, modes)); + nullptr, nullptr, modes.data())); EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png"); - EXPECT_EQ(modes[0], aiTextureMapMode_Mirror); - EXPECT_EQ(modes[1], aiTextureMapMode_Clamp); + EXPECT_EQ(exp_modes, modes); + + // Also as Base Color + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_BASE_COLOR, 0, &path, nullptr, nullptr, + nullptr, nullptr, modes.data())); + EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png"); + EXPECT_EQ(exp_modes, modes); + + // Should have a MetallicFactor (default is 1.0) + ai_real metal_factor = ai_real(0.5); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_METALLIC_FACTOR, metal_factor)); + EXPECT_EQ(ai_real(0.0), metal_factor); + + // And a roughness factor (default is 1.0) + ai_real roughness_factor = ai_real(0.5); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness_factor)); + EXPECT_EQ(ai_real(1.0), roughness_factor); + + aiColor3D spec_color = { 0, 0, 0 }; + ai_real glossiness = ai_real(0.5); + if (spec_gloss) { + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); + constexpr ai_real spec_val(0.20000000298023225); // From the file + EXPECT_EQ(spec_val, spec_color.r); + EXPECT_EQ(spec_val, spec_color.g); + EXPECT_EQ(spec_val, spec_color.b); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness)); + EXPECT_EQ(ai_real(1.0), glossiness); + } else { + EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); + EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness)); + } return true; } @@ -105,14 +140,89 @@ public: }; TEST_F(utglTF2ImportExport, importglTF2FromFileTest) { - EXPECT_TRUE(importerTest()); + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", false, {aiTextureMapMode_Mirror, aiTextureMapMode_Clamp})); } TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) { EXPECT_TRUE(binaryImporterTest()); } +TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_pbrSpecularGlossiness) { + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", true)); +} + +void VerifyClearCoatScene(const aiScene *scene) { + ASSERT_NE(nullptr, scene); + + ASSERT_TRUE(scene->HasMaterials()); + + // Find a specific Clearcoat material and check the values + const aiString partial_coated("Partial_Coated"); + bool found_partial_coat = false; + for (size_t i = 0; i < scene->mNumMaterials; ++i) { + const aiMaterial *material = scene->mMaterials[i]; + ASSERT_NE(nullptr, material); + if (material->GetName() == partial_coated) { + found_partial_coat = true; + + ai_real clearcoat_factor(0.0f); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat_factor)); + EXPECT_EQ(ai_real(1.0f), clearcoat_factor); + + ai_real clearcoat_rough_factor(0.0f); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat_rough_factor)); + EXPECT_EQ(ai_real(0.03f), clearcoat_rough_factor); + + // Should import the texture as diffuse and as base color + aiString path; + std::array modes; + static const std::array exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_CLEARCOAT_TEXTURE, &path, nullptr, nullptr, + nullptr, nullptr, modes.data())); + EXPECT_STREQ(path.C_Str(), "PartialCoating.png"); + EXPECT_EQ(exp_modes, modes); + } + } + EXPECT_TRUE(found_partial_coat); +} + +TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_clearcoat) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest.gltf", aiProcess_ValidateDataStructure); + VerifyClearCoatScene(scene); +} + #ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_clearcoat) { + { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(nullptr, scene); + // Export + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest_out.glb")); + } + + // And re-import + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest_out.glb", aiProcess_ValidateDataStructure); + VerifyClearCoatScene(scene); +} + +TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_pbrSpecularGlossiness) { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", + aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + // Export + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb")); + + // And re-import + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true)); +} + TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) { Assimp::Importer importer; Assimp::Exporter exporter; @@ -130,6 +240,7 @@ TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) { EXPECT_NE(nullptr, scene); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj")); } + #endif // ASSIMP_BUILD_NO_EXPORT TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) { @@ -492,32 +603,58 @@ TEST_F(utglTF2ImportExport, sceneMetadata) { } TEST_F(utglTF2ImportExport, texcoords) { + Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", - aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_TRUE(scene->HasMaterials()); + const aiMaterial *material = scene->mMaterials[0]; + + aiString path; + unsigned int uvIndex = 255; + aiTextureMapMode modes[2]; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); + EXPECT_EQ(uvIndex, 0); + + uvIndex = 255; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); + EXPECT_EQ(uvIndex, 1); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utglTF2ImportExport, texcoords_export) { + { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf_out.glb")); + } + + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure); ASSERT_NE(scene, nullptr); ASSERT_TRUE(scene->HasMaterials()); const aiMaterial *material = scene->mMaterials[0]; aiString path; + unsigned int uvIndex = 255; aiTextureMapMode modes[2]; - EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, - nullptr, nullptr, modes)); + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); EXPECT_STREQ(path.C_Str(), "texture.png"); - - int uvIndex = -1; - EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_DIFFUSE, 0), &uvIndex), aiReturn_SUCCESS); EXPECT_EQ(uvIndex, 0); - // Using manual macro expansion of AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE here. - // The following works with some but not all compilers: - // #define APPLY(X, Y) X(Y) - // ..., APPLY(AI_MATKEY_GLTF_TEXTURE_TEXCOORD, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE), ... - EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_UNKNOWN, 0), &uvIndex), aiReturn_SUCCESS); + uvIndex = 255; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); EXPECT_EQ(uvIndex, 1); } +#endif // ASSIMP_BUILD_NO_EXPORT TEST_F(utglTF2ImportExport, recursive_nodes) { Assimp::Importer importer; const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/RecursiveNodes/RecursiveNodes.gltf", aiProcess_ValidateDataStructure); diff --git a/tools/assimp_view/AnimEvaluator.cpp b/tools/assimp_view/AnimEvaluator.cpp index df5167923..5a2ddc182 100644 --- a/tools/assimp_view/AnimEvaluator.cpp +++ b/tools/assimp_view/AnimEvaluator.cpp @@ -39,9 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -#include "assimp_view.h" +#include "AnimEvaluator.h" -#include +#include +#include using namespace AssimpView; diff --git a/tools/assimp_view/AnimEvaluator.h b/tools/assimp_view/AnimEvaluator.h index 950763081..566247604 100644 --- a/tools/assimp_view/AnimEvaluator.h +++ b/tools/assimp_view/AnimEvaluator.h @@ -1,4 +1,3 @@ -/** Calculates a pose for a given time of an animation */ /* --------------------------------------------------------------------------- Open Asset Import Library (assimp) @@ -40,11 +39,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ +#pragma once #ifndef AV_ANIMEVALUATOR_H_INCLUDED #define AV_ANIMEVALUATOR_H_INCLUDED +/** Calculates a pose for a given time of an animation */ + #include #include +#include + +struct aiAnimation; namespace AssimpView { @@ -63,18 +68,19 @@ public: /// @brief The class destructor. ~AnimEvaluator(); - /** Evaluates the animation tracks for a given time stamp. The calculated pose can be retrieved as a - * array of transformation matrices afterwards by calling GetTransformations(). - * @param pTime The time for which you want to evaluate the animation, in seconds. Will be mapped into the animation cycle, so - * it can be an arbitrary value. Best use with ever-increasing time stamps. - */ + /// @brief Evaluates the animation tracks for a given time stamp. + /// The calculated pose can be retrieved as an array of transformation + /// matrices afterwards by calling GetTransformations(). + /// @param pTime The time for which you want to evaluate the animation, in seconds. + /// Will be mapped into the animation cycle, so it can get an arbitrary + /// value. Best use with ever-increasing time stamps. void Evaluate(double pTime); - /** Returns the transform matrices calculated at the last Evaluate() call. The array matches the mChannels array of - * the aiAnimation. */ + /// @brief Returns the transform matrices calculated at the last Evaluate() call. + /// The array matches the mChannels array of the aiAnimation. const std::vector &GetTransformations() const { return mTransforms; } -protected: +private: const aiAnimation *mAnim; double mLastTime; std::vector> mLastPositions; diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index 260b22941..5ab7c53ad 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -489,7 +489,7 @@ int CreateAssetData() { nidx = 3; break; default: - ai_assert(false); + CLogWindow::Instance().WriteLine("Unknown primitiv type"); break; }; @@ -500,8 +500,7 @@ int CreateAssetData() { // check whether we can use 16 bit indices if (numIndices >= 65536) { // create 32 bit index buffer - if (FAILED(g_piDevice->CreateIndexBuffer(4 * - numIndices, + if (FAILED(g_piDevice->CreateIndexBuffer(4 * numIndices, D3DUSAGE_WRITEONLY | dwUsage, D3DFMT_INDEX32, D3DPOOL_DEFAULT, @@ -523,7 +522,7 @@ int CreateAssetData() { } else { // create 16 bit index buffer if (FAILED(g_piDevice->CreateIndexBuffer(2 * - numIndices, +numIndices, D3DUSAGE_WRITEONLY | dwUsage, D3DFMT_INDEX16, D3DPOOL_DEFAULT,