From 63d3655f1b8b73e3c15799e061baaa8fa95e086f Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 24 Aug 2017 17:15:48 -0400 Subject: [PATCH 01/56] Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List --- code/CMakeLists.txt | 2 + code/ImporterRegistry.cpp | 4 +- code/glTF2Importer.cpp | 680 ++++++++++++++++++++++++++++++++++++++ code/glTF2Importer.h | 91 +++++ 4 files changed, 775 insertions(+), 2 deletions(-) create mode 100644 code/glTF2Importer.cpp create mode 100644 code/glTF2Importer.h diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 236e6d7ef..0e7aad6cc 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -665,6 +665,8 @@ ADD_ASSIMP_IMPORTER( GLTF glTF2Asset.inl glTF2AssetWriter.h glTF2AssetWriter.inl + glTF2Importer.cpp + glTF2Importer.h glTF2Exporter.h glTF2Exporter.cpp ) diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index afc308075..2b5d9c1a0 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -181,7 +181,7 @@ corresponding preprocessor flag to selectively disable formats. # include "AssbinLoader.h" #endif #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER -# include "glTFImporter.h" +# include "glTF2Importer.h" #endif #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER # include "C4DImporter.h" @@ -335,7 +335,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) out.push_back( new AssbinImporter() ); #endif #if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) - out.push_back( new glTFImporter() ); + out.push_back( new glTF2Importer() ); #endif #if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER ) out.push_back( new C4DImporter() ); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp new file mode 100644 index 000000000..bd4f42600 --- /dev/null +++ b/code/glTF2Importer.cpp @@ -0,0 +1,680 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + +#include "glTF2Importer.h" +#include "StringComparison.h" +#include "StringUtils.h" + +#include +#include +#include +#include +#include + +#include + +#include "MakeVerboseFormat.h" + +#include "glTF2Asset.h" +// This is included here so WriteLazyDict's definition is found. +#include "glTF2AssetWriter.h" + +using namespace Assimp; +using namespace glTF2; + + +// +// glTF2Importer +// + +static const aiImporterDesc desc = { + "glTF2 Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour + | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + 0, + 0, + 0, + 0, + "gltf glb" +}; + +glTF2Importer::glTF2Importer() +: BaseImporter() +, meshOffsets() +, embeddedTexIdxs() +, mScene( NULL ) { + // empty +} + +glTF2Importer::~glTF2Importer() { + // empty +} + +const aiImporterDesc* glTF2Importer::GetInfo() const +{ + return &desc; +} + +bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +{ + const std::string& extension = GetExtension(pFile); + + if (extension == "gltf" || extension == "glb") + return true; + + if ((checkSig || !extension.length()) && pIOHandler) { + char buffer[4]; + + std::unique_ptr pStream(pIOHandler->Open(pFile)); + if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { + if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { + return true; // Has GLB header + } + else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0 + || memcmp(buffer, "{\n ", sizeof(buffer)) == 0) { + // seems a JSON file, and we're the only format that can read them + return true; + } + } + } + + return false; +} + + + +//static void CopyValue(const glTF2::vec3& v, aiColor3D& out) +//{ +// out.r = v[0]; out.g = v[1]; out.b = v[2]; +//} + +static void CopyValue(const glTF2::vec4& v, aiColor4D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3]; +} + +static void CopyValue(const glTF2::vec4& v, aiColor3D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; +} + +static void CopyValue(const glTF2::vec3& v, aiVector3D& out) +{ + out.x = v[0]; out.y = v[1]; out.z = v[2]; +} + +static void CopyValue(const glTF2::vec4& v, aiQuaternion& out) +{ + out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3]; +} + +static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o) +{ + o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3]; + o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7]; + o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11]; + o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; +} + +inline void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TexProperty prop, aiMaterial* mat, + aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) +{ + if (prop.texture) { + if (prop.texture->source) { + aiString uri(prop.texture->source->uri); + + int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; + if (texIdx != -1) { // embedded + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + uri.data[0] = '*'; + uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); + } + + mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); + } + } + else { + aiColor4D col; + CopyValue(prop.color, col); + mat->AddProperty(&col, 1, pKey, type, idx); + } +} + +void glTF2Importer::ImportMaterials(glTF2::Asset& r) +{ + mScene->mNumMaterials = unsigned(r.materials.Size()); + mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; + + for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { + aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial(); + + Material& mat = r.materials[i]; + + /*if (!mat.name.empty())*/ { + aiString str(mat.id /*mat.name*/); + aimat->AddProperty(&str, AI_MATKEY_NAME); + } + + SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); + SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + + if (mat.shininess > 0.f) { + aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS); + } + } +} + + +static inline void SetFace(aiFace& face, int a) +{ + face.mNumIndices = 1; + face.mIndices = new unsigned int[1]; + face.mIndices[0] = a; +} + +static inline void SetFace(aiFace& face, int a, int b) +{ + face.mNumIndices = 2; + face.mIndices = new unsigned int[2]; + face.mIndices[0] = a; + face.mIndices[1] = b; +} + +static inline void SetFace(aiFace& face, int a, int b, int c) +{ + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + face.mIndices[0] = a; + face.mIndices[1] = b; + face.mIndices[2] = c; +} + +static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts) +{ + for (unsigned i = 0; i < nFaces; ++i) { + for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { + unsigned idx = faces[i].mIndices[j]; + if (idx >= nVerts) + return false; + } + } + return true; +} + +void glTF2Importer::ImportMeshes(glTF2::Asset& r) +{ + std::vector meshes; + + unsigned int k = 0; + + for (unsigned int m = 0; m < r.meshes.Size(); ++m) { + Mesh& mesh = r.meshes[m]; + + // Check if mesh extensions is used + if(mesh.Extension.size() > 0) + { + for(Mesh::SExtension* cur_ext : mesh.Extension) + { +#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC + if(cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) + { + // Limitations for meshes when using Open3DGC-compression. + // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? + // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can + // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" + // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. + // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. + // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor + // of primitive must point to one continuous region of the buffer. + if(mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed."); + + Mesh::SCompression_Open3DGC* o3dgc_ext = (Mesh::SCompression_Open3DGC*)cur_ext; + Ref buf = r.buffers.Get(o3dgc_ext->Buffer); + + buf->EncodedRegion_SetCurrent(mesh.id); + } + else +#endif + { + throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + + "\"), only Open3DGC is supported."); + } + } + }// if(mesh.Extension.size() > 0) + + meshOffsets.push_back(k); + k += unsigned(mesh.primitives.size()); + + for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { + Mesh::Primitive& prim = mesh.primitives[p]; + + aiMesh* aim = new aiMesh(); + meshes.push_back(aim); + + aim->mName = mesh.id; + if (mesh.primitives.size() > 1) { + size_t& len = aim->mName.length; + aim->mName.data[len] = '-'; + len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); + } + + switch (prim.mode) { + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + } + + Mesh::Primitive::Attributes& attr = prim.attributes; + + if (attr.position.size() > 0 && attr.position[0]) { + aim->mNumVertices = attr.position[0]->count; + attr.position[0]->ExtractData(aim->mVertices); + } + + if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); + + for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); + aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); + + aiVector3D* values = aim->mTextureCoords[tc]; + for (unsigned int i = 0; i < aim->mNumVertices; ++i) { + values[i].y = 1 - values[i].y; // Flip Y coords + } + } + + + if (prim.indices) { + aiFace* faces = 0; + unsigned int nFaces = 0; + + unsigned int count = prim.indices->count; + + Accessor::Indexer data = prim.indices->GetIndexer(); + ai_assert(data.IsValid()); + + switch (prim.mode) { + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], data.GetUInt(i)); + } + break; + } + + case PrimitiveMode_LINES: { + nFaces = count / 2; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + } + break; + } + + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + + if (faces) { + aim->mFaces = faces; + aim->mNumFaces = nFaces; + ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); + } + } + + + if (prim.material) { + aim->mMaterialIndex = prim.material.GetIndex(); + } + } + } + + meshOffsets.push_back(k); + + CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); +} + +void glTF2Importer::ImportCameras(glTF2::Asset& r) +{ + if (!r.cameras.Size()) return; + + mScene->mNumCameras = r.cameras.Size(); + mScene->mCameras = new aiCamera*[r.cameras.Size()]; + + for (size_t i = 0; i < r.cameras.Size(); ++i) { + Camera& cam = r.cameras[i]; + + aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); + + if (cam.type == Camera::Perspective) { + + aicam->mAspect = cam.cameraProperties.perspective.aspectRatio; + aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * aicam->mAspect; + aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar; + aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear; + } + else { + // assimp does not support orthographic cameras + } + } +} + +void glTF2Importer::ImportLights(glTF2::Asset& r) +{ + if (!r.lights.Size()) return; + + mScene->mNumLights = r.lights.Size(); + mScene->mLights = new aiLight*[r.lights.Size()]; + + for (size_t i = 0; i < r.lights.Size(); ++i) { + Light& l = r.lights[i]; + + aiLight* ail = mScene->mLights[i] = new aiLight(); + + switch (l.type) { + case Light::Type_directional: + ail->mType = aiLightSource_DIRECTIONAL; break; + + case Light::Type_spot: + ail->mType = aiLightSource_SPOT; break; + + case Light::Type_ambient: + ail->mType = aiLightSource_AMBIENT; break; + + default: // Light::Type_point + ail->mType = aiLightSource_POINT; break; + } + + CopyValue(l.color, ail->mColorAmbient); + CopyValue(l.color, ail->mColorDiffuse); + CopyValue(l.color, ail->mColorSpecular); + + ail->mAngleOuterCone = l.falloffAngle; + ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all + + ail->mAttenuationConstant = l.constantAttenuation; + ail->mAttenuationLinear = l.linearAttenuation; + ail->mAttenuationQuadratic = l.quadraticAttenuation; + } +} + + +aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& meshOffsets, glTF2::Ref& ptr) +{ + Node& node = *ptr; + + aiNode* ainode = new aiNode(node.id); + + if (!node.children.empty()) { + ainode->mNumChildren = unsigned(node.children.size()); + ainode->mChildren = new aiNode*[ainode->mNumChildren]; + + for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { + aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); + child->mParent = ainode; + ainode->mChildren[i] = child; + } + } + + aiMatrix4x4& matrix = ainode->mTransformation; + if (node.matrix.isPresent) { + CopyValue(node.matrix.value, matrix); + } + else { + if (node.translation.isPresent) { + aiVector3D trans; + CopyValue(node.translation.value, trans); + aiMatrix4x4 t; + aiMatrix4x4::Translation(trans, t); + matrix = t * matrix; + } + + if (node.scale.isPresent) { + aiVector3D scal(1.f); + CopyValue(node.scale.value, scal); + aiMatrix4x4 s; + aiMatrix4x4::Scaling(scal, s); + matrix = s * matrix; + } + + + if (node.rotation.isPresent) { + aiQuaternion rot; + CopyValue(node.rotation.value, rot); + matrix = aiMatrix4x4(rot.GetMatrix()) * matrix; + } + } + + if (!node.meshes.empty()) { + int count = 0; + for (size_t i = 0; i < node.meshes.size(); ++i) { + int idx = node.meshes[i].GetIndex(); + count += meshOffsets[idx + 1] - meshOffsets[idx]; + } + + ainode->mNumMeshes = count; + ainode->mMeshes = new unsigned int[count]; + + int k = 0; + for (size_t i = 0; i < node.meshes.size(); ++i) { + int idx = node.meshes[i].GetIndex(); + for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) { + ainode->mMeshes[k] = j; + } + } + } + + if (node.camera) { + pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; + } + + if (node.light) { + pScene->mLights[node.light.GetIndex()]->mName = ainode->mName; + } + + return ainode; +} + +void glTF2Importer::ImportNodes(glTF2::Asset& r) +{ + if (!r.scene) return; + + std::vector< Ref > rootNodes = r.scene->nodes; + + // The root nodes + unsigned int numRootNodes = unsigned(rootNodes.size()); + if (numRootNodes == 1) { // a single root node: use it + mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); + } + else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode* root = new aiNode("ROOT"); + root->mChildren = new aiNode*[numRootNodes]; + for (unsigned int i = 0; i < numRootNodes; ++i) { + aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); + node->mParent = root; + root->mChildren[root->mNumChildren++] = node; + } + mScene->mRootNode = root; + } + + //if (!mScene->mRootNode) { + // mScene->mRootNode = new aiNode("EMPTY"); + //} +} + +void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r) +{ + embeddedTexIdxs.resize(r.images.Size(), -1); + + int numEmbeddedTexs = 0; + for (size_t i = 0; i < r.images.Size(); ++i) { + if (r.images[i].HasData()) + numEmbeddedTexs += 1; + } + + if (numEmbeddedTexs == 0) + return; + + mScene->mTextures = new aiTexture*[numEmbeddedTexs]; + + // Add the embedded textures + for (size_t i = 0; i < r.images.Size(); ++i) { + Image img = r.images[i]; + if (!img.HasData()) continue; + + int idx = mScene->mNumTextures++; + embeddedTexIdxs[i] = idx; + + aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); + + size_t length = img.GetDataLength(); + void* data = img.StealData(); + + tex->mWidth = static_cast(length); + tex->mHeight = 0; + tex->pcData = reinterpret_cast(data); + + if (!img.mimeType.empty()) { + const char* ext = strchr(img.mimeType.c_str(), '/') + 1; + if (ext) { + if (strcmp(ext, "jpeg") == 0) ext = "jpg"; + + size_t len = strlen(ext); + if (len <= 3) { + strcpy(tex->achFormatHint, ext); + } + } + } + } +} + +void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { + + this->mScene = pScene; + + // read the asset file + glTF2::Asset asset(pIOHandler); + asset.Load(pFile, GetExtension(pFile) == "glb"); + + + // + // Copy the data out + // + + ImportEmbeddedTextures(asset); + ImportMaterials(asset); + + ImportMeshes(asset); + + ImportCameras(asset); + ImportLights(asset); + + ImportNodes(asset); + + // TODO: it does not split the loaded vertices, should it? + //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; + MakeVerboseFormatProcess process; + process.Execute(pScene); + + + if (pScene->mNumMeshes == 0) { + pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + } +} + +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + diff --git a/code/glTF2Importer.h b/code/glTF2Importer.h new file mode 100644 index 000000000..6be7131d1 --- /dev/null +++ b/code/glTF2Importer.h @@ -0,0 +1,91 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#ifndef AI_GLTF2IMPORTER_H_INC +#define AI_GLTF2IMPORTER_H_INC + +#include "BaseImporter.h" +#include + +struct aiNode; + + +namespace glTF2 +{ + class Asset; +} + +namespace Assimp { + +/** + * Load the glTF2 format. + * https://github.com/KhronosGroup/glTF/tree/master/specification + */ +class glTF2Importer : public BaseImporter{ +public: + glTF2Importer(); + virtual ~glTF2Importer(); + virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const; + +protected: + virtual const aiImporterDesc* GetInfo() const; + virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ); + +private: + + std::vector meshOffsets; + + std::vector embeddedTexIdxs; + + aiScene* mScene; + + void ImportEmbeddedTextures(glTF2::Asset& a); + void ImportMaterials(glTF2::Asset& a); + void ImportMeshes(glTF2::Asset& a); + void ImportCameras(glTF2::Asset& a); + void ImportLights(glTF2::Asset& a); + void ImportNodes(glTF2::Asset& a); + +}; + +} // Namespace assimp + +#endif // AI_GLTF2IMPORTER_H_INC + From f814acf33a553b38900b7bd2591d2864aeacdb34 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 24 Aug 2017 17:31:33 -0400 Subject: [PATCH 02/56] Update glTF2 Asset to use indexes --- code/glTF2Asset.h | 6 +- code/glTF2Asset.inl | 311 +++++++++++--------------------------------- 2 files changed, 77 insertions(+), 240 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 52bc18268..2e7a694d8 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -232,7 +232,7 @@ namespace glTF2 case ComponentType_UNSIGNED_BYTE: return 1; default: - throw DeadlyImportError("GLTF: Unsupported Component Type "+t); + throw DeadlyImportError("GLTF: Unsupported Component Type " + std::to_string(t)); } } @@ -629,7 +629,7 @@ namespace glTF2 float zfar; //! The floating-point distance to the far clipping plane. (required) float znear; //! The floating-point distance to the near clipping plane. (required) } ortographic; - }; + } cameraProperties; Camera() {} void Read(Value& obj, Asset& r); @@ -1146,7 +1146,7 @@ namespace glTF2 LazyDict samplers; LazyDict scenes; //LazyDict shaders; - LazyDict skins; + LazyDict skins; //LazyDict techniques; LazyDict textures; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 09e647cca..268deb8a8 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -128,6 +128,12 @@ namespace { return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; } + inline Value* FindUInt(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsUint()) ? &it->value : 0; + } + inline Value* FindArray(Value& val, const char* id) { Value::MemberIterator it = val.FindMember(id); @@ -176,7 +182,7 @@ inline void LazyDict::AttachToDocument(Document& doc) } if (container) { - mDict = FindObject(*container, mDictId); + mDict = FindArray(*container, mDictId); } } @@ -189,13 +195,8 @@ inline void LazyDict::DetachFromDocument() template Ref LazyDict::Get(unsigned int i) { - return Ref(mObjs, i); -} -template -Ref LazyDict::Get(const char* id) -{ - id = T::TranslateId(mAsset, id); + std::string id = std::string(mDictId) + "[" + std::to_string(i) + "]"; typename Dict::iterator it = mObjsById.find(id); if (it != mObjsById.end()) { // already created? @@ -207,19 +208,21 @@ Ref LazyDict::Get(const char* id) throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\""); } - Value::MemberIterator obj = mDict->FindMember(id); - if (obj == mDict->MemberEnd()) { - throw DeadlyImportError("GLTF: Missing object with id \"" + std::string(id) + "\" in \"" + mDictId + "\""); - } - if (!obj->value.IsObject()) { - throw DeadlyImportError("GLTF: Object with id \"" + std::string(id) + "\" is not a JSON object"); + if (!mDict->IsArray()) { + throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\""); + } + + Value& obj = mDict->operator[](i); + + if (!obj.IsObject()) { + throw DeadlyImportError("GLTF: Object at index \"" + std::to_string(i) + "\" is not a JSON object"); } - // create an instance of the given type T* inst = new T(); inst->id = id; - ReadMember(obj->value, "name", inst->name); - inst->Read(obj->value, mAsset); + ReadMember(obj, "name", inst->name); + inst->Read(obj, mAsset); + return Add(inst); } @@ -437,9 +440,9 @@ inline void Buffer::Grow(size_t amount) inline void BufferView::Read(Value& obj, Asset& r) { - const char* bufferId = MemberOrDefault(obj, "buffer", 0); - if (bufferId) { - buffer = r.buffers.Get(bufferId); + + if (Value* bufferVal = FindUInt(obj, "buffer")) { + buffer = r.buffers.Get(bufferVal->GetUint()); } byteOffset = MemberOrDefault(obj, "byteOffset", 0u); @@ -452,9 +455,9 @@ inline void BufferView::Read(Value& obj, Asset& r) inline void Accessor::Read(Value& obj, Asset& r) { - const char* bufferViewId = MemberOrDefault(obj, "bufferView", 0); - if (bufferViewId) { - bufferView = r.bufferViews.Get(bufferViewId); + + if (Value* bufferViewVal = FindUInt(obj, "bufferView")) { + bufferView = r.bufferViews.Get(bufferViewVal->GetUint()); } byteOffset = MemberOrDefault(obj, "byteOffset", 0u); @@ -611,9 +614,8 @@ inline void Image::Read(Value& obj, Asset& r) ReadMember(*ext, "mimeType", mimeType); - const char* bufferViewId; - if (ReadMember(*ext, "bufferView", bufferViewId)) { - Ref bv = r.bufferViews.Get(bufferViewId); + if (Value* bufferViewVal = FindUInt(*ext, "bufferView")) { + Ref bv = r.bufferViews.Get(bufferViewVal->GetUint()); if (bv) { mDataLength = bv->byteLength; mData = new uint8_t[mDataLength]; @@ -687,23 +689,22 @@ inline void Sampler::SetDefaults() inline void Texture::Read(Value& obj, Asset& r) { - const char* sourcestr; - if (ReadMember(obj, "source", sourcestr)) { - source = r.images.Get(sourcestr); + if (Value* sourceVal = FindUInt(obj, "source")) { + source = r.images.Get(sourceVal->GetUint()); } - const char* samplerstr; - if (ReadMember(obj, "sampler", samplerstr)) { - sampler = r.samplers.Get(samplerstr); + if (Value* samplerVal = FindUInt(obj, "sampler")) { + sampler = r.samplers.Get(samplerVal->GetUint()); } } namespace { inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out) { + //@TODO: update this format if (Value* prop = FindMember(vals, propName)) { - if (prop->IsString()) { - out.texture = r.textures.Get(prop->GetString()); + if (prop->IsUint()) { + out.texture = r.textures.Get(prop->GetUint()); } else { ReadValue(*prop, out.color); @@ -824,22 +825,23 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. + //@TODO: update this int undPos = 0; Mesh::AccessorList* vec = 0; if (GetAttribVector(prim, attr, vec, undPos)) { size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; if ((*vec).size() <= idx) (*vec).resize(idx + 1); - (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetString()); + (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetUint()); } } } - if (Value* indices = FindString(primitive, "indices")) { - prim.indices = pAsset_Root.accessors.Get(indices->GetString()); + if (Value* indices = FindUInt(primitive, "indices")) { + prim.indices = pAsset_Root.accessors.Get(indices->GetUint()); } - if (Value* material = FindString(primitive, "material")) { - prim.material = pAsset_Root.materials.Get(material->GetString()); + if (Value* material = FindUInt(primitive, "material")) { + prim.material = pAsset_Root.materials.Get(material->GetUint()); } } } @@ -914,177 +916,6 @@ mr_skip_extensions: return;// After label some operators must be present. } -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC -inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root) -{ -typedef unsigned short IndicesType;///< \sa glTFExporter::ExportMeshes. - -o3dgc::SC3DMCDecoder decoder; -o3dgc::IndexedFaceSet ifs; -o3dgc::BinaryStream bstream; -uint8_t* decoded_data; -size_t decoded_data_size = 0; -Ref buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); - - // Read data from buffer and place it in BinaryStream for decoder. - // Just "Count" because always is used type equivalent to uint8_t. - bstream.LoadFromBuffer(&buf->GetPointer()[pCompression_Open3DGC.Offset], static_cast(pCompression_Open3DGC.Count)); - - // After decoding header we can get size of primitives. - if(decoder.DecodeHeader(ifs, bstream) != o3dgc::O3DGC_OK) throw DeadlyImportError("GLTF: can not decode Open3DGC header."); - - /****************** Get sizes of arrays and check sizes ******************/ - // Note. See "Limitations for meshes when using Open3DGC-compression". - - // Indices - size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note. - - if(primitives[0].indices->count != size_coordindex) - throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + std::to_string(size_coordindex) + - ") not equal to uncompressed (" + std::to_string(primitives[0].indices->count) + ")."); - - size_coordindex *= sizeof(IndicesType); - // Coordinates - size_t size_coord = ifs.GetNCoord();// See float attributes note. - - if(primitives[0].attributes.position[0]->count != size_coord) - throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + std::to_string(size_coord) + - ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.position[0]->count) + ")."); - - size_coord *= 3 * sizeof(float); - // Normals - size_t size_normal = ifs.GetNNormal();// See float attributes note. - - if(primitives[0].attributes.normal[0]->count != size_normal) - throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + std::to_string(size_normal) + - ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.normal[0]->count) + ")."); - - size_normal *= 3 * sizeof(float); - // Additional attributes. - std::vector size_floatattr; - std::vector size_intattr; - - size_floatattr.resize(ifs.GetNumFloatAttributes()); - size_intattr.resize(ifs.GetNumIntAttributes()); - - decoded_data_size = size_coordindex + size_coord + size_normal; - for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) - { - // size = number_of_elements * components_per_element * size_of_component. - // Note. But as you can see above, at first we are use this variable in meaning "count". After checking count of objects... - size_t tval = ifs.GetNFloatAttribute(static_cast(idx)); - - switch(ifs.GetFloatAttributeType(static_cast(idx))) - { - case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD: - // Check situation when encoded data contain texture coordinates but primitive not. - if(idx_texcoord < primitives[0].attributes.texcoord.size()) - { - if(primitives[0].attributes.texcoord[idx]->count != tval) - throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + std::to_string(tval) + - ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.texcoord[idx]->count) + ")."); - - idx_texcoord++; - } - else - { - ifs.SetNFloatAttribute(static_cast(idx), 0ul);// Disable decoding this attribute. - } - - break; - default: - throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast(idx)))); - } - - tval *= ifs.GetFloatAttributeDim(static_cast(idx)) * sizeof(o3dgc::Real);// After checking count of objects we can get size of array. - size_floatattr[idx] = tval; - decoded_data_size += tval; - } - - for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) - { - // size = number_of_elements * components_per_element * size_of_component. See float attributes note. - size_t tval = ifs.GetNIntAttribute(static_cast(idx)); - switch( ifs.GetIntAttributeType(static_cast(idx) ) ) - { - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN: - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX: - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID: - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID: - break; - - default: - throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast(idx)))); - } - - tval *= ifs.GetIntAttributeDim(static_cast(idx)) * sizeof(long);// See float attributes note. - size_intattr[idx] = tval; - decoded_data_size += tval; - } - - // Create array for decoded data. - decoded_data = new uint8_t[decoded_data_size]; - - /****************** Set right array regions for decoder ******************/ - - auto get_buf_offset = [](Ref& pAccessor) -> size_t { return pAccessor->byteOffset + pAccessor->bufferView->byteOffset; }; - - // Indices - ifs.SetCoordIndex((IndicesType* const)(decoded_data + get_buf_offset(primitives[0].indices))); - // Coordinates - ifs.SetCoord((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.position[0]))); - // Normals - if(size_normal) - { - ifs.SetNormal((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0]))); - } - - for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) - { - switch(ifs.GetFloatAttributeType(static_cast(idx))) - { - case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD: - if(idx_texcoord < primitives[0].attributes.texcoord.size()) - { - // See above about absent attributes. - ifs.SetFloatAttribute(static_cast(idx), (o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx]))); - idx_texcoord++; - } - - break; - default: - throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast(idx)))); - } - } - - for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) { - switch(ifs.GetIntAttributeType(static_cast(idx))) { - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN: - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX: - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID: - case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID: - break; - - // ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint))); - default: - throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast(idx)))); - } - } - - // - // Decode data - // - if ( decoder.DecodePayload( ifs, bstream ) != o3dgc::O3DGC_OK ) { - throw DeadlyImportError( "GLTF: can not decode Open3DGC data." ); - } - - // Set encoded region for "buffer". - buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id); - // No. Do not delete "output_data". After calling "EncodedRegion_Mark" bufferView is owner of "output_data". - // "delete [] output_data;" -} -#endif - inline void Camera::Read(Value& obj, Asset& r) { type = MemberOrDefault(obj, "type", Camera::Perspective); @@ -1095,16 +926,16 @@ inline void Camera::Read(Value& obj, Asset& r) if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters"); if (type == Camera::Perspective) { - perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f); - perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f); - perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); - perspective.znear = MemberOrDefault(*it, "znear", 0.01f); + cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f); + cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f); + cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); + cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f); } else { - ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); - ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); - ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); - ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); + cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); + cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); + cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); + cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); } } @@ -1156,13 +987,14 @@ inline void Light::SetDefaults() inline void Node::Read(Value& obj, Asset& r) { + if (Value* children = FindArray(obj, "children")) { this->children.reserve(children->Size()); for (unsigned int i = 0; i < children->Size(); ++i) { Value& child = (*children)[i]; - if (child.IsString()) { + if (child.IsNumber()) { // get/create the child node - Ref chn = r.nodes.Get(child.GetString()); + Ref chn = r.nodes.Get(child.GetUint()); if (chn) this->children.push_back(chn); } } @@ -1185,15 +1017,15 @@ inline void Node::Read(Value& obj, Asset& r) this->meshes.reserve(numMeshes); for (unsigned i = 0; i < numMeshes; ++i) { - if ((*meshes)[i].IsString()) { - Ref mesh = r.meshes.Get((*meshes)[i].GetString()); + if ((*meshes)[i].IsNumber()) { + Ref mesh = r.meshes.Get((*meshes)[i].GetUint()); if (mesh) this->meshes.push_back(mesh); } } } - if (Value* camera = FindString(obj, "camera")) { - this->camera = r.cameras.Get(camera->GetString()); + if (Value* camera = FindUInt(obj, "camera")) { + this->camera = r.cameras.Get(camera->GetUint()); if (this->camera) this->camera->id = this->id; } @@ -1204,8 +1036,8 @@ inline void Node::Read(Value& obj, Asset& r) if (r.extensionsUsed.KHR_materials_common) { if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { - if (Value* light = FindString(*ext, "light")) { - this->light = r.lights.Get(light->GetString()); + if (Value* light = FindUInt(*ext, "light")) { + this->light = r.lights.Get(light->GetUint()); } } @@ -1217,8 +1049,8 @@ inline void Scene::Read(Value& obj, Asset& r) { if (Value* array = FindArray(obj, "nodes")) { for (unsigned int i = 0; i < array->Size(); ++i) { - if (!(*array)[i].IsString()) continue; - Ref node = r.nodes.Get((*array)[i].GetString()); + if (!(*array)[i].IsNumber()) continue; + Ref node = r.nodes.Get((*array)[i].GetUint()); if (node) this->nodes.push_back(node); } @@ -1229,13 +1061,14 @@ inline void Scene::Read(Value& obj, Asset& r) inline void AssetMetadata::Read(Document& doc) { // read the version, etc. - float statedVersion = 0; + std::string statedVersion; + if (Value* obj = FindObject(doc, "asset")) { ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "generator", generator); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); - statedVersion = MemberOrDefault(*obj, "version", 0); + statedVersion = MemberOrDefault(*obj, "version", "0.0"); if (Value* profile = FindObject(*obj, "profile")) { ReadMember(*profile, "api", this->profile.api); @@ -1243,14 +1076,16 @@ inline void AssetMetadata::Read(Document& doc) } } - version = std::max(statedVersion, version); + float statedFloatVersion = std::strtof(statedVersion.c_str(), 0); + + version = std::max(statedFloatVersion, version); if (version == 0) { - // if missing version, we'll assume version 1.0... - version = 1; + // if missing version, we'll assume version 2.0... + version = 2; } - if (version != 1) { + if (version != 2) { char msg[128]; ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %.1f", version); throw DeadlyImportError(msg); @@ -1361,12 +1196,14 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) mDicts[i]->AttachToDocument(doc); } - - // Read the "scene" property, which specifies which scene to load // and recursively load everything referenced by it - if (Value* scene = FindString(doc, "scene")) { - this->scene = scenes.Get(scene->GetString()); + if (Value* scene = FindUInt(doc, "scene")) { + unsigned int sceneIndex = scene->GetUint(); + + Ref s = scenes.Get(sceneIndex); + + this->scene = s; } // Clean up From 47c7c3cf506166b483fd4e44e20a58cd1107e763 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 25 Aug 2017 16:09:07 -0400 Subject: [PATCH 03/56] Disambiguate Get methods --- code/glTF2Asset.h | 4 +-- code/glTF2Asset.inl | 59 +++++++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 2e7a694d8..2ec2b84eb 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -1046,9 +1046,9 @@ namespace glTF2 LazyDict(Asset& asset, const char* dictId, const char* extId = 0); ~LazyDict(); - Ref Get(const char* id); + Ref Retrieve(unsigned int i); + Ref Get(unsigned int i); - Ref Get(const std::string& pID) { return Get(pID.c_str()); } Ref Create(const char* id); Ref Create(const std::string& id) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 268deb8a8..97e507ee6 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -194,6 +194,14 @@ inline void LazyDict::DetachFromDocument() template Ref LazyDict::Get(unsigned int i) +{ + + return Ref(mObjs, i); + +} + +template +Ref LazyDict::Retrieve(unsigned int i) { std::string id = std::string(mDictId) + "[" + std::to_string(i) + "]"; @@ -442,7 +450,7 @@ inline void BufferView::Read(Value& obj, Asset& r) { if (Value* bufferVal = FindUInt(obj, "buffer")) { - buffer = r.buffers.Get(bufferVal->GetUint()); + buffer = r.buffers.Retrieve(bufferVal->GetUint()); } byteOffset = MemberOrDefault(obj, "byteOffset", 0u); @@ -457,7 +465,7 @@ inline void Accessor::Read(Value& obj, Asset& r) { if (Value* bufferViewVal = FindUInt(obj, "bufferView")) { - bufferView = r.bufferViews.Get(bufferViewVal->GetUint()); + bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); } byteOffset = MemberOrDefault(obj, "byteOffset", 0u); @@ -615,7 +623,7 @@ inline void Image::Read(Value& obj, Asset& r) ReadMember(*ext, "mimeType", mimeType); if (Value* bufferViewVal = FindUInt(*ext, "bufferView")) { - Ref bv = r.bufferViews.Get(bufferViewVal->GetUint()); + Ref bv = r.bufferViews.Retrieve(bufferViewVal->GetUint()); if (bv) { mDataLength = bv->byteLength; mData = new uint8_t[mDataLength]; @@ -690,11 +698,11 @@ inline void Sampler::SetDefaults() inline void Texture::Read(Value& obj, Asset& r) { if (Value* sourceVal = FindUInt(obj, "source")) { - source = r.images.Get(sourceVal->GetUint()); + source = r.images.Retrieve(sourceVal->GetUint()); } if (Value* samplerVal = FindUInt(obj, "sampler")) { - sampler = r.samplers.Get(samplerVal->GetUint()); + sampler = r.samplers.Retrieve(samplerVal->GetUint()); } } @@ -704,7 +712,7 @@ namespace { //@TODO: update this format if (Value* prop = FindMember(vals, propName)) { if (prop->IsUint()) { - out.texture = r.textures.Get(prop->GetUint()); + out.texture = r.textures.Retrieve(prop->GetUint()); } else { ReadValue(*prop, out.color); @@ -820,7 +828,7 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) if (Value* attrs = FindObject(primitive, "attributes")) { for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { - if (!it->value.IsString()) continue; + if (!it->value.IsUint()) continue; const char* attr = it->name.GetString(); // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. @@ -831,17 +839,17 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) if (GetAttribVector(prim, attr, vec, undPos)) { size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; if ((*vec).size() <= idx) (*vec).resize(idx + 1); - (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetUint()); + (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint()); } } } if (Value* indices = FindUInt(primitive, "indices")) { - prim.indices = pAsset_Root.accessors.Get(indices->GetUint()); + prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint()); } if (Value* material = FindUInt(primitive, "material")) { - prim.material = pAsset_Root.materials.Get(material->GetUint()); + prim.material = pAsset_Root.materials.Retrieve(material->GetUint()); } } } @@ -992,9 +1000,9 @@ inline void Node::Read(Value& obj, Asset& r) this->children.reserve(children->Size()); for (unsigned int i = 0; i < children->Size(); ++i) { Value& child = (*children)[i]; - if (child.IsNumber()) { + if (child.IsUint()) { // get/create the child node - Ref chn = r.nodes.Get(child.GetUint()); + Ref chn = r.nodes.Retrieve(child.GetUint()); if (chn) this->children.push_back(chn); } } @@ -1010,22 +1018,21 @@ inline void Node::Read(Value& obj, Asset& r) ReadMember(obj, "rotation", rotation); } - if (Value* meshes = FindArray(obj, "meshes")) { - unsigned numMeshes = (unsigned)meshes->Size(); + if (Value* mesh = FindUInt(obj, "mesh")) { + //unsigned numMeshes = (unsigned)meshes->Size(); + unsigned numMeshes = 1; - std::vector meshList; + //std::vector meshList; this->meshes.reserve(numMeshes); - for (unsigned i = 0; i < numMeshes; ++i) { - if ((*meshes)[i].IsNumber()) { - Ref mesh = r.meshes.Get((*meshes)[i].GetUint()); - if (mesh) this->meshes.push_back(mesh); - } - } + + Ref meshRef = r.meshes.Retrieve((*mesh).GetUint()); + + if (meshRef) this->meshes.push_back(meshRef); } if (Value* camera = FindUInt(obj, "camera")) { - this->camera = r.cameras.Get(camera->GetUint()); + this->camera = r.cameras.Retrieve(camera->GetUint()); if (this->camera) this->camera->id = this->id; } @@ -1037,7 +1044,7 @@ inline void Node::Read(Value& obj, Asset& r) if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { if (Value* light = FindUInt(*ext, "light")) { - this->light = r.lights.Get(light->GetUint()); + this->light = r.lights.Retrieve(light->GetUint()); } } @@ -1049,8 +1056,8 @@ inline void Scene::Read(Value& obj, Asset& r) { if (Value* array = FindArray(obj, "nodes")) { for (unsigned int i = 0; i < array->Size(); ++i) { - if (!(*array)[i].IsNumber()) continue; - Ref node = r.nodes.Get((*array)[i].GetUint()); + if (!(*array)[i].IsUint()) continue; + Ref node = r.nodes.Retrieve((*array)[i].GetUint()); if (node) this->nodes.push_back(node); } @@ -1201,7 +1208,7 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) if (Value* scene = FindUInt(doc, "scene")) { unsigned int sceneIndex = scene->GetUint(); - Ref s = scenes.Get(sceneIndex); + Ref s = scenes.Retrieve(sceneIndex); this->scene = s; } From 4d59dee5ea25b7f1a7512348de6bc80a09a6d3fa Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 25 Aug 2017 16:52:44 -0400 Subject: [PATCH 04/56] Cache retrieved items via an original index map --- code/glTF2Asset.h | 15 ++++++++------- code/glTF2Asset.inl | 11 +++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 2ec2b84eb..2b37d6a0e 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -382,6 +382,7 @@ namespace glTF2 struct Object { int index; //!< The index of this object within its property container + int oIndex; //!< The original index of this object defined in the JSON std::string id; //!< The globally unique ID used to reference this object std::string name; //!< The user-defined name of this object @@ -1025,14 +1026,14 @@ namespace glTF2 friend class Asset; friend class AssetWriter; - typedef typename std::gltf_unordered_map< std::string, unsigned int > Dict; + typedef typename std::gltf_unordered_map< unsigned int, unsigned int > Dict; - std::vector mObjs; //! The read objects - Dict mObjsById; //! The read objects accessible by id - const char* mDictId; //! ID of the dictionary object - const char* mExtId; //! ID of the extension defining the dictionary - Value* mDict; //! JSON dictionary object - Asset& mAsset; //! The asset instance + std::vector mObjs; //! The read objects + Dict mObjsByOIndex; //! The read objects accessible by original index + const char* mDictId; //! ID of the dictionary object + const char* mExtId; //! ID of the extension defining the dictionary + Value* mDict; //! JSON dictionary object + Asset& mAsset; //! The asset instance void AttachToDocument(Document& doc); void DetachFromDocument(); diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 97e507ee6..062d8318d 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -204,10 +204,8 @@ template Ref LazyDict::Retrieve(unsigned int i) { - std::string id = std::string(mDictId) + "[" + std::to_string(i) + "]"; - - typename Dict::iterator it = mObjsById.find(id); - if (it != mObjsById.end()) { // already created? + typename Dict::iterator it = mObjsByOIndex.find(i); + if (it != mObjsByOIndex.end()) {// already created? return Ref(mObjs, it->second); } @@ -227,7 +225,8 @@ Ref LazyDict::Retrieve(unsigned int i) } T* inst = new T(); - inst->id = id; + inst->id = std::string(mDictId) + "[" + std::to_string(i) + "]"; + inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); @@ -239,7 +238,7 @@ Ref LazyDict::Add(T* obj) { unsigned int idx = unsigned(mObjs.size()); mObjs.push_back(obj); - mObjsById[obj->id] = idx; + mObjsByOIndex[obj->oIndex] = idx; mAsset.mUsedIds[obj->id] = true; return Ref(mObjs, idx); } From 39172feb3e3e9bb0c185209ed996867414ff0f44 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 25 Aug 2017 17:58:41 -0400 Subject: [PATCH 05/56] Start reading pbr materials --- code/glTF2Asset.inl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 062d8318d..27fdd1c01 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -733,6 +733,12 @@ inline void Material::Read(Value& material, Asset& r) ReadMember(*values, "shininess", shininess); } + if (Value* values = FindObject(material, "pbrMetallicRoughness")) { + ReadMaterialProperty(r, *values, "baseColorFactor", this->diffuse); + } + + ReadMember(material, "doubleSided", doubleSided); + if (Value* extensions = FindObject(material, "extensions")) { if (r.extensionsUsed.KHR_materials_common) { if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { From 67eb3b06087021490e43d6c74e05dcd88c6d921a Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 27 Aug 2017 23:47:31 -0400 Subject: [PATCH 06/56] temporarily disable gltf exporting of animations and skins --- code/glTF2Exporter.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 7daef7000..68f2f4420 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -128,7 +128,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportScene(); - ExportAnimations(); + //ExportAnimations(); AssetWriter writer(*mAsset); @@ -414,7 +414,7 @@ Ref FindSkeletonRootJoint(Ref& skinRef) return parentNodeRef; } -void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref& bufferRef, Ref& skinRef, std::vector& inverseBindMatricesData) +/*void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref& bufferRef, Ref& skinRef, std::vector& inverseBindMatricesData) { if (aimesh->mNumBones < 1) { return; @@ -491,7 +491,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, RefHasBones()) { - ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); - } + /*************** Skins ****************/ + /*if(aim->HasBones()) { + ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); + }*/ /****************** Compression ******************/ ///TODO: animation: weights, joints. @@ -942,7 +942,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref bufferRef = mAsset->buffers.Get(unsigned (0)); @@ -963,7 +963,7 @@ void glTF2Exporter::ExportAnimations() name = mAsset->FindUniqueID(name, "animation"); Ref animRef = mAsset->animations.Create(name); - /******************* Parameters ********************/ + // Parameters ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, anim->mTicksPerSecond); for (unsigned int j = 0; j < 3; ++j) { @@ -1011,7 +1011,7 @@ void glTF2Exporter::ExportAnimations() // } } // End: for-loop mNumAnimations -} +} */ #endif // ASSIMP_BUILD_NO_GLTF_EXPORTER From b42d785afebd313f8a531dc8cf832d80ecd50910 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 27 Aug 2017 23:47:54 -0400 Subject: [PATCH 07/56] Start managing and importing gltf2 pbr materials --- code/glTF2Asset.h | 40 +++++++++++++++++++++++++++++----------- code/glTF2Asset.inl | 19 +++++++++++++++---- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 2b37d6a0e..5d99735b2 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -671,11 +671,18 @@ namespace glTF2 inline void SetData(uint8_t* data, size_t length, Asset& r); }; - //! Holds a material property that can be a texture or a color - struct TexProperty + struct ColorProperty + { + union { + vec4, vec3 + } color; + } + + //! Holds a material property that can be a texture or a color (fallback for glTF 1) + struct FallbackTexProperty { Ref texture; - vec4 color; + ColorProperty color; }; //! The material appearance of a primitive. @@ -694,16 +701,27 @@ namespace glTF2 Technique_CONSTANT }; - TexProperty ambient; - TexProperty diffuse; - TexProperty specular; - TexProperty emission; - Ref normal; + //PBR metallic roughness properties + ColorProperty baseColor; + Ref baseColorTexture; + Ref metallicRoughnessTexture; + float metallicFactor; + float roughnessFactor; + //other basic material properties + Ref normalTexture; + Ref occlusionTexture; + Ref emissiveTexture; + ColorProperty emissiveFactor; + std::string alphaMode; + float alphaCutoff; bool doubleSided; - bool transparent; - float transparency; - float shininess; + + //fallback material properties (compatible with non-pbr defintions) + FallbackTexProperty diffuse; + FallbackTexProperty emissive; + FallbackTexProperty specular; + Ref normal; Technique technique; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 27fdd1c01..bf8cb5a36 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -725,18 +725,29 @@ inline void Material::Read(Value& material, Asset& r) SetDefaults(); if (Value* values = FindObject(material, "values")) { - ReadMaterialProperty(r, *values, "ambient", this->ambient); - ReadMaterialProperty(r, *values, "diffuse", this->diffuse); - ReadMaterialProperty(r, *values, "specular", this->specular); + ReadMember(*values, "transparency", transparency); - ReadMember(*values, "shininess", shininess); } if (Value* values = FindObject(material, "pbrMetallicRoughness")) { + //pbr + ReadMaterialProperty(r, *values, "baseColorFactor", this->baseColor); + ReadMaterialProperty(r, *values, "baseColorTexture", this->baseColorTexture); + + //non-pbr fallback ReadMaterialProperty(r, *values, "baseColorFactor", this->diffuse); + ReadMaterialProperty(r, *values, "baseColorTexture", this->diffuse); + + ReadMember(*values, "metallicFactor", metallicFactor); } + ReadMaterialProperty(r, *values, "normalTexture", this->normalTexture); + ReadMaterialProperty(r, *values, "normalTexture", this->normal); + ReadMaterialProperty(r, *values, "occlusionTexture", this->occlusionTexture); + ReadMaterialProperty(r, *values, "emissiveTexture", this->emissiveTexture); + ReadMember(*values, "metallicFactor", emissiveFactor); + ReadMember(material, "doubleSided", doubleSided); if (Value* extensions = FindObject(material, "extensions")) { From 6b4286abf69a6bdff733dcf88a13891c21892985 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 27 Aug 2017 23:50:22 -0400 Subject: [PATCH 08/56] check in gltf2 models to test directory Remove un-needed test models --- .../BoxTextured-glTF-Binary/BoxTextured.glb | Bin 0 -> 4696 bytes .../BoxTextured.gltf | 181 +++++++++++ .../BoxTextured.gltf | 197 ++++++++++++ .../BoxTextured0.bin | Bin 0 -> 840 bytes .../CesiumLogoFlat.png | Bin 0 -> 2433 bytes .../BoxTextured.gltf | 282 ++++++++++++++++++ .../BoxTextured0.bin | Bin 0 -> 840 bytes .../BoxTextured0.vert | 17 ++ .../BoxTextured1.frag | 29 ++ .../CesiumLogoFlat.png | Bin 0 -> 2433 bytes .../glTF2/BoxTextured-glTF/BoxTextured.gltf | 181 +++++++++++ .../glTF2/BoxTextured-glTF/BoxTextured0.bin | Bin 0 -> 840 bytes .../glTF2/BoxTextured-glTF/CesiumLogoFlat.png | Bin 0 -> 2433 bytes 13 files changed, 887 insertions(+) create mode 100644 test/models/glTF2/BoxTextured-glTF-Binary/BoxTextured.glb create mode 100644 test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf create mode 100644 test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf create mode 100644 test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured0.bin create mode 100644 test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/CesiumLogoFlat.png create mode 100644 test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured.gltf create mode 100644 test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.bin create mode 100644 test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert create mode 100644 test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag create mode 100644 test/models/glTF2/BoxTextured-glTF-techniqueWebGL/CesiumLogoFlat.png create mode 100644 test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf create mode 100644 test/models/glTF2/BoxTextured-glTF/BoxTextured0.bin create mode 100644 test/models/glTF2/BoxTextured-glTF/CesiumLogoFlat.png diff --git a/test/models/glTF2/BoxTextured-glTF-Binary/BoxTextured.glb b/test/models/glTF2/BoxTextured-glTF-Binary/BoxTextured.glb new file mode 100644 index 0000000000000000000000000000000000000000..03cd2acf941a0838722aa3e7243d33a8f459c22e GIT binary patch literal 4696 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 Jbq)o|e*xHM<_Q1* literal 0 HcmV?d00001 diff --git a/test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf new file mode 100644 index 000000000..c9c461495 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf @@ -0,0 +1,181 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "name": "Texture" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "data:image/png;base64,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" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" + } + ] +} diff --git a/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf new file mode 100644 index 000000000..b286239fa --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf @@ -0,0 +1,197 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "extensions": { + "KHR_materials_pbrSpecularGlossiness": { + "diffuseTexture": { + "index": 0 + }, + "specularFactor": [ + 0.20000000298023225, + 0.20000000298023225, + 0.20000000298023225 + ], + "glossinessFactor": 1.0 + } + }, + "name": "Texture" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "CesiumLogoFlat.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "BoxTextured0.bin" + } + ], + "extensionsUsed": [ + "KHR_materials_pbrSpecularGlossiness" + ] +} diff --git a/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured0.bin b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured0.bin new file mode 100644 index 0000000000000000000000000000000000000000..d2a73551f9456732c7ca85b9d70895f5d9ab8171 GIT binary patch literal 840 zcma)4TMmLS5FAugR8)K(r@fgRg`3F9)Sc2X4N+i|$-K6U9|D@%NdZH8sMCdXhgs?; z>8CE)+Yvq1hwmphbb0bSz9n3Qv{?B+?(fNy1()2HW=AbfwKB4_dS!i9PnJ%1er4>H zi~S!ZIHJM{XG4VxuDIcDxZ(qtxm=$B literal 0 HcmV?d00001 diff --git a/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/CesiumLogoFlat.png b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/CesiumLogoFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..45d502ed2610974189307ad542b05b70df14abd4 GIT binary patch literal 2433 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 literal 0 HcmV?d00001 diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert new file mode 100644 index 000000000..05d5e82c2 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert @@ -0,0 +1,17 @@ +precision highp float; +uniform mat4 u_modelViewMatrix; +uniform mat4 u_projectionMatrix; +uniform mat3 u_normalMatrix; +attribute vec3 a_position; +varying vec3 v_position; +attribute vec3 a_normal; +varying vec3 v_normal; +attribute vec2 a_texcoord0; +varying vec2 v_texcoord0; +void main(void) { + vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); + v_position = pos.xyz; + gl_Position = u_projectionMatrix * pos; + v_normal = u_normalMatrix * a_normal; + v_texcoord0 = a_texcoord0; +} diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag new file mode 100644 index 000000000..3850980a0 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag @@ -0,0 +1,29 @@ +precision highp float; +uniform sampler2D u_diffuse; +uniform vec4 u_specular; +uniform float u_shininess; +uniform float u_transparency; +varying vec3 v_position; +varying vec3 v_normal; +varying vec2 v_texcoord0; +void main(void) { + vec3 normal = normalize(v_normal); + vec4 diffuse = texture2D(u_diffuse, v_texcoord0); + vec3 diffuseLight = vec3(0.0, 0.0, 0.0); + vec3 specular = u_specular.rgb; + vec3 specularLight = vec3(0.0, 0.0, 0.0); + vec3 ambient = diffuse.rgb; + vec3 viewDir = -normalize(v_position); + vec3 ambientLight = vec3(0.0, 0.0, 0.0); + ambientLight += vec3(0.2, 0.2, 0.2); + vec3 l = vec3(0.0, 0.0, 1.0); + diffuseLight += vec3(1.0, 1.0, 1.0) * max(dot(normal, l), 0.); + vec3 reflectDir = reflect(-l, normal); + float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess)); + specularLight += vec3(1.0, 1.0, 1.0) * specularIntensity; + vec3 color = vec3(0.0, 0.0, 0.0); + color += diffuse.rgb * diffuseLight; + color += specular * specularLight; + color += ambient * ambientLight; + gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency); +} diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/CesiumLogoFlat.png b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/CesiumLogoFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..45d502ed2610974189307ad542b05b70df14abd4 GIT binary patch literal 2433 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 literal 0 HcmV?d00001 diff --git a/test/models/glTF2/BoxTextured-glTF/CesiumLogoFlat.png b/test/models/glTF2/BoxTextured-glTF/CesiumLogoFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..45d502ed2610974189307ad542b05b70df14abd4 GIT binary patch literal 2433 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 Date: Wed, 30 Aug 2017 17:25:11 -0400 Subject: [PATCH 09/56] Working read, import, export, and write of gltf2 (pbr) material --- code/glTF2Asset.h | 51 ++++++++------ code/glTF2Asset.inl | 115 +++++++++++++++++++----------- code/glTF2AssetWriter.inl | 145 ++++++++++++++++++++++++++++++++------ code/glTF2Exporter.cpp | 50 +++++++------ code/glTF2Exporter.h | 10 ++- code/glTF2Importer.cpp | 93 +++++++++++++++++------- 6 files changed, 329 insertions(+), 135 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 5d99735b2..509fef115 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -133,7 +133,6 @@ namespace glTF2 struct Light; struct Skin; - // Vec/matrix types, as raw float arrays typedef float (vec3)[3]; typedef float (vec4)[4]; @@ -671,20 +670,30 @@ namespace glTF2 inline void SetData(uint8_t* data, size_t length, Asset& r); }; - struct ColorProperty - { - union { - vec4, vec3 - } color; - } - - //! Holds a material property that can be a texture or a color (fallback for glTF 1) - struct FallbackTexProperty + struct TextureInfo { Ref texture; - ColorProperty color; + unsigned int index; + unsigned int texCoord = 0; }; + struct NormalTextureInfo : TextureInfo + { + float scale = 1; + }; + + struct OcclusionTextureInfo : TextureInfo + { + float strength = 1; + }; + + //! Holds a material property that can be a texture or a color (fallback for glTF 1) + /*struct FallbackTexProperty + { + Ref texture; + vec4 color; + };*/ + //! The material appearance of a primitive. struct Material : public Object { @@ -702,26 +711,26 @@ namespace glTF2 }; //PBR metallic roughness properties - ColorProperty baseColor; - Ref baseColorTexture; - Ref metallicRoughnessTexture; + vec4 baseColorFactor; + TextureInfo baseColorTexture; + TextureInfo metallicRoughnessTexture; float metallicFactor; float roughnessFactor; //other basic material properties - Ref normalTexture; - Ref occlusionTexture; - Ref emissiveTexture; - ColorProperty emissiveFactor; + NormalTextureInfo normalTexture; + OcclusionTextureInfo occlusionTexture; + TextureInfo emissiveTexture; + vec3 emissiveFactor; std::string alphaMode; float alphaCutoff; bool doubleSided; //fallback material properties (compatible with non-pbr defintions) - FallbackTexProperty diffuse; - FallbackTexProperty emissive; + /*FallbackTexProperty diffuse; + FallbackTexProperty emission; FallbackTexProperty specular; - Ref normal; + Ref normal;*/ Technique technique; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index bf8cb5a36..94858044d 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -128,6 +128,12 @@ namespace { return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; } + inline Value* FindNumber(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0; + } + inline Value* FindUInt(Value& val, const char* id) { Value::MemberIterator it = val.FindMember(id); @@ -225,7 +231,7 @@ Ref LazyDict::Retrieve(unsigned int i) } T* inst = new T(); - inst->id = std::string(mDictId) + "[" + std::to_string(i) + "]"; + inst->id = std::string(mDictId) + "_" + std::to_string(i); inst->oIndex = i; ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); @@ -706,15 +712,42 @@ inline void Texture::Read(Value& obj, Asset& r) } namespace { - inline void ReadMaterialProperty(Asset& r, Value& vals, const char* propName, TexProperty& out) + inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) + { + if (Value* index = FindUInt(*prop, "index")) { + out.texture = r.textures.Retrieve(index->GetUint()); + } + + if (Value* texcoord = FindUInt(*prop, "texCoord")) { + out.texCoord = texcoord->GetUint(); + } + } + + inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, TextureInfo& out) { - //@TODO: update this format if (Value* prop = FindMember(vals, propName)) { - if (prop->IsUint()) { - out.texture = r.textures.Retrieve(prop->GetUint()); + SetTextureProperties(r, prop, out); + } + } + + inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, NormalTextureInfo& out) + { + if (Value* prop = FindMember(vals, propName)) { + SetTextureProperties(r, prop, out); + + if (Value* scale = FindNumber(*prop, "scale")) { + out.scale = scale->GetDouble(); } - else { - ReadValue(*prop, out.color); + } + } + + inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, OcclusionTextureInfo& out) + { + if (Value* prop = FindMember(vals, propName)) { + SetTextureProperties(r, prop, out); + + if (Value* strength = FindNumber(*prop, "strength")) { + out.strength = strength->GetDouble(); } } } @@ -724,33 +757,24 @@ inline void Material::Read(Value& material, Asset& r) { SetDefaults(); - if (Value* values = FindObject(material, "values")) { - - - ReadMember(*values, "transparency", transparency); - } - if (Value* values = FindObject(material, "pbrMetallicRoughness")) { - //pbr - ReadMaterialProperty(r, *values, "baseColorFactor", this->baseColor); - ReadMaterialProperty(r, *values, "baseColorTexture", this->baseColorTexture); - - //non-pbr fallback - ReadMaterialProperty(r, *values, "baseColorFactor", this->diffuse); - ReadMaterialProperty(r, *values, "baseColorTexture", this->diffuse); - - ReadMember(*values, "metallicFactor", metallicFactor); + ReadMember(*values, "baseColorFactor", this->baseColorFactor); + ReadTextureProperty(r, *values, "baseColorTexture", this->baseColorTexture); + ReadTextureProperty(r, *values, "metallicRoughnessTexture", this->metallicRoughnessTexture); + ReadMember(*values, "metallicFactor", this->metallicFactor); + ReadMember(*values, "roughnessFactor", this->roughnessFactor); } - ReadMaterialProperty(r, *values, "normalTexture", this->normalTexture); - ReadMaterialProperty(r, *values, "normalTexture", this->normal); - ReadMaterialProperty(r, *values, "occlusionTexture", this->occlusionTexture); - ReadMaterialProperty(r, *values, "emissiveTexture", this->emissiveTexture); - ReadMember(*values, "metallicFactor", emissiveFactor); + ReadTextureProperty(r, material, "normalTexture", this->normalTexture); + ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture); + ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture); + ReadMember(material, "emissiveFactor", this->emissiveFactor); - ReadMember(material, "doubleSided", doubleSided); + ReadMember(material, "doubleSided", this->doubleSided); + ReadMember(material, "alphaMode", this->alphaMode); + ReadMember(material, "alphaCutoff", this->alphaCutoff); - if (Value* extensions = FindObject(material, "extensions")) { + /* if (Value* extensions = FindObject(material, "extensions")) { if (r.extensionsUsed.KHR_materials_common) { if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { if (Value* tnq = FindString(*ext, "technique")) { @@ -762,9 +786,9 @@ inline void Material::Read(Value& material, Asset& r) } if (Value* values = FindObject(*ext, "values")) { - ReadMaterialProperty(r, *values, "ambient", this->ambient); - ReadMaterialProperty(r, *values, "diffuse", this->diffuse); - ReadMaterialProperty(r, *values, "specular", this->specular); + ReadTextureProperty(r, *values, "ambient", this->ambient); + ReadTextureProperty(r, *values, "diffuse", this->diffuse); + ReadTextureProperty(r, *values, "specular", this->specular); ReadMember(*values, "doubleSided", doubleSided); ReadMember(*values, "transparent", transparent); @@ -773,25 +797,28 @@ inline void Material::Read(Value& material, Asset& r) } } } - } + } */ } namespace { void SetVector(vec4& v, float x, float y, float z, float w) { v[0] = x; v[1] = y; v[2] = z; v[3] = w; } + + void SetVector(vec3& v, float x, float y, float z) + { v[0] = x; v[1] = y; v[2] = z; } } inline void Material::SetDefaults() { - SetVector(ambient.color, 0, 0, 0, 1); - SetVector(diffuse.color, 0, 0, 0, 1); - SetVector(specular.color, 0, 0, 0, 1); - SetVector(emission.color, 0, 0, 0, 1); + //pbr materials + SetVector(baseColorFactor, 1, 1, 1, 1); + SetVector(emissiveFactor, 0, 0, 0); + metallicFactor = 1.0; + roughnessFactor = 1.0; + alphaMode = "OPAQUE"; + alphaCutoff = 0.5; doubleSided = false; - transparent = false; - transparency = 1.0; - shininess = 0.0; technique = Technique_undefined; } @@ -833,6 +860,10 @@ namespace { inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) { + if (Value* name = FindMember(pJSON_Object, "name")) { + this->name = name->GetString(); + } + /****************** Mesh primitives ******************/ if (Value* primitives = FindArray(pJSON_Object, "primitives")) { this->primitives.resize(primitives->Size()); @@ -1055,7 +1086,7 @@ inline void Node::Read(Value& obj, Asset& r) // TODO load "skeletons", "skin", "jointName" - if (Value* extensions = FindObject(obj, "extensions")) { + /*if (Value* extensions = FindObject(obj, "extensions")) { if (r.extensionsUsed.KHR_materials_common) { if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { @@ -1065,7 +1096,7 @@ inline void Node::Read(Value& obj, Asset& r) } } - } + }*/ } inline void Scene::Read(Value& obj, Asset& r) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index ed8ee80ea..a939e38d6 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -72,6 +72,12 @@ namespace glTF2 { return val; } + inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& al) { + val.SetDouble(r); + + return val; + } + template inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref >& v, MemoryPoolAllocator<>& al) { if (v.empty()) return; @@ -196,51 +202,148 @@ namespace glTF2 { } namespace { - inline void WriteTex(Value& obj, Ref texture, const char* propName, MemoryPoolAllocator<>& al) + inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al) { - if (texture) { + tex.SetObject(); + tex.AddMember("index", t.texture->index, al); + + if (t.texCoord != 0) { + tex.AddMember("texCoord", t.texCoord, al); + } + } + + inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al) + { + + if (t.texture) { Value tex; - tex.SetObject(); - tex.AddMember("index", texture->index, al); + + SetTexBasic(t, tex, al); + obj.AddMember(StringRef(propName), tex, al); } } - inline void WriteColorOrTex(Value& obj, TexProperty& prop, const char* propName, MemoryPoolAllocator<>& al) + inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al) { - WriteTex(obj, prop.texture, propName, al); - if (!prop.texture) { - Value col; - obj.AddMember(StringRef(propName), MakeValue(col, prop.color, al), al); + + if (t.texture) { + Value tex; + + SetTexBasic(t, tex, al); + + if (t.scale != 1) { + tex.AddMember("scale", t.scale, al); + } + + obj.AddMember(StringRef(propName), tex, al); } } + + inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al) + { + + if (t.texture) { + Value tex; + + SetTexBasic(t, tex, al); + + if (t.strength != 1) { + tex.AddMember("strength", t.strength, al); + } + + obj.AddMember(StringRef(propName), tex, al); + } + } + + template + inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al) + { + Value arr; + obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al); + } + + template + inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, float(&defaultVal)[N], MemoryPoolAllocator<>& al) + { + if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) { + WriteVec(obj, prop, propName, al); + } + } + + inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al) + { + Value num; + obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al); + } } inline void Write(Value& obj, Material& m, AssetWriter& w) { - if (m.transparent) { - obj.AddMember("alphaMode", "BLEND", w.mAl); + if (!m.name.empty()) { + obj.AddMember("name", m.name, w.mAl); } - Value v; + Value pbrMetallicRoughness; + pbrMetallicRoughness.SetObject(); + { + WriteTex(pbrMetallicRoughness, m.baseColorTexture, "baseColorTexture", w.mAl); + WriteTex(pbrMetallicRoughness, m.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl); + + //@TODO: define this as a constant? + vec4 defaultEmissiveFactor = {1, 1, 1, 1}; + WriteVec(pbrMetallicRoughness, m.baseColorFactor, "baseColorFactor", defaultEmissiveFactor, w.mAl); + + if (m.metallicFactor != 1) { + WriteFloat(pbrMetallicRoughness, m.metallicFactor, "metallicFactor", w.mAl); + } + + if (m.roughnessFactor != 1) { + WriteFloat(pbrMetallicRoughness, m.roughnessFactor, "roughnessFactor", w.mAl); + } + } + + if (pbrMetallicRoughness.MemberCount() > 0) { + obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl); + } + + WriteTex(obj, m.normalTexture, "normalTexture", w.mAl); + WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl); + WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl); + + //@TODO: define this as a constant? + vec3 defaultEmissiveFactor = {0, 0, 0}; + WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl); + + if (m.alphaCutoff != 0.5) { + WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl); + } + + if (m.alphaMode != "OPAQUE") { + obj.AddMember("alphaMode", m.alphaMode, w.mAl); + } + + if (m.doubleSided) { + obj.AddMember("doubleSided", m.doubleSided, w.mAl); + } + + /*Value v; v.SetObject(); { if (m.transparent && !m.diffuse.texture) { m.diffuse.color[3] = m.transparency; } - WriteColorOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl); - WriteColorOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl); - WriteColorOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl); - WriteColorOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl); + WriteVecOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl); + WriteVecOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl); + WriteVecOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl); + WriteVecOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl); v.AddMember("shininessFactor", m.shininess, w.mAl); } v.AddMember("type", "commonPhong", w.mAl); Value ext; ext.SetObject(); ext.AddMember("KHR_materials_common", v, w.mAl); - obj.AddMember("extensions", ext, w.mAl); - - WriteTex(obj, m.normal, "normalTexture", w.mAl); + obj.AddMember("extensions", ext, w.mAl);*/ } namespace { @@ -263,8 +366,6 @@ namespace glTF2 { inline void Write(Value& obj, Mesh& m, AssetWriter& w) { - /********************* Name **********************/ - obj.AddMember("name", m.name, w.mAl); /**************** Mesh extensions ****************/ if(m.Extension.size() > 0) @@ -617,7 +718,7 @@ namespace glTF2 { exts.PushBack(StringRef("KHR_binary_glTF"), mAl); // This is used to export common materials with GLTF 2. - exts.PushBack(StringRef("KHR_materials_common"), mAl); + //exts.PushBack(StringRef("KHR_materials_common"), mAl); } if (!exts.Empty()) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 68f2f4420..f59c280f1 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -234,12 +234,6 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu return acc; } -namespace { - void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) { - if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {} - } -} - void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture) { std::string samplerId = mAsset->FindUniqueID("", "sampler"); @@ -286,11 +280,11 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture) texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear; } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt) +void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt, unsigned int slot = 0) { aiString tex; if (mat->GetTextureCount(tt) > 0) { - if (mat->Get(AI_MATKEY_TEXTURE(tt, 0), tex) == AI_SUCCESS) { + if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { std::string path = tex.C_Str(); if (path.size() > 0) { @@ -332,15 +326,21 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe } } -void glTF2Exporter::GetMatColorOrTex(const aiMaterial* mat, TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt) +void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx) { aiColor4D col; if (mat->Get(propName, type, idx, col) == AI_SUCCESS) { - prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a; + prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a; } - GetMatTex(mat, prop.texture, tt); } +void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx) +{ + aiColor3D col; + if (mat->Get(propName, type, idx, col) == AI_SUCCESS) { + prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; + } +} void glTF2Exporter::ExportMaterials() { @@ -348,7 +348,6 @@ void glTF2Exporter::ExportMaterials() for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; - std::string name; if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { name = aiName.C_Str(); @@ -357,15 +356,20 @@ void glTF2Exporter::ExportMaterials() Ref m = mAsset->materials.Create(name); - GetMatColorOrTex(mat, m->ambient, AI_MATKEY_COLOR_AMBIENT, aiTextureType_AMBIENT); - GetMatColorOrTex(mat, m->diffuse, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_DIFFUSE); - GetMatColorOrTex(mat, m->specular, AI_MATKEY_COLOR_SPECULAR, aiTextureType_SPECULAR); - GetMatColorOrTex(mat, m->emission, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_EMISSIVE); - GetMatTex(mat, m->normal, aiTextureType_NORMALS); + GetMatTex(mat, m->baseColorTexture.texture, aiTextureType_DIFFUSE); + GetMatTex(mat, m->metallicRoughnessTexture.texture, aiTextureType_UNKNOWN, 0);//get unknown slot + GetMatTex(mat, m->emissiveTexture.texture, aiTextureType_EMISSIVE); + GetMatTex(mat, m->normalTexture.texture, aiTextureType_NORMALS); + GetMatTex(mat, m->occlusionTexture.texture, aiTextureType_LIGHTMAP); - m->transparent = mat->Get(AI_MATKEY_OPACITY, m->transparency) == aiReturn_SUCCESS && m->transparency != 1.0; + GetMatColor(mat, m->baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); + GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE); - GetMatScalar(mat, m->shininess, AI_MATKEY_SHININESS); + mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); + mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff); + mat->Get("$mat.gltf.metallicFactor", 0, 0, m->metallicFactor); + mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->roughnessFactor); + mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode); } } @@ -566,13 +570,17 @@ void glTF2Exporter::ExportMeshes() DefaultLogger::get()->warn("GLTF: can not use Open3DGC-compression: " + msg); comp_allow = false; - } + } - std::string meshId = mAsset->FindUniqueID(aim->mName.C_Str(), "mesh"); + std::string name = aim->mName.C_Str(); + + std::string meshId = mAsset->FindUniqueID(name, "mesh"); Ref m = mAsset->meshes.Create(meshId); m->primitives.resize(1); Mesh::Primitive& p = m->primitives.back(); + m->name = name; + p.material = mAsset->materials.Get(aim->mMaterialIndex); /******************* Vertices ********************/ diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 17cc9cfdc..2ba0143bf 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -66,8 +66,13 @@ namespace glTF2 class Asset; struct TexProperty; + struct TextureInfo; struct Node; struct Texture; + + // Vec/matrix types, as raw float arrays + typedef float (vec3)[3]; + typedef float (vec4)[4]; } namespace Assimp @@ -102,8 +107,9 @@ namespace Assimp void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture); - void GetMatTex(const aiMaterial* mat, glTF2::Ref& texture, aiTextureType tt); - void GetMatColorOrTex(const aiMaterial* mat, glTF2::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt); + void GetMatTex(const aiMaterial* mat, glTF2::Ref& texture, aiTextureType tt, unsigned int slot); + void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx); + void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx); void ExportMetadata(); void ExportMaterials(); void ExportMeshes(); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index bd4f42600..25cb39168 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -141,6 +141,11 @@ static void CopyValue(const glTF2::vec4& v, aiColor3D& out) out.r = v[0]; out.g = v[1]; out.b = v[2]; } +static void CopyValue(const glTF2::vec3& v, aiColor4D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0; +} + static void CopyValue(const glTF2::vec3& v, aiVector3D& out) { out.x = v[0]; out.y = v[1]; out.z = v[2]; @@ -159,28 +164,56 @@ static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o) o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; } -inline void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TexProperty prop, aiMaterial* mat, - aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) +inline void SetMaterialColorProperty(Asset& r, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) { - if (prop.texture) { - if (prop.texture->source) { - aiString uri(prop.texture->source->uri); + aiColor4D col; + CopyValue(prop, col); + mat->AddProperty(&col, 1, pKey, type, idx); +} - int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; - if (texIdx != -1) { // embedded - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) - uri.data[0] = '*'; - uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); - } +inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) +{ + vec4 prop4; + prop4[0] = prop[0]; + prop4[1] = prop[1]; + prop4[2] = prop[2]; + prop4[3] = 1; + + return SetMaterialColorProperty(r, prop4, mat, pKey, type, idx); +} + +inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, int texSlot) +{ + if (prop.texture && prop.texture->source) { + aiString uri(prop.texture->source->uri); + + int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; + if (texIdx != -1) { // embedded + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + uri.data[0] = '*'; + uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); + } + + if (texSlot < 0) { mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); } + else { + mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, + texSlot)); + } } - else { - aiColor4D col; - CopyValue(prop.color, col); - mat->AddProperty(&col, 1, pKey, type, idx); - } +} + +//import textures that are only supported in pbr contexts +inline void SetMaterialPBRTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, unsigned int texSlot) +{ + return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, aiTextureType_UNKNOWN, texSlot); +} + +inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType) +{ + return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, texType, -1); } void glTF2Importer::ImportMaterials(glTF2::Asset& r) @@ -193,18 +226,23 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) Material& mat = r.materials[i]; - /*if (!mat.name.empty())*/ { - aiString str(mat.id /*mat.name*/); - aimat->AddProperty(&str, AI_MATKEY_NAME); - } + aiString str(mat.id); + aimat->AddProperty(&str, AI_MATKEY_NAME); - SetMaterialColorProperty(embeddedTexIdxs, r, mat.diffuse, aimat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialColorProperty(embeddedTexIdxs, r, mat.specular, aimat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR); - SetMaterialColorProperty(embeddedTexIdxs, r, mat.ambient, aimat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT); + SetMaterialColorProperty(r, mat.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.baseColorTexture, aimat, aiTextureType_DIFFUSE); + SetMaterialPBRTextureProperty(embeddedTexIdxs, r, mat.metallicRoughnessTexture, aimat, 0); + aimat->AddProperty(&mat.metallicFactor, 1, "$mat.gltf.metallicFactor"); + aimat->AddProperty(&mat.roughnessFactor, 1, "$mat.gltf.roughnessFactor"); - if (mat.shininess > 0.f) { - aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS); - } + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE); + SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE); + + aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); + aimat->AddProperty(&mat.alphaMode, 1, "$mat.gltf.alphaMode"); + aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff"); } } @@ -295,7 +333,8 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) aiMesh* aim = new aiMesh(); meshes.push_back(aim); - aim->mName = mesh.id; + aim->mName = mesh.name.empty() ? mesh.id : mesh.name; + if (mesh.primitives.size() > 1) { size_t& len = aim->mName.length; aim->mName.data[len] = '-'; From 0cf69479c30c97a6f4bfeb00ffdceab5749b2b5f Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 30 Aug 2017 21:50:06 -0400 Subject: [PATCH 10/56] Use `!ObjectEmpty()` vs. `MemberCount() > 0` --- code/glTF2AssetWriter.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index a939e38d6..bd16a7023 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -303,7 +303,7 @@ namespace glTF2 { } } - if (pbrMetallicRoughness.MemberCount() > 0) { + if (!pbrMetallicRoughness.ObjectEmpty()) { obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl); } From 7615a97cd3164d624f3762dd3edf49f6e461a88d Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 30 Aug 2017 23:51:52 -0400 Subject: [PATCH 11/56] Remove redundant function --- code/glTF2Importer.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 25cb39168..b1bbf8349 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -205,12 +205,6 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& } } -//import textures that are only supported in pbr contexts -inline void SetMaterialPBRTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, unsigned int texSlot) -{ - return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, aiTextureType_UNKNOWN, texSlot); -} - inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType) { return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, texType, -1); @@ -231,7 +225,7 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) SetMaterialColorProperty(r, mat.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.baseColorTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialPBRTextureProperty(embeddedTexIdxs, r, mat.metallicRoughnessTexture, aimat, 0); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.metallicRoughnessTexture, aimat, aiTextureType_UNKNOWN, 0); aimat->AddProperty(&mat.metallicFactor, 1, "$mat.gltf.metallicFactor"); aimat->AddProperty(&mat.roughnessFactor, 1, "$mat.gltf.roughnessFactor"); From 863458cd4a30632350685f8aee88ed420118f577 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 31 Aug 2017 01:35:10 -0400 Subject: [PATCH 12/56] Start removing materials common, and adding pbrSpecularGlossiness --- code/glTF2Asset.h | 69 +++++---------------------------------- code/glTF2Asset.inl | 64 ++++++++++++------------------------ code/glTF2AssetWriter.h | 2 +- code/glTF2AssetWriter.inl | 42 +++++++++++++++--------- code/glTF2Importer.cpp | 7 ++++ 5 files changed, 63 insertions(+), 121 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 509fef115..b19de747a 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_binary_glTF: full - * KHR_materials_common: full */ #ifndef GLTF2ASSET_H_INC #define GLTF2ASSET_H_INC @@ -697,19 +696,6 @@ namespace glTF2 //! The material appearance of a primitive. struct Material : public Object { - //Ref source; //!< The ID of the technique. - //std::gltf_unordered_map values; //!< A dictionary object of parameter values. - - //! Techniques defined by KHR_materials_common - enum Technique - { - Technique_undefined = 0, - Technique_BLINN, - Technique_PHONG, - Technique_LAMBERT, - Technique_CONSTANT - }; - //PBR metallic roughness properties vec4 baseColorFactor; TextureInfo baseColorTexture; @@ -726,13 +712,12 @@ namespace glTF2 float alphaCutoff; bool doubleSided; - //fallback material properties (compatible with non-pbr defintions) - /*FallbackTexProperty diffuse; - FallbackTexProperty emission; - FallbackTexProperty specular; - Ref normal;*/ - - Technique technique; + //extension: KHR_materials_pbrSpecularGlossiness + vec4 diffuseFactor; + vec3 specularFactor; + float glossinessFactor; + TextureInfo diffuseTexture; + TextureInfo specularGlossinessTexture; Material() { SetDefaults(); } void Read(Value& obj, Asset& r); @@ -943,35 +928,6 @@ namespace glTF2 void Read(Value& obj, Asset& r); }; - - //! A light (from KHR_materials_common extension) - struct Light : public Object - { - enum Type - { - Type_undefined, - Type_ambient, - Type_directional, - Type_point, - Type_spot - }; - - Type type; - - vec4 color; - float distance; - float constantAttenuation; - float linearAttenuation; - float quadraticAttenuation; - float falloffAngle; - float falloffExponent; - - Light() {} - void Read(Value& obj, Asset& r); - - void SetDefaults(); - }; - struct Animation : public Object { struct AnimSampler { @@ -1152,7 +1108,7 @@ namespace glTF2 struct Extensions { bool KHR_binary_glTF; - bool KHR_materials_common; + bool KHR_materials_pbrSpecularGlossiness; } extensionsUsed; @@ -1170,16 +1126,11 @@ namespace glTF2 LazyDict materials; LazyDict meshes; LazyDict nodes; - //LazyDict programs; LazyDict samplers; LazyDict scenes; - //LazyDict shaders; LazyDict skins; - //LazyDict techniques; LazyDict textures; - LazyDict lights; // KHR_materials_common ext - Ref scene; public: @@ -1195,14 +1146,10 @@ namespace glTF2 , materials (*this, "materials") , meshes (*this, "meshes") , nodes (*this, "nodes") - //, programs (*this, "programs") , samplers (*this, "samplers") , scenes (*this, "scenes") - //, shaders (*this, "shaders") - , skins (*this, "skins") - //, techniques (*this, "techniques") + , skins (*this, "skins") , textures (*this, "textures") - , lights (*this, "lights", "KHR_materials_common") { memset(&extensionsUsed, 0, sizeof(extensionsUsed)); } diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 94858044d..3d53bfccf 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -757,12 +757,12 @@ inline void Material::Read(Value& material, Asset& r) { SetDefaults(); - if (Value* values = FindObject(material, "pbrMetallicRoughness")) { - ReadMember(*values, "baseColorFactor", this->baseColorFactor); - ReadTextureProperty(r, *values, "baseColorTexture", this->baseColorTexture); - ReadTextureProperty(r, *values, "metallicRoughnessTexture", this->metallicRoughnessTexture); - ReadMember(*values, "metallicFactor", this->metallicFactor); - ReadMember(*values, "roughnessFactor", this->roughnessFactor); + if (Value* pbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) { + ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->baseColorFactor); + ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->baseColorTexture); + ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->metallicRoughnessTexture); + ReadMember(*pbrMetallicRoughness, "metallicFactor", this->metallicFactor); + ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->roughnessFactor); } ReadTextureProperty(r, material, "normalTexture", this->normalTexture); @@ -774,30 +774,17 @@ inline void Material::Read(Value& material, Asset& r) ReadMember(material, "alphaMode", this->alphaMode); ReadMember(material, "alphaCutoff", this->alphaCutoff); - /* if (Value* extensions = FindObject(material, "extensions")) { - if (r.extensionsUsed.KHR_materials_common) { - if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { - if (Value* tnq = FindString(*ext, "technique")) { - const char* t = tnq->GetString(); - if (strcmp(t, "BLINN") == 0) technique = Technique_BLINN; - else if (strcmp(t, "PHONG") == 0) technique = Technique_PHONG; - else if (strcmp(t, "LAMBERT") == 0) technique = Technique_LAMBERT; - else if (strcmp(t, "CONSTANT") == 0) technique = Technique_CONSTANT; - } - - if (Value* values = FindObject(*ext, "values")) { - ReadTextureProperty(r, *values, "ambient", this->ambient); - ReadTextureProperty(r, *values, "diffuse", this->diffuse); - ReadTextureProperty(r, *values, "specular", this->specular); - - ReadMember(*values, "doubleSided", doubleSided); - ReadMember(*values, "transparent", transparent); - ReadMember(*values, "transparency", transparency); - ReadMember(*values, "shininess", shininess); - } + if (Value* extensions = FindObject(material, "extensions")) { + if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { + if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) { + ReadMember(*pbrSpecularGlossiness, "diffuseFactor", this->diffuseFactor); + ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", this->diffuseTexture); + ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", this->specularGlossinessTexture); + ReadMember(*pbrSpecularGlossiness, "specularFactor", this->specularFactor); + ReadMember(*pbrSpecularGlossiness, "glossinessFactor", this->glossinessFactor); } } - } */ + } } namespace { @@ -820,7 +807,10 @@ inline void Material::SetDefaults() alphaCutoff = 0.5; doubleSided = false; - technique = Technique_undefined; + //pbrSpecularGlossiness properties + SetVector(diffuseFactor, 1, 1, 1, 1); + SetVector(specularFactor, 1, 1, 1); + glossinessFactor = 1.0; } namespace { @@ -1083,20 +1073,6 @@ inline void Node::Read(Value& obj, Asset& r) if (this->camera) this->camera->id = this->id; } - - // TODO load "skeletons", "skin", "jointName" - - /*if (Value* extensions = FindObject(obj, "extensions")) { - if (r.extensionsUsed.KHR_materials_common) { - - if (Value* ext = FindObject(*extensions, "KHR_materials_common")) { - if (Value* light = FindUInt(*ext, "light")) { - this->light = r.lights.Retrieve(light->GetUint()); - } - } - - } - }*/ } inline void Scene::Read(Value& obj, Asset& r) @@ -1293,7 +1269,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc) if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; CHECK_EXT(KHR_binary_glTF); - CHECK_EXT(KHR_materials_common); + CHECK_EXT(KHR_materials_pbrSpecularGlossiness); #undef CHECK_EXT } diff --git a/code/glTF2AssetWriter.h b/code/glTF2AssetWriter.h index 976f23f9a..97efbeab5 100644 --- a/code/glTF2AssetWriter.h +++ b/code/glTF2AssetWriter.h @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_binary_glTF: full - * KHR_materials_common: full + * KHR_materials_pbrSpecularGlossiness: full */ #ifndef GLTF2ASSETWRITER_H_INC #define GLTF2ASSETWRITER_H_INC diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index bd16a7023..33625816e 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -327,23 +327,35 @@ namespace glTF2 { obj.AddMember("doubleSided", m.doubleSided, w.mAl); } - /*Value v; - v.SetObject(); + Value pbrSpecularGlossiness; + pbrSpecularGlossiness.SetObject(); { - if (m.transparent && !m.diffuse.texture) { - m.diffuse.color[3] = m.transparency; + //pbrSpecularGlossiness + + vec4 defaultDiffuseFactor = {1, 1, 1, 1}; + WriteVec(pbrSpecularGlossiness, m.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); + + vec3 defaultSpecularFactor = {1, 1, 1}; + WriteVec(pbrSpecularGlossiness, m.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); + + if (m.glossinessFactor != 1) { + WriteFloat(obj, m.glossinessFactor, "glossinessFactor", w.mAl); } - WriteVecOrTex(v, m.ambient, m.ambient.texture ? "ambientTexture" : "ambientFactor", w.mAl); - WriteVecOrTex(v, m.diffuse, m.diffuse.texture ? "diffuseTexture" : "diffuseFactor", w.mAl); - WriteVecOrTex(v, m.specular, m.specular.texture ? "specularTexture" : "specularFactor", w.mAl); - WriteVecOrTex(v, m.emission, m.emission.texture ? "emissionTexture" : "emissionFactor", w.mAl); - v.AddMember("shininessFactor", m.shininess, w.mAl); + + WriteTex(obj, m.diffuseTexture, "diffuseTexture", w.mAl); + WriteTex(obj, m.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); } - v.AddMember("type", "commonPhong", w.mAl); + Value ext; ext.SetObject(); - ext.AddMember("KHR_materials_common", v, w.mAl); - obj.AddMember("extensions", ext, w.mAl);*/ + + if (!pbrSpecularGlossiness.ObjectEmpty()) { + ext.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl); + } + + if (!ext.ObjectEmpty()) { + obj.AddMember("extensions", ext, w.mAl); + } } namespace { @@ -714,11 +726,11 @@ namespace glTF2 { Value exts; exts.SetArray(); { - if (false) - exts.PushBack(StringRef("KHR_binary_glTF"), mAl); + //if (false) + // exts.PushBack(StringRef("KHR_binary_glTF"), mAl); // This is used to export common materials with GLTF 2. - //exts.PushBack(StringRef("KHR_materials_common"), mAl); + //exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); } if (!exts.Empty()) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index b1bbf8349..316970fa5 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -237,6 +237,13 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); aimat->AddProperty(&mat.alphaMode, 1, "$mat.gltf.alphaMode"); aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff"); + + //pbrSpecularGlossiness + SetMaterialColorProperty(r, mat.diffuseFactor, aimat, "$clr.diffuse", 0, 1); + SetMaterialColorProperty(r, mat.specularFactor, aimat, "$clr.specular", 0, 1); + aimat->AddProperty(&mat.glossinessFactor, 1, "$mat.gltf.glossinessFactor"); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.diffuseTexture, aimat, aiTextureType_DIFFUSE, 1); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.specularGlossinessTexture, aimat, aiTextureType_UNKNOWN, 1); } } From 7532d6aac1f18aba3b7e33e7f706c143b6430d4d Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 31 Aug 2017 18:26:50 -0400 Subject: [PATCH 13/56] Remove Light, Technique references --- code/glTF2Asset.h | 23 ------------------- code/glTF2Asset.inl | 46 -------------------------------------- code/glTF2AssetWriter.inl | 10 --------- code/glTF2Importer.cpp | 47 ++------------------------------------- 4 files changed, 2 insertions(+), 124 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index b19de747a..a4b833f58 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -129,7 +129,6 @@ namespace glTF2 struct BufferView; // here due to cross-reference struct Texture; - struct Light; struct Skin; // Vec/matrix types, as raw float arrays @@ -835,7 +834,6 @@ namespace glTF2 Nullable scale; Ref camera; - Ref light; std::vector< Ref > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy. Ref skin; //!< The ID of the skin referenced by this node. @@ -891,27 +889,6 @@ namespace glTF2 void Read(Value& obj, Asset& r); }; - struct Technique : public Object - { - struct Parameters - { - - }; - - struct States - { - - }; - - struct Functions - { - - }; - - Technique() {} - void Read(Value& obj, Asset& r); - }; - //! A texture and its sampler. struct Texture : public Object { diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 3d53bfccf..eab0b8373 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -984,52 +984,6 @@ inline void Camera::Read(Value& obj, Asset& r) } } -inline void Light::Read(Value& obj, Asset& r) -{ - SetDefaults(); - - if (Value* type = FindString(obj, "type")) { - const char* t = type->GetString(); - if (strcmp(t, "ambient") == 0) this->type = Type_ambient; - else if (strcmp(t, "directional") == 0) this->type = Type_directional; - else if (strcmp(t, "point") == 0) this->type = Type_point; - else if (strcmp(t, "spot") == 0) this->type = Type_spot; - - if (this->type != Type_undefined) { - if (Value* vals = FindString(obj, t)) { - ReadMember(*vals, "color", color); - - ReadMember(*vals, "constantAttenuation", constantAttenuation); - ReadMember(*vals, "linearAttenuation", linearAttenuation); - ReadMember(*vals, "quadraticAttenuation", quadraticAttenuation); - ReadMember(*vals, "distance", distance); - - ReadMember(*vals, "falloffAngle", falloffAngle); - ReadMember(*vals, "falloffExponent", falloffExponent); - } - } - } -} - -inline void Light::SetDefaults() -{ - #ifndef M_PI - const float M_PI = 3.14159265358979323846f; - #endif - - type = Type_undefined; - - SetVector(color, 0.f, 0.f, 0.f, 1.f); - - constantAttenuation = 0.f; - linearAttenuation = 1.f; - quadraticAttenuation = 1.f; - distance = 0.f; - - falloffAngle = static_cast(M_PI / 2.f); - falloffExponent = 0.f; -} - inline void Node::Read(Value& obj, Asset& r) { diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 33625816e..a8ee16c82 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -557,11 +557,6 @@ namespace glTF2 { } - inline void Write(Value& obj, Technique& b, AssetWriter& w) - { - - } - inline void Write(Value& obj, Texture& tex, AssetWriter& w) { if (tex.source) { @@ -572,11 +567,6 @@ namespace glTF2 { } } - inline void Write(Value& obj, Light& b, AssetWriter& w) - { - - } - inline AssetWriter::AssetWriter(Asset& a) : mDoc() diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 316970fa5..b4fd96948 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -493,46 +493,6 @@ void glTF2Importer::ImportCameras(glTF2::Asset& r) } } -void glTF2Importer::ImportLights(glTF2::Asset& r) -{ - if (!r.lights.Size()) return; - - mScene->mNumLights = r.lights.Size(); - mScene->mLights = new aiLight*[r.lights.Size()]; - - for (size_t i = 0; i < r.lights.Size(); ++i) { - Light& l = r.lights[i]; - - aiLight* ail = mScene->mLights[i] = new aiLight(); - - switch (l.type) { - case Light::Type_directional: - ail->mType = aiLightSource_DIRECTIONAL; break; - - case Light::Type_spot: - ail->mType = aiLightSource_SPOT; break; - - case Light::Type_ambient: - ail->mType = aiLightSource_AMBIENT; break; - - default: // Light::Type_point - ail->mType = aiLightSource_POINT; break; - } - - CopyValue(l.color, ail->mColorAmbient); - CopyValue(l.color, ail->mColorDiffuse); - CopyValue(l.color, ail->mColorSpecular); - - ail->mAngleOuterCone = l.falloffAngle; - ail->mAngleInnerCone = l.falloffExponent; // TODO fix this, it does not look right at all - - ail->mAttenuationConstant = l.constantAttenuation; - ail->mAttenuationLinear = l.linearAttenuation; - ail->mAttenuationQuadratic = l.quadraticAttenuation; - } -} - - aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& meshOffsets, glTF2::Ref& ptr) { Node& node = *ptr; @@ -602,10 +562,6 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; } - if (node.light) { - pScene->mLights[node.light.GetIndex()]->mName = ainode->mName; - } - return ainode; } @@ -695,13 +651,14 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO // Copy the data out // + + ImportEmbeddedTextures(asset); ImportMaterials(asset); ImportMeshes(asset); ImportCameras(asset); - ImportLights(asset); ImportNodes(asset); From 562920fbb8811bd8b47eb9eb5755ad25c0b98973 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 31 Aug 2017 18:30:43 -0400 Subject: [PATCH 14/56] Changes to GLTF2 materials pbrMetallicRoughness and pbrSpecularGlossiness as structs; persist textureinfo properties from start to finish; persist pbrSpecularGlossiness (via extensionsUsed) usage from start to finish --- code/glTF2Asset.h | 27 +++++++--- code/glTF2Asset.inl | 36 +++++++------ code/glTF2AssetWriter.inl | 64 +++++++++++----------- code/glTF2Exporter.cpp | 109 +++++++++++++++++++++++++++++++++----- code/glTF2Exporter.h | 8 +++ code/glTF2Importer.cpp | 48 +++++++++-------- 6 files changed, 200 insertions(+), 92 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index a4b833f58..3faea0938 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -692,15 +692,30 @@ namespace glTF2 vec4 color; };*/ - //! The material appearance of a primitive. - struct Material : public Object + struct PbrMetallicRoughness { - //PBR metallic roughness properties vec4 baseColorFactor; TextureInfo baseColorTexture; TextureInfo metallicRoughnessTexture; float metallicFactor; float roughnessFactor; + }; + + struct PbrSpecularGlossiness + { + bool on = false; + vec4 diffuseFactor; + vec3 specularFactor; + float glossinessFactor; + TextureInfo diffuseTexture; + TextureInfo specularGlossinessTexture; + }; + + //! The material appearance of a primitive. + struct Material : public Object + { + //PBR metallic roughness properties + PbrMetallicRoughness pbrMetallicRoughness; //other basic material properties NormalTextureInfo normalTexture; @@ -712,11 +727,7 @@ namespace glTF2 bool doubleSided; //extension: KHR_materials_pbrSpecularGlossiness - vec4 diffuseFactor; - vec3 specularFactor; - float glossinessFactor; - TextureInfo diffuseTexture; - TextureInfo specularGlossinessTexture; + PbrSpecularGlossiness pbrSpecularGlossiness; Material() { SetDefaults(); } void Read(Value& obj, Asset& r); diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index eab0b8373..632401576 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -758,11 +758,11 @@ inline void Material::Read(Value& material, Asset& r) SetDefaults(); if (Value* pbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) { - ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->baseColorFactor); - ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->baseColorTexture); - ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->metallicRoughnessTexture); - ReadMember(*pbrMetallicRoughness, "metallicFactor", this->metallicFactor); - ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->roughnessFactor); + ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor); + ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture); + ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture); + ReadMember(*pbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor); + ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor); } ReadTextureProperty(r, material, "normalTexture", this->normalTexture); @@ -777,11 +777,13 @@ inline void Material::Read(Value& material, Asset& r) if (Value* extensions = FindObject(material, "extensions")) { if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) { - ReadMember(*pbrSpecularGlossiness, "diffuseFactor", this->diffuseFactor); - ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", this->diffuseTexture); - ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", this->specularGlossinessTexture); - ReadMember(*pbrSpecularGlossiness, "specularFactor", this->specularFactor); - ReadMember(*pbrSpecularGlossiness, "glossinessFactor", this->glossinessFactor); + this->pbrSpecularGlossiness.on = true; + + ReadMember(*pbrSpecularGlossiness, "diffuseFactor", this->pbrSpecularGlossiness.diffuseFactor); + ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", this->pbrSpecularGlossiness.diffuseTexture); + ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", this->pbrSpecularGlossiness.specularGlossinessTexture); + ReadMember(*pbrSpecularGlossiness, "specularFactor", this->pbrSpecularGlossiness.specularFactor); + ReadMember(*pbrSpecularGlossiness, "glossinessFactor", this->pbrSpecularGlossiness.glossinessFactor); } } } @@ -798,19 +800,19 @@ namespace { inline void Material::SetDefaults() { //pbr materials - SetVector(baseColorFactor, 1, 1, 1, 1); - SetVector(emissiveFactor, 0, 0, 0); - metallicFactor = 1.0; - roughnessFactor = 1.0; + SetVector(pbrMetallicRoughness.baseColorFactor, 1, 1, 1, 1); + pbrMetallicRoughness.metallicFactor = 1.0; + pbrMetallicRoughness.roughnessFactor = 1.0; + SetVector(emissiveFactor, 0, 0, 0); alphaMode = "OPAQUE"; alphaCutoff = 0.5; doubleSided = false; //pbrSpecularGlossiness properties - SetVector(diffuseFactor, 1, 1, 1, 1); - SetVector(specularFactor, 1, 1, 1); - glossinessFactor = 1.0; + SetVector(pbrSpecularGlossiness.diffuseFactor, 1, 1, 1, 1); + SetVector(pbrSpecularGlossiness.specularFactor, 1, 1, 1); + pbrSpecularGlossiness.glossinessFactor = 1.0; } namespace { diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index a8ee16c82..ce2e7c41d 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -287,19 +287,19 @@ namespace glTF2 { Value pbrMetallicRoughness; pbrMetallicRoughness.SetObject(); { - WriteTex(pbrMetallicRoughness, m.baseColorTexture, "baseColorTexture", w.mAl); - WriteTex(pbrMetallicRoughness, m.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl); + WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl); + WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl); //@TODO: define this as a constant? vec4 defaultEmissiveFactor = {1, 1, 1, 1}; - WriteVec(pbrMetallicRoughness, m.baseColorFactor, "baseColorFactor", defaultEmissiveFactor, w.mAl); + WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultEmissiveFactor, w.mAl); - if (m.metallicFactor != 1) { - WriteFloat(pbrMetallicRoughness, m.metallicFactor, "metallicFactor", w.mAl); + if (m.pbrMetallicRoughness.metallicFactor != 1) { + WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl); } - if (m.roughnessFactor != 1) { - WriteFloat(pbrMetallicRoughness, m.roughnessFactor, "roughnessFactor", w.mAl); + if (m.pbrMetallicRoughness.roughnessFactor != 1) { + WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl); } } @@ -327,34 +327,36 @@ namespace glTF2 { obj.AddMember("doubleSided", m.doubleSided, w.mAl); } - Value pbrSpecularGlossiness; - pbrSpecularGlossiness.SetObject(); - { - //pbrSpecularGlossiness + Value exts; + exts.SetObject(); - vec4 defaultDiffuseFactor = {1, 1, 1, 1}; - WriteVec(pbrSpecularGlossiness, m.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); + if (m.pbrSpecularGlossiness.on) { + Value pbrSpecularGlossiness; + pbrSpecularGlossiness.SetObject(); + { + //pbrSpecularGlossiness - vec3 defaultSpecularFactor = {1, 1, 1}; - WriteVec(pbrSpecularGlossiness, m.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); + vec4 defaultDiffuseFactor = {1, 1, 1, 1}; + WriteVec(pbrSpecularGlossiness, m.pbrSpecularGlossiness.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); - if (m.glossinessFactor != 1) { - WriteFloat(obj, m.glossinessFactor, "glossinessFactor", w.mAl); + vec3 defaultSpecularFactor = {1, 1, 1}; + WriteVec(pbrSpecularGlossiness, m.pbrSpecularGlossiness.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); + + if (m.pbrSpecularGlossiness.glossinessFactor != 1) { + WriteFloat(obj, m.pbrSpecularGlossiness.glossinessFactor, "glossinessFactor", w.mAl); + } + + WriteTex(obj, m.pbrSpecularGlossiness.diffuseTexture, "diffuseTexture", w.mAl); + WriteTex(obj, m.pbrSpecularGlossiness.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); } - WriteTex(obj, m.diffuseTexture, "diffuseTexture", w.mAl); - WriteTex(obj, m.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); + if (!pbrSpecularGlossiness.ObjectEmpty()) { + exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl); + } } - Value ext; - ext.SetObject(); - - if (!pbrSpecularGlossiness.ObjectEmpty()) { - ext.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl); - } - - if (!ext.ObjectEmpty()) { - obj.AddMember("extensions", ext, w.mAl); + if (!exts.ObjectEmpty()) { + obj.AddMember("extensions", exts, w.mAl); } } @@ -719,8 +721,10 @@ namespace glTF2 { //if (false) // exts.PushBack(StringRef("KHR_binary_glTF"), mAl); - // This is used to export common materials with GLTF 2. - //exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); + // This is used to export pbrSpecularGlossiness materials with GLTF 2. + if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { + exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); + } } if (!exts.Empty()) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index f59c280f1..9e04da76c 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -112,9 +112,9 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportMetadata(); - //for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {} - - //for (unsigned int i = 0; i < pScene->mNumLights; ++i) {} + if (mScene->mRootNode) { + ExportExtensions(mScene->mRootNode); + } ExportMaterials(); @@ -124,8 +124,6 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportMeshes(); - //for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {} - ExportScene(); //ExportAnimations(); @@ -280,10 +278,26 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture) texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear; } +void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) +{ + const char* key = (std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName).c_str(); + + mat->Get(key, tt, slot, prop); +} + +void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot) +{ + const char* key = (std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName).c_str(); + + mat->Get(key, tt, slot, prop); +} + void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt, unsigned int slot = 0) { - aiString tex; + if (mat->GetTextureCount(tt) > 0) { + aiString tex; + if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { std::string path = tex.C_Str(); @@ -326,6 +340,41 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe } } +void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +{ + Ref& texture = prop.texture; + + GetMatTex(mat, texture, tt, slot); + + if (texture) { + GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + } +} + +void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +{ + Ref& texture = prop.texture; + + GetMatTex(mat, texture, tt, slot); + + if (texture) { + GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + GetMatTexProp(mat, prop.scale, "scale", tt, slot); + } +} + +void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +{ + Ref& texture = prop.texture; + + GetMatTex(mat, texture, tt, slot); + + if (texture) { + GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + GetMatTexProp(mat, prop.strength, "strength", tt, slot); + } +} + void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx) { aiColor4D col; @@ -344,6 +393,8 @@ void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* p void glTF2Exporter::ExportMaterials() { + bool& KHR_materials_pbrSpecularGlossiness = mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness; + aiString aiName; for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; @@ -356,20 +407,36 @@ void glTF2Exporter::ExportMaterials() Ref m = mAsset->materials.Create(name); - GetMatTex(mat, m->baseColorTexture.texture, aiTextureType_DIFFUSE); - GetMatTex(mat, m->metallicRoughnessTexture.texture, aiTextureType_UNKNOWN, 0);//get unknown slot - GetMatTex(mat, m->emissiveTexture.texture, aiTextureType_EMISSIVE); - GetMatTex(mat, m->normalTexture.texture, aiTextureType_NORMALS); - GetMatTex(mat, m->occlusionTexture.texture, aiTextureType_LIGHTMAP); + GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); + GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, aiTextureType_UNKNOWN, 0);//get unknown slot + GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); - GetMatColor(mat, m->baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); + GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS); + GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP); + GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE); GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE); mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff); - mat->Get("$mat.gltf.metallicFactor", 0, 0, m->metallicFactor); - mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->roughnessFactor); + mat->Get("$mat.gltf.metallicFactor", 0, 0, m->pbrMetallicRoughness.metallicFactor); + mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->pbrMetallicRoughness.roughnessFactor); mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode); + + bool hasPbrSpecularGlossiness; + mat->Get("$mat.gltf.pbrSpecularGlossiness.on", 0, 0, hasPbrSpecularGlossiness); + + if (hasPbrSpecularGlossiness) { + + if (!KHR_materials_pbrSpecularGlossiness) { + KHR_materials_pbrSpecularGlossiness = true; + } + + GetMatColor(mat, m->pbrSpecularGlossiness.diffuseFactor, "$clr.diffuse", 0, 1); + GetMatColor(mat, m->pbrSpecularGlossiness.specularFactor, "$clr.specular", 0, 1); + mat->Get("$mat.gltf.glossinessFactor", 0, 0, m->pbrSpecularGlossiness.glossinessFactor); + GetMatTex(mat, m->pbrSpecularGlossiness.diffuseTexture, aiTextureType_DIFFUSE, 1); + GetMatTex(mat, m->pbrSpecularGlossiness.specularGlossinessTexture, aiTextureType_UNKNOWN, 1); + } } } @@ -862,6 +929,20 @@ void glTF2Exporter::ExportMetadata() asset.generator = buffer; } +void glTF2Exporter::ExportExtensions(const aiNode* n) +{ + aiMetadata* mMetaData = n->mMetaData; + + if (mMetaData != nullptr) { + bool pbrSpecularGlossiness; + + if (mMetaData->Get("extensionsUsed.pbrSpecularGlossiness", pbrSpecularGlossiness)) { + mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = pbrSpecularGlossiness; + } + } + +} + inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref& animRef, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond) { // Loop over the data and check to see if it exactly matches an existing buffer. diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 2ba0143bf..827189f29 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -67,6 +67,8 @@ namespace glTF2 class Asset; struct TexProperty; struct TextureInfo; + struct NormalTextureInfo; + struct OcclusionTextureInfo; struct Node; struct Texture; @@ -107,10 +109,16 @@ namespace Assimp void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture); + 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); void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx); void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx); void ExportMetadata(); + void ExportExtensions(const aiNode* n); void ExportMaterials(); void ExportMeshes(); unsigned int ExportNodeHierarchy(const aiNode* n); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index b4fd96948..97901fc01 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -183,7 +183,7 @@ inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, cons return SetMaterialColorProperty(r, prop4, mat, pKey, type, idx); } -inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, int texSlot) +inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0) { if (prop.texture && prop.texture->source) { aiString uri(prop.texture->source->uri); @@ -195,19 +195,11 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); } - if (texSlot < 0) { - mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0); - } - else { - mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, - texSlot)); - } - } -} + mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); -inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType) -{ - return SetMaterialTextureProperty(embeddedTexIdxs, r, prop, mat, texType, -1); + const char *texCoordName = (std::string(_AI_MATKEY_TEXTURE_BASE) + ".texCoord").c_str(); + mat->AddProperty(&prop.texCoord, 1, texCoordName, texType, texSlot); + } } void glTF2Importer::ImportMaterials(glTF2::Asset& r) @@ -223,11 +215,11 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) aiString str(mat.id); aimat->AddProperty(&str, AI_MATKEY_NAME); - SetMaterialColorProperty(r, mat.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.baseColorTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.metallicRoughnessTexture, aimat, aiTextureType_UNKNOWN, 0); - aimat->AddProperty(&mat.metallicFactor, 1, "$mat.gltf.metallicFactor"); - aimat->AddProperty(&mat.roughnessFactor, 1, "$mat.gltf.roughnessFactor"); + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_UNKNOWN); + aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, "$mat.gltf.pbrMetallicRoughness.metallicFactor"); + aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, "$mat.gltf.pbrMetallicRoughness.roughnessFactor"); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP); @@ -239,11 +231,14 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff"); //pbrSpecularGlossiness - SetMaterialColorProperty(r, mat.diffuseFactor, aimat, "$clr.diffuse", 0, 1); - SetMaterialColorProperty(r, mat.specularFactor, aimat, "$clr.specular", 0, 1); - aimat->AddProperty(&mat.glossinessFactor, 1, "$mat.gltf.glossinessFactor"); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.diffuseTexture, aimat, aiTextureType_DIFFUSE, 1); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.specularGlossinessTexture, aimat, aiTextureType_UNKNOWN, 1); + if (mat.pbrSpecularGlossiness.on) { + aimat->AddProperty(&mat.pbrSpecularGlossiness.on, 1, "$mat.gltf.pbrSpecularGlossiness.on"); + SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.diffuseFactor, aimat, "$clr.diffuse", 0, 1); + SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.specularFactor, aimat, "$clr.specular", 0, 1); + aimat->AddProperty(&mat.pbrSpecularGlossiness.glossinessFactor, 1, "$mat.gltf.pbrSpecularGlossiness.glossinessFactor"); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.diffuseTexture, aimat, aiTextureType_DIFFUSE, 1); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.specularGlossinessTexture, aimat, aiTextureType_UNKNOWN, 1); + } } } @@ -590,6 +585,13 @@ void glTF2Importer::ImportNodes(glTF2::Asset& r) //if (!mScene->mRootNode) { // mScene->mRootNode = new aiNode("EMPTY"); //} + + //initialize mMetaData; + aiMetadata* mMetaData = new aiMetadata(); + + //store used glTF extensions on the root node, for a lack of a better place. + mMetaData->Add("extensionsUsed.pbrSpecularGlossiness", r.extensionsUsed.KHR_materials_pbrSpecularGlossiness); + mScene->mRootNode->mMetaData = mMetaData; } void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r) From 2d54019b8fb10e46f2b1d4e98e3f1a904de15309 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 31 Aug 2017 23:38:10 -0400 Subject: [PATCH 15/56] Remove OPEN3DGC and compression references --- code/glTF2Asset.h | 71 ------------------- code/glTF2Asset.inl | 74 -------------------- code/glTF2AssetWriter.inl | 51 -------------- code/glTF2Exporter.cpp | 142 +------------------------------------- code/glTF2Importer.cpp | 32 --------- 5 files changed, 1 insertion(+), 369 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 3faea0938..dd348de1a 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -752,86 +752,15 @@ namespace glTF2 Ref material; }; - /// \struct SExtension - /// Extension used for mesh. - struct SExtension - { - /// \enum EType - /// Type of extension. - enum EType - { - #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - Compression_Open3DGC,///< Compression of mesh data using Open3DGC algorithm. - #endif - - Unknown - }; - - EType Type;///< Type of extension. - - /// \fn SExtension - /// Constructor. - /// \param [in] pType - type of extension. - SExtension(const EType pType) - : Type(pType) - {} - - virtual ~SExtension() { - // empty - } - }; - - #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - /// \struct SCompression_Open3DGC - /// Compression of mesh data using Open3DGC algorithm. - struct SCompression_Open3DGC : public SExtension - { - using SExtension::Type; - - std::string Buffer;///< ID of "buffer" used for storing compressed data. - size_t Offset;///< Offset in "bufferView" where compressed data are stored. - size_t Count;///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type". - bool Binary;///< If true then "binary" mode is used for coding, if false - "ascii" mode. - size_t IndicesCount;///< Count of indices in mesh. - size_t VerticesCount;///< Count of vertices in mesh. - // AttribType::Value Type;///< Is always "SCALAR". - // ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121). - - /// \fn SCompression_Open3DGC - /// Constructor. - SCompression_Open3DGC() - : SExtension(Compression_Open3DGC) { - // empty - } - - virtual ~SCompression_Open3DGC() { - // empty - } - }; - #endif - std::vector primitives; - std::list Extension;///< List of extensions used in mesh. Mesh() {} - /// \fn ~Mesh() - /// Destructor. - ~Mesh() { for(std::list::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { delete *it; }; } - /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root) /// Get mesh data from JSON-object and place them to root asset. /// \param [in] pJSON_Object - reference to pJSON-object from which data are read. /// \param [out] pAsset_Root - reference to root assed where data will be stored. void Read(Value& pJSON_Object, Asset& pAsset_Root); - - #ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - /// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root) - /// Decode part of "buffer" which encoded with Open3DGC algorithm. - /// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region. - /// \param [out] pAsset_Root - reference to root assed where data will be stored. - void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root); - #endif }; struct Node : public Object diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 632401576..dd110ebb7 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -44,11 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Header files, Assimp #include -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - // Header files, Open3DGC. -# include -#endif - using namespace Assimp; namespace glTF2 { @@ -892,75 +887,6 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) } } } - - /****************** Mesh extensions ******************/ - Value* json_extensions = FindObject(pJSON_Object, "extensions"); - - if(json_extensions == nullptr) goto mr_skip_extensions; - - for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); it_memb++) - { -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - if(it_memb->name.GetString() == std::string("Open3DGC-compression")) - { - // Search for compressed data. - // Compressed data contain description of part of "buffer" which is encoded. This part must be decoded and - // new data will replace old encoded part by request. In fact \"compressedData\" is kind of "accessor" structure. - Value* comp_data = FindObject(it_memb->value, "compressedData"); - - if(comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\"."); - - DefaultLogger::get()->info("GLTF: Decompressing Open3DGC data."); - - /************** Read data from JSON-document **************/ - #define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \ - if(!ReadMember(*comp_data, pFieldName, pOut)) \ - { \ - throw DeadlyImportError(std::string("GLTF: \"compressedData\" must has \"") + pFieldName + "\"."); \ - } - - const char* mode_str; - const char* type_str; - ComponentType component_type; - SCompression_Open3DGC* ext_o3dgc = new SCompression_Open3DGC; - - MESH_READ_COMPRESSEDDATA_MEMBER("buffer", ext_o3dgc->Buffer); - MESH_READ_COMPRESSEDDATA_MEMBER("byteOffset", ext_o3dgc->Offset); - MESH_READ_COMPRESSEDDATA_MEMBER("componentType", component_type); - MESH_READ_COMPRESSEDDATA_MEMBER("type", type_str); - MESH_READ_COMPRESSEDDATA_MEMBER("count", ext_o3dgc->Count); - MESH_READ_COMPRESSEDDATA_MEMBER("mode", mode_str); - MESH_READ_COMPRESSEDDATA_MEMBER("indicesCount", ext_o3dgc->IndicesCount); - MESH_READ_COMPRESSEDDATA_MEMBER("verticesCount", ext_o3dgc->VerticesCount); - - #undef MESH_READ_COMPRESSEDDATA_MEMBER - - // Check some values - if(strcmp(type_str, "SCALAR")) throw DeadlyImportError("GLTF: only \"SCALAR\" type is supported for compressed data."); - if(component_type != ComponentType_UNSIGNED_BYTE) throw DeadlyImportError("GLTF: only \"UNSIGNED_BYTE\" component type is supported for compressed data."); - - // Set read/write data mode. - if(strcmp(mode_str, "binary") == 0) - ext_o3dgc->Binary = true; - else if(strcmp(mode_str, "ascii") == 0) - ext_o3dgc->Binary = false; - else - throw DeadlyImportError(std::string("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"") + mode_str + "\"."); - - /************************ Decoding ************************/ - Decode_O3DGC(*ext_o3dgc, pAsset_Root); - Extension.push_back(ext_o3dgc);// store info in mesh extensions list. - }// if(it_memb->name.GetString() == "Open3DGC-compression") - else -#endif - { - throw DeadlyImportError(std::string("GLTF: Unknown mesh extension: \"") + it_memb->name.GetString() + "\"."); - } - }// for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++) - -mr_skip_extensions: - - return;// After label some operators must be present. } inline void Camera::Read(Value& obj, Asset& r) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index ce2e7c41d..c74ea4031 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -380,57 +380,6 @@ namespace glTF2 { inline void Write(Value& obj, Mesh& m, AssetWriter& w) { - - /**************** Mesh extensions ****************/ - if(m.Extension.size() > 0) - { - Value json_extensions; - - json_extensions.SetObject(); - for(Mesh::SExtension* ptr_ext : m.Extension) - { - switch(ptr_ext->Type) - { -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - case Mesh::SExtension::EType::Compression_Open3DGC: - { - Value json_comp_data; - Mesh::SCompression_Open3DGC* ptr_ext_comp = (Mesh::SCompression_Open3DGC*)ptr_ext; - - // filling object "compressedData" - json_comp_data.SetObject(); - json_comp_data.AddMember("buffer", ptr_ext_comp->Buffer, w.mAl); - json_comp_data.AddMember("byteOffset", ptr_ext_comp->Offset, w.mAl); - json_comp_data.AddMember("componentType", 5121, w.mAl); - json_comp_data.AddMember("type", "SCALAR", w.mAl); - json_comp_data.AddMember("count", ptr_ext_comp->Count, w.mAl); - if(ptr_ext_comp->Binary) - json_comp_data.AddMember("mode", "binary", w.mAl); - else - json_comp_data.AddMember("mode", "ascii", w.mAl); - - json_comp_data.AddMember("indicesCount", ptr_ext_comp->IndicesCount, w.mAl); - json_comp_data.AddMember("verticesCount", ptr_ext_comp->VerticesCount, w.mAl); - // filling object "Open3DGC-compression" - Value json_o3dgc; - - json_o3dgc.SetObject(); - json_o3dgc.AddMember("compressedData", json_comp_data, w.mAl); - // add member to object "extensions" - json_extensions.AddMember("Open3DGC-compression", json_o3dgc, w.mAl); - } - - break; -#endif - default: - throw DeadlyImportError("GLTF: Can not write mesh: unknown mesh extension, only Open3DGC is supported."); - }// switch(ptr_ext->Type) - }// for(Mesh::SExtension* ptr_ext : m.Extension) - - // Add extensions to mesh - obj.AddMember("extensions", json_extensions, w.mAl); - }// if(m.Extension.size() > 0) - /****************** Primitives *******************/ Value primitives; primitives.SetArray(); diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9e04da76c..2b7e4c33d 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -62,11 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "glTF2AssetWriter.h" -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - // Header files, Open3DGC. -# include -#endif - using namespace rapidjson; using namespace Assimp; @@ -573,15 +568,6 @@ void glTF2Exporter::ExportMeshes() // because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification. typedef unsigned short IndicesType; - // Variables needed for compression. BEGIN. - // Indices, not pointers - because pointer to buffer is changing while writing to it. - size_t idx_srcdata_begin;// Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer. - size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals. - std::vector idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer. - size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer. - bool comp_allow;// Point that data of current mesh can be compressed. - // Variables needed for compression. END. - std::string fname = std::string(mFilename); std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf")); std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str()); @@ -614,31 +600,6 @@ void glTF2Exporter::ExportMeshes() for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) { const aiMesh* aim = mScene->mMeshes[idx_mesh]; - // Check if compressing requested and mesh can be encoded. -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - comp_allow = mProperties->GetPropertyBool("extensions.Open3DGC.use", false); -#else - comp_allow = false; -#endif - - if(comp_allow && (aim->mPrimitiveTypes == aiPrimitiveType_TRIANGLE) && (aim->mNumVertices > 0) && (aim->mNumFaces > 0)) - { - idx_srcdata_tc.clear(); - idx_srcdata_tc.reserve(AI_MAX_NUMBER_OF_TEXTURECOORDS); - } - else - { - std::string msg; - - if(aim->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) - msg = "all primitives of the mesh must be a triangles."; - else - msg = "mesh must has vertices and faces."; - - DefaultLogger::get()->warn("GLTF: can not use Open3DGC-compression: " + msg); - comp_allow = false; - } - std::string name = aim->mName.C_Str(); std::string meshId = mAsset->FindUniqueID(name, "mesh"); @@ -651,15 +612,10 @@ void glTF2Exporter::ExportMeshes() p.material = mAsset->materials.Get(aim->mMaterialIndex); /******************* Vertices ********************/ - // If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored. - if(comp_allow) idx_srcdata_begin = b->byteLength; - Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if (v) p.attributes.position.push_back(v); /******************** Normals ********************/ - if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array. - Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if (n) p.attributes.normal.push_back(n); @@ -675,16 +631,12 @@ void glTF2Exporter::ExportMeshes() if (aim->mNumUVComponents[i] > 0) { AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; - if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array. - Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); if (tc) p.attributes.texcoord.push_back(tc); } } /*************** Vertices indices ****************/ - idx_srcdata_ind = b->byteLength;// Store index of indices array. - if (aim->mNumFaces > 0) { std::vector indices; unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices; @@ -713,99 +665,7 @@ void glTF2Exporter::ExportMeshes() /*if(aim->HasBones()) { ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); }*/ - - /****************** Compression ******************/ - ///TODO: animation: weights, joints. - if(comp_allow) - { -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - // Only one type of compression supported at now - Open3DGC. - // - o3dgc::BinaryStream bs; - o3dgc::SC3DMCEncoder encoder; - o3dgc::IndexedFaceSet comp_o3dgc_ifs; - o3dgc::SC3DMCEncodeParams comp_o3dgc_params; - - // - // Fill data for encoder. - // - // Quantization - unsigned quant_coord = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.POSITION", 12); - unsigned quant_normal = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.NORMAL", 10); - unsigned quant_texcoord = mProperties->GetPropertyInteger("extensions.Open3DGC.quantization.TEXCOORD", 10); - - // Prediction - o3dgc::O3DGCSC3DMCPredictionMode prediction_position = o3dgc::O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION; - o3dgc::O3DGCSC3DMCPredictionMode prediction_normal = o3dgc::O3DGC_SC3DMC_SURF_NORMALS_PREDICTION; - o3dgc::O3DGCSC3DMCPredictionMode prediction_texcoord = o3dgc::O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION; - - // IndexedFacesSet: "Crease angle", "solid", "convex" are set to default. - comp_o3dgc_ifs.SetCCW(true); - comp_o3dgc_ifs.SetIsTriangularMesh(true); - comp_o3dgc_ifs.SetNumFloatAttributes(0); - // Coordinates - comp_o3dgc_params.SetCoordQuantBits(quant_coord); - comp_o3dgc_params.SetCoordPredMode(prediction_position); - comp_o3dgc_ifs.SetNCoord(aim->mNumVertices); - comp_o3dgc_ifs.SetCoord((o3dgc::Real* const)&b->GetPointer()[idx_srcdata_begin]); - // Normals - if(idx_srcdata_normal != SIZE_MAX) - { - comp_o3dgc_params.SetNormalQuantBits(quant_normal); - comp_o3dgc_params.SetNormalPredMode(prediction_normal); - comp_o3dgc_ifs.SetNNormal(aim->mNumVertices); - comp_o3dgc_ifs.SetNormal((o3dgc::Real* const)&b->GetPointer()[idx_srcdata_normal]); - } - - // Texture coordinates - for(size_t num_tc = 0; num_tc < idx_srcdata_tc.size(); num_tc++) - { - size_t num = comp_o3dgc_ifs.GetNumFloatAttributes(); - - comp_o3dgc_params.SetFloatAttributeQuantBits(static_cast(num), quant_texcoord); - comp_o3dgc_params.SetFloatAttributePredMode(static_cast(num), prediction_texcoord); - comp_o3dgc_ifs.SetNFloatAttribute(static_cast(num), aim->mNumVertices);// number of elements. - comp_o3dgc_ifs.SetFloatAttributeDim(static_cast(num), aim->mNumUVComponents[num_tc]);// components per element: aiVector3D => x * float - comp_o3dgc_ifs.SetFloatAttributeType(static_cast(num), o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD); - comp_o3dgc_ifs.SetFloatAttribute(static_cast(num), (o3dgc::Real* const)&b->GetPointer()[idx_srcdata_tc[num_tc]]); - comp_o3dgc_ifs.SetNumFloatAttributes(static_cast(num + 1)); - } - - // Coordinates indices - comp_o3dgc_ifs.SetNCoordIndex(aim->mNumFaces); - comp_o3dgc_ifs.SetCoordIndex((IndicesType* const)&b->GetPointer()[idx_srcdata_ind]); - // Prepare to enconding - comp_o3dgc_params.SetNumFloatAttributes(comp_o3dgc_ifs.GetNumFloatAttributes()); - if(mProperties->GetPropertyBool("extensions.Open3DGC.binary", true)) - comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_BINARY); - else - comp_o3dgc_params.SetStreamType(o3dgc::O3DGC_STREAM_TYPE_ASCII); - - comp_o3dgc_ifs.ComputeMinMax(o3dgc::O3DGC_SC3DMC_MAX_ALL_DIMS); - // - // Encoding - // - encoder.Encode(comp_o3dgc_params, comp_o3dgc_ifs, bs); - // Replace data in buffer. - b->ReplaceData(idx_srcdata_begin, b->byteLength - idx_srcdata_begin, bs.GetBuffer(), bs.GetSize()); - // - // Add information about extension to mesh. - // - // Create extension structure. - Mesh::SCompression_Open3DGC* ext = new Mesh::SCompression_Open3DGC; - - // Fill it. - ext->Buffer = b->id; - ext->Offset = idx_srcdata_begin; - ext->Count = b->byteLength - idx_srcdata_begin; - ext->Binary = mProperties->GetPropertyBool("extensions.Open3DGC.binary"); - ext->IndicesCount = comp_o3dgc_ifs.GetNCoordIndex() * 3; - ext->VerticesCount = comp_o3dgc_ifs.GetNCoord(); - // And assign to mesh. - m->Extension.push_back(ext); -#endif - }// if(comp_allow) - }// for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) + } //---------------------------------------- // Finish the skin diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 97901fc01..a2c0911bd 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -288,38 +288,6 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh& mesh = r.meshes[m]; - // Check if mesh extensions is used - if(mesh.Extension.size() > 0) - { - for(Mesh::SExtension* cur_ext : mesh.Extension) - { -#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC - if(cur_ext->Type == Mesh::SExtension::EType::Compression_Open3DGC) - { - // Limitations for meshes when using Open3DGC-compression. - // It's a current limitation of sp... Specification have not this part still - about mesh compression. Why only one primitive? - // Because glTF is very flexibly. But in fact it ugly flexible. Every primitive can has own set of accessors and accessors can - // point to a-a-a-a-any part of buffer (through bufferview of course) and even to another buffer. We know that "Open3DGC-compression" - // is applicable only to part of buffer. As we can't guaranty continuity of the data for decoder, we will limit quantity of primitives. - // Yes indices, coordinates etc. still can br stored in different buffers, but with current specification it's a exporter problem. - // Also primitive can has only one of "POSITION", "NORMAL" and less then "AI_MAX_NUMBER_OF_TEXTURECOORDS" of "TEXCOORD". All accessor - // of primitive must point to one continuous region of the buffer. - if(mesh.primitives.size() > 2) throw DeadlyImportError("GLTF: When using Open3DGC compression then only one primitive per mesh are allowed."); - - Mesh::SCompression_Open3DGC* o3dgc_ext = (Mesh::SCompression_Open3DGC*)cur_ext; - Ref buf = r.buffers.Get(o3dgc_ext->Buffer); - - buf->EncodedRegion_SetCurrent(mesh.id); - } - else -#endif - { - throw DeadlyImportError("GLTF: Can not import mesh: unknown mesh extension (code: \"" + to_string(cur_ext->Type) + - "\"), only Open3DGC is supported."); - } - } - }// if(mesh.Extension.size() > 0) - meshOffsets.push_back(k); k += unsigned(mesh.primitives.size()); From 8bef546b41b1069effb64fd53682172fb7187607 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 31 Aug 2017 23:40:44 -0400 Subject: [PATCH 16/56] mention pbrSpecularGlossiness support --- code/glTF2Asset.h | 1 + 1 file changed, 1 insertion(+) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index dd348de1a..1f9f48e18 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_binary_glTF: full + * KHR_materials_pbrSpecularGlossiness full */ #ifndef GLTF2ASSET_H_INC #define GLTF2ASSET_H_INC From feee7528d6c8323e0cdb7aeb4c38bb62909d6a51 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 02:42:09 -0400 Subject: [PATCH 17/56] Make sure `on` flag for specularGlossiness is being persisted --- code/glTF2Exporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 2b7e4c33d..ae610d16d 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -426,6 +426,7 @@ void glTF2Exporter::ExportMaterials() KHR_materials_pbrSpecularGlossiness = true; } + m->pbrSpecularGlossiness.on = true; GetMatColor(mat, m->pbrSpecularGlossiness.diffuseFactor, "$clr.diffuse", 0, 1); GetMatColor(mat, m->pbrSpecularGlossiness.specularFactor, "$clr.specular", 0, 1); mat->Get("$mat.gltf.glossinessFactor", 0, 0, m->pbrSpecularGlossiness.glossinessFactor); From f09892ab63fcd919f1489bd8853963c020b3ca80 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 02:42:26 -0400 Subject: [PATCH 18/56] Write specularGlossiness textures on the specularGlossiness object --- code/glTF2AssetWriter.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index c74ea4031..9aa00729c 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -346,8 +346,8 @@ namespace glTF2 { WriteFloat(obj, m.pbrSpecularGlossiness.glossinessFactor, "glossinessFactor", w.mAl); } - WriteTex(obj, m.pbrSpecularGlossiness.diffuseTexture, "diffuseTexture", w.mAl); - WriteTex(obj, m.pbrSpecularGlossiness.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); + WriteTex(pbrSpecularGlossiness, m.pbrSpecularGlossiness.diffuseTexture, "diffuseTexture", w.mAl); + WriteTex(pbrSpecularGlossiness, m.pbrSpecularGlossiness.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); } if (!pbrSpecularGlossiness.ObjectEmpty()) { From ab08a7c3cbc27add5c10ea44786018c9b5c8ff47 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 17:49:04 -0400 Subject: [PATCH 19/56] reenable animation and skins exports Currently incorrect, however. May need to be removed --- code/glTF2Asset.h | 3 +++ code/glTF2Asset.inl | 36 ++++++++++++++++++++++++++---------- code/glTF2Exporter.cpp | 14 +++++++------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 1f9f48e18..8e3a6dd7a 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -928,9 +928,11 @@ namespace glTF2 friend class AssetWriter; typedef typename std::gltf_unordered_map< unsigned int, unsigned int > Dict; + typedef typename std::gltf_unordered_map< std::string, unsigned int > IdDict; std::vector mObjs; //! The read objects Dict mObjsByOIndex; //! The read objects accessible by original index + IdDict mObjsById; //! The read objects accessible by id const char* mDictId; //! ID of the dictionary object const char* mExtId; //! ID of the extension defining the dictionary Value* mDict; //! JSON dictionary object @@ -951,6 +953,7 @@ namespace glTF2 Ref Retrieve(unsigned int i); Ref Get(unsigned int i); + Ref Get(const char* id); Ref Create(const char* id); Ref Create(const std::string& id) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index dd110ebb7..5316b5e26 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -1,4 +1,4 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- @@ -193,14 +193,6 @@ inline void LazyDict::DetachFromDocument() mDict = 0; } -template -Ref LazyDict::Get(unsigned int i) -{ - - return Ref(mObjs, i); - -} - template Ref LazyDict::Retrieve(unsigned int i) { @@ -234,12 +226,34 @@ Ref LazyDict::Retrieve(unsigned int i) return Add(inst); } +template +Ref LazyDict::Get(unsigned int i) +{ + + return Ref(mObjs, i); + +} + +template +Ref LazyDict::Get(const char* id) +{ + id = T::TranslateId(mAsset, id); + + typename IdDict::iterator it = mObjsById.find(id); + if (it != mObjsById.end()) { // already created? + return Ref(mObjs, it->second); + } + + throw std::out_of_range("id \"" + std::string(id) + "\" Doesn't exist"); +} + template Ref LazyDict::Add(T* obj) { unsigned int idx = unsigned(mObjs.size()); mObjs.push_back(obj); mObjsByOIndex[obj->oIndex] = idx; + mObjsById[obj->id] = idx; mAsset.mUsedIds[obj->id] = true; return Ref(mObjs, idx); } @@ -252,8 +266,10 @@ Ref LazyDict::Create(const char* id) throw DeadlyImportError("GLTF: two objects with the same ID exist"); } T* inst = new T(); + unsigned int idx = unsigned(mObjs.size()); inst->id = id; - inst->index = static_cast(mObjs.size()); + inst->index = idx; + inst->oIndex = idx; return Add(inst); } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index ae610d16d..164b559fd 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -121,7 +121,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportScene(); - //ExportAnimations(); + ExportAnimations(); AssetWriter writer(*mAsset); @@ -481,7 +481,7 @@ Ref FindSkeletonRootJoint(Ref& skinRef) return parentNodeRef; } -/*void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref& bufferRef, Ref& skinRef, std::vector& inverseBindMatricesData) +void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref& bufferRef, Ref& skinRef, std::vector& inverseBindMatricesData) { if (aimesh->mNumBones < 1) { return; @@ -558,7 +558,7 @@ Ref FindSkeletonRootJoint(Ref& skinRef) delete[] jointsPerVertex; delete[] vertexWeightData; delete[] vertexJointData; -}*/ +} void glTF2Exporter::ExportMeshes() { @@ -663,9 +663,9 @@ void glTF2Exporter::ExportMeshes() } /*************** Skins ****************/ - /*if(aim->HasBones()) { + if(aim->HasBones()) { ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); - }*/ + } } //---------------------------------------- @@ -892,7 +892,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref bufferRef = mAsset->buffers.Get(unsigned (0)); @@ -961,7 +961,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref Date: Fri, 1 Sep 2017 17:56:13 -0400 Subject: [PATCH 20/56] store node mesh vs. meshes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glTF nodes can only hold one mesh. this simply assigns to and check’s a Node’s Mesh --- code/glTF2Asset.h | 2 +- code/glTF2Asset.inl | 9 +-------- code/glTF2AssetWriter.inl | 4 +++- code/glTF2Exporter.cpp | 19 +++++++++---------- code/glTF2Importer.cpp | 21 +++++++-------------- 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 8e3a6dd7a..9facef6a7 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -767,7 +767,7 @@ namespace glTF2 struct Node : public Object { std::vector< Ref > children; - std::vector< Ref > meshes; + Ref mesh; Nullable matrix; Nullable translation; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 5316b5e26..bebaeba53 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -954,16 +954,9 @@ inline void Node::Read(Value& obj, Asset& r) } if (Value* mesh = FindUInt(obj, "mesh")) { - //unsigned numMeshes = (unsigned)meshes->Size(); - unsigned numMeshes = 1; - - //std::vector meshList; - - this->meshes.reserve(numMeshes); - Ref meshRef = r.meshes.Retrieve((*mesh).GetUint()); - if (meshRef) this->meshes.push_back(meshRef); + if (meshRef) this->mesh = meshRef; } if (Value* camera = FindUInt(obj, "camera")) { diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 9aa00729c..4a2aa9f39 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -441,7 +441,9 @@ namespace glTF2 { AddRefsVector(obj, "children", n.children, w.mAl); - AddRefsVector(obj, "meshes", n.meshes, w.mAl); + if (n.mesh) { + obj.AddMember("mesh", n.mesh->index, w.mAl); + } AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 164b559fd..7daedd4a3 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -442,16 +442,15 @@ void glTF2Exporter::ExportMaterials() */ bool FindMeshNode(Ref& nodeIn, Ref& meshNode, std::string meshID) { - for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) { - if (meshID.compare(nodeIn->meshes[i]->id) == 0) { - meshNode = nodeIn; - return true; - } + + if (nodeIn->mesh && meshID.compare(nodeIn->mesh->id) == 0) { + meshNode = nodeIn; + return true; } for (unsigned int i = 0; i < nodeIn->children.size(); ++i) { if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) { - return true; + return true; } } @@ -722,8 +721,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n) CopyValue(n->mTransformation, node->matrix.value); } - for (unsigned int i = 0; i < n->mNumMeshes; ++i) { - node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); + if (n->mNumMeshes > 0) { + node->mesh = mAsset->meshes.Get(n->mMeshes[0]); } for (unsigned int i = 0; i < n->mNumChildren; ++i) { @@ -751,8 +750,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref& parent) CopyValue(n->mTransformation, node->matrix.value); } - for (unsigned int i = 0; i < n->mNumMeshes; ++i) { - node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); + if (n->mNumMeshes > 0) { + node->mesh = mAsset->meshes.Get(n->mMeshes[0]); } for (unsigned int i = 0; i < n->mNumChildren; ++i) { diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index a2c0911bd..90ae849bd 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -502,22 +502,15 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& } } - if (!node.meshes.empty()) { - int count = 0; - for (size_t i = 0; i < node.meshes.size(); ++i) { - int idx = node.meshes[i].GetIndex(); - count += meshOffsets[idx + 1] - meshOffsets[idx]; - } - - ainode->mNumMeshes = count; - ainode->mMeshes = new unsigned int[count]; + if (node.mesh) { + ainode->mNumMeshes = 1; + ainode->mMeshes = new unsigned int[1]; int k = 0; - for (size_t i = 0; i < node.meshes.size(); ++i) { - int idx = node.meshes[i].GetIndex(); - for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) { - ainode->mMeshes[k] = j; - } + int idx = node.mesh.GetIndex(); + + for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) { + ainode->mMeshes[k] = j; } } From 7f01e3f48f0008a43a64d90c94d6c8288de83498 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 17:56:42 -0400 Subject: [PATCH 21/56] Only export byteStride if not 0 --- code/glTF2AssetWriter.inl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 4a2aa9f39..69d54d97b 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -97,7 +97,11 @@ namespace glTF2 { { obj.AddMember("bufferView", a.bufferView->index, w.mAl); obj.AddMember("byteOffset", a.byteOffset, w.mAl); - obj.AddMember("byteStride", a.byteStride, w.mAl); + + if (a.byteStride != 0) { + obj.AddMember("byteStride", a.byteStride, w.mAl); + } + obj.AddMember("componentType", int(a.componentType), w.mAl); obj.AddMember("count", a.count, w.mAl); obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); From d277995a972dedcccc5258105b543b5b65fa89c9 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 17:56:48 -0400 Subject: [PATCH 22/56] Formatting --- code/glTF2Asset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 9facef6a7..875594254 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -777,7 +777,7 @@ namespace glTF2 Ref camera; std::vector< Ref > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy. - Ref skin; //!< The ID of the skin referenced by this node. + Ref skin; //!< The ID of the skin referenced by this node. std::string jointName; //!< Name used when this node is a joint in a skin. Ref parent; //!< This is not part of the glTF specification. Used as a helper. From 63ef19d9ad1b5a6404fb2520209bb7c0f1e05005 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 17:56:30 -0400 Subject: [PATCH 23/56] Export extensions --- code/glTF2Exporter.cpp | 18 ------------------ code/glTF2Exporter.h | 1 - code/glTF2Importer.cpp | 7 ------- 3 files changed, 26 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 7daedd4a3..9a2c1cd75 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -107,10 +107,6 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai ExportMetadata(); - if (mScene->mRootNode) { - ExportExtensions(mScene->mRootNode); - } - ExportMaterials(); if (mScene->mRootNode) { @@ -789,20 +785,6 @@ void glTF2Exporter::ExportMetadata() asset.generator = buffer; } -void glTF2Exporter::ExportExtensions(const aiNode* n) -{ - aiMetadata* mMetaData = n->mMetaData; - - if (mMetaData != nullptr) { - bool pbrSpecularGlossiness; - - if (mMetaData->Get("extensionsUsed.pbrSpecularGlossiness", pbrSpecularGlossiness)) { - mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = pbrSpecularGlossiness; - } - } - -} - inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref& animRef, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond) { // Loop over the data and check to see if it exactly matches an existing buffer. diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 827189f29..4b9fe0ce0 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -118,7 +118,6 @@ namespace Assimp void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx); void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx); void ExportMetadata(); - void ExportExtensions(const aiNode* n); void ExportMaterials(); void ExportMeshes(); unsigned int ExportNodeHierarchy(const aiNode* n); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 90ae849bd..36fe8b70e 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -546,13 +546,6 @@ void glTF2Importer::ImportNodes(glTF2::Asset& r) //if (!mScene->mRootNode) { // mScene->mRootNode = new aiNode("EMPTY"); //} - - //initialize mMetaData; - aiMetadata* mMetaData = new aiMetadata(); - - //store used glTF extensions on the root node, for a lack of a better place. - mMetaData->Add("extensionsUsed.pbrSpecularGlossiness", r.extensionsUsed.KHR_materials_pbrSpecularGlossiness); - mScene->mRootNode->mMetaData = mMetaData; } void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r) From 2abdbdb55e2801f284d1a8fc2a090e9da28a4557 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 1 Sep 2017 18:29:30 -0400 Subject: [PATCH 24/56] Fix unused CopyValue --- code/glTF2Importer.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 36fe8b70e..08145f5fe 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -136,10 +136,10 @@ static void CopyValue(const glTF2::vec4& v, aiColor4D& out) out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3]; } -static void CopyValue(const glTF2::vec4& v, aiColor3D& out) +/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out) { out.r = v[0]; out.g = v[1]; out.b = v[2]; -} +}*/ static void CopyValue(const glTF2::vec3& v, aiColor4D& out) { @@ -173,14 +173,9 @@ inline void SetMaterialColorProperty(Asset& r, vec4& prop, aiMaterial* mat, cons inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) { - vec4 prop4; - - prop4[0] = prop[0]; - prop4[1] = prop[1]; - prop4[2] = prop[2]; - prop4[3] = 1; - - return SetMaterialColorProperty(r, prop4, mat, pKey, type, idx); + aiColor4D col; + CopyValue(prop, col); + mat->AddProperty(&col, 1, pKey, type, idx); } inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0) From 7245cceead0ea647a61cebafc32191e2f588c7ea Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 3 Sep 2017 22:03:02 -0400 Subject: [PATCH 25/56] Set default values on Sampler --- code/glTF2Asset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 875594254..711e8231b 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -800,7 +800,7 @@ namespace glTF2 SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required) SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required) - Sampler() {} + Sampler() { SetDefaults(); } void Read(Value& obj, Asset& r); void SetDefaults(); }; From a9c4fa84b5f48fccfc099d8c300144d5ba1807eb Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 3 Sep 2017 22:09:48 -0400 Subject: [PATCH 26/56] Sampler improvements; Add new LazyDict method Samplers are now imported into assimp internal format from textures; Samplers have defaults as per spec; Sampler enums are strongly typed with UNSET values; Samplers are exported properly; Sampler filters are exported as well; Samplers are re-used across textures on export Default sampler values are not written --- code/glTF2Asset.h | 25 ++++++----- code/glTF2Asset.inl | 28 +++++++----- code/glTF2AssetWriter.inl | 23 ++++++---- code/glTF2Exporter.cpp | 91 +++++++++++++++++++++++---------------- code/glTF2Exporter.h | 2 +- code/glTF2Importer.cpp | 21 +++++++++ 6 files changed, 123 insertions(+), 67 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 711e8231b..aabd462d8 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -242,15 +242,17 @@ namespace glTF2 }; //! Values for the Sampler::magFilter field - enum SamplerMagFilter + enum class SamplerMagFilter: unsigned int { + UNSET = 0, SamplerMagFilter_Nearest = 9728, SamplerMagFilter_Linear = 9729 }; //! Values for the Sampler::minFilter field - enum SamplerMinFilter + enum class SamplerMinFilter: unsigned int { + UNSET = 0, SamplerMinFilter_Nearest = 9728, SamplerMinFilter_Linear = 9729, SamplerMinFilter_Nearest_Mipmap_Nearest = 9984, @@ -260,11 +262,12 @@ namespace glTF2 }; //! Values for the Sampler::wrapS and Sampler::wrapT field - enum SamplerWrap + enum class SamplerWrap: unsigned int { - SamplerWrap_Clamp_To_Edge = 33071, - SamplerWrap_Mirrored_Repeat = 33648, - SamplerWrap_Repeat = 10497 + UNSET = 0, + Clamp_To_Edge = 33071, + Mirrored_Repeat = 33648, + Repeat = 10497 }; //! Values for the Texture::format and Texture::internalFormat fields @@ -795,10 +798,10 @@ namespace glTF2 struct Sampler : public Object { - SamplerMagFilter magFilter; //!< The texture magnification filter. (required) - SamplerMinFilter minFilter; //!< The texture minification filter. (required) - SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required) - SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required) + SamplerMagFilter magFilter; //!< The texture magnification filter. + SamplerMinFilter minFilter; //!< The texture minification filter. + SamplerWrap wrapS; //!< The texture wrapping in the S direction. + SamplerWrap wrapT; //!< The texture wrapping in the T direction. Sampler() { SetDefaults(); } void Read(Value& obj, Asset& r); @@ -955,6 +958,8 @@ namespace glTF2 Ref Get(unsigned int i); Ref Get(const char* id); + bool Has(const char* id); + Ref Create(const char* id); Ref Create(const std::string& id) { return Create(id.c_str()); } diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index bebaeba53..5764c6ff6 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -244,7 +244,17 @@ Ref LazyDict::Get(const char* id) return Ref(mObjs, it->second); } - throw std::out_of_range("id \"" + std::string(id) + "\" Doesn't exist"); + return Create(id); +} + +template +bool LazyDict::Has(const char* id) +{ + id = T::TranslateId(mAsset, id); + + typename IdDict::iterator it = mObjsById.find(id); + + return it != mObjsById.end(); } template @@ -697,6 +707,7 @@ inline void Sampler::Read(Value& obj, Asset& r) { SetDefaults(); + ReadMember(obj, "name", name); ReadMember(obj, "magFilter", magFilter); ReadMember(obj, "minFilter", minFilter); ReadMember(obj, "wrapS", wrapS); @@ -705,10 +716,11 @@ inline void Sampler::Read(Value& obj, Asset& r) inline void Sampler::SetDefaults() { - magFilter = SamplerMagFilter_Linear; - minFilter = SamplerMinFilter_Linear; - wrapS = SamplerWrap_Repeat; - wrapT = SamplerWrap_Repeat; + //only wrapping modes have defaults + wrapS = SamplerWrap::Repeat; + wrapT = SamplerWrap::Repeat; + magFilter = SamplerMagFilter::UNSET; + minFilter = SamplerMinFilter::UNSET; } inline void Texture::Read(Value& obj, Asset& r) @@ -883,7 +895,6 @@ inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) // Valid attribute semantics include POSITION, NORMAL, TEXCOORD, COLOR, JOINT, JOINTMATRIX, // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. - //@TODO: update this int undPos = 0; Mesh::AccessorList* vec = 0; if (GetAttribVector(prim, attr, vec, undPos)) { @@ -943,7 +954,6 @@ inline void Node::Read(Value& obj, Asset& r) } } - if (Value* matrix = FindArray(obj, "matrix")) { ReadValue(*matrix, this->matrix); } @@ -978,7 +988,6 @@ inline void Scene::Read(Value& obj, Asset& r) } } - inline void AssetMetadata::Read(Document& doc) { // read the version, etc. @@ -1013,8 +1022,6 @@ inline void AssetMetadata::Read(Document& doc) } } - - // // Asset methods implementation // @@ -1142,7 +1149,6 @@ inline void Asset::SetAsBinary() } } - inline void Asset::ReadExtensionsUsed(Document& doc) { Value* extsUsed = FindArray(doc, "extensionsUsed"); diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 69d54d97b..f7943172e 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -467,17 +467,24 @@ namespace glTF2 { inline void Write(Value& obj, Sampler& b, AssetWriter& w) { - if (b.wrapS) { - obj.AddMember("wrapS", b.wrapS, w.mAl); + if (!b.name.empty()) { + obj.AddMember("name", b.name, w.mAl); } - if (b.wrapT) { - obj.AddMember("wrapT", b.wrapT, w.mAl); + + if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) { + obj.AddMember("wrapS", static_cast(b.wrapS), w.mAl); } - if (b.magFilter) { - obj.AddMember("magFilter", b.magFilter, w.mAl); + + if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) { + obj.AddMember("wrapT", static_cast(b.wrapT), w.mAl); } - if (b.minFilter) { - obj.AddMember("minFilter", b.minFilter, w.mAl); + + if (b.magFilter != SamplerMagFilter::UNSET) { + obj.AddMember("magFilter", static_cast(b.magFilter), w.mAl); + } + + if (b.minFilter != SamplerMinFilter::UNSET) { + obj.AddMember("minFilter", static_cast(b.minFilter), w.mAl); } } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9a2c1cd75..fec7236e3 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -223,50 +223,63 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu return acc; } -void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture) +inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map) { - std::string samplerId = mAsset->FindUniqueID("", "sampler"); - texture->sampler = mAsset->samplers.Create(samplerId); - - aiTextureMapMode mapU, mapV; - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); - - switch (mapU) { - case aiTextureMapMode_Wrap: - texture->sampler->wrapS = SamplerWrap_Repeat; - break; + switch (map) { case aiTextureMapMode_Clamp: - texture->sampler->wrapS = SamplerWrap_Clamp_To_Edge; + wrap = SamplerWrap::Clamp_To_Edge; break; case aiTextureMapMode_Mirror: - texture->sampler->wrapS = SamplerWrap_Mirrored_Repeat; + wrap = SamplerWrap::Mirrored_Repeat; break; - case aiTextureMapMode_Decal: - default: - texture->sampler->wrapS = SamplerWrap_Repeat; - break; - }; - - switch (mapV) { case aiTextureMapMode_Wrap: - texture->sampler->wrapT = SamplerWrap_Repeat; - break; - case aiTextureMapMode_Clamp: - texture->sampler->wrapT = SamplerWrap_Clamp_To_Edge; - break; - case aiTextureMapMode_Mirror: - texture->sampler->wrapT = SamplerWrap_Mirrored_Repeat; - break; case aiTextureMapMode_Decal: default: - texture->sampler->wrapT = SamplerWrap_Repeat; + wrap = SamplerWrap::Repeat; break; }; +} - // Hard coded Texture filtering options because I do not know where to find them in the aiMaterial. - texture->sampler->magFilter = SamplerMagFilter_Linear; - texture->sampler->minFilter = SamplerMinFilter_Linear_Mipmap_Linear; +void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, aiTextureType tt, unsigned int slot) +{ + aiString aId; + std::string id; + if (aiGetMaterialString(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str(), tt, slot, &aId) == AI_SUCCESS) { + id = aId.C_Str(); + } + + if (mAsset->samplers.Has(id.c_str())) { + texture->sampler = mAsset->samplers.Get(id.c_str()); + } else { + id = mAsset->FindUniqueID(id, "sampler"); + + texture->sampler = mAsset->samplers.Create(id.c_str()); + + aiTextureMapMode mapU, mapV; + SamplerMagFilter filterMag; + SamplerMinFilter filterMin; + + if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) { + SetSamplerWrap(texture->sampler->wrapS, mapU); + } + + if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) { + SetSamplerWrap(texture->sampler->wrapT, mapV); + } + + if (aiGetMaterialInteger(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str(), tt, slot, (int*)&filterMag) == AI_SUCCESS) { + texture->sampler->magFilter = filterMag; + } + + if (aiGetMaterialInteger(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str(), tt, slot, (int*)&filterMin) == AI_SUCCESS) { + texture->sampler->minFilter = filterMin; + } + + aiString name; + if (aiGetMaterialString(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str(), 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) @@ -324,7 +337,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe texture->source->uri = path; } - GetTexSampler(mat, texture); + GetTexSampler(mat, texture, tt, slot); } } } @@ -390,17 +403,23 @@ void glTF2Exporter::ExportMaterials() for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; + std::string id = "material_" + std::to_string(i); + + Ref m = mAsset->materials.Create(id); + std::string name; if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { name = aiName.C_Str(); } name = mAsset->FindUniqueID(name, "material"); - Ref m = mAsset->materials.Create(name); + m->name = name; GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, aiTextureType_UNKNOWN, 0);//get unknown slot GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); + mat->Get("$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, m->pbrMetallicRoughness.metallicFactor); + mat->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, m->pbrMetallicRoughness.roughnessFactor); GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS); GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP); @@ -409,8 +428,6 @@ void glTF2Exporter::ExportMaterials() mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff); - mat->Get("$mat.gltf.metallicFactor", 0, 0, m->pbrMetallicRoughness.metallicFactor); - mat->Get("$mat.gltf.roughnessFactor", 0, 0, m->pbrMetallicRoughness.roughnessFactor); mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode); bool hasPbrSpecularGlossiness; diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 4b9fe0ce0..420c2afa6 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -108,7 +108,7 @@ namespace Assimp void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); - void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture); + 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); diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 08145f5fe..86301a3f4 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -194,6 +194,27 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& const char *texCoordName = (std::string(_AI_MATKEY_TEXTURE_BASE) + ".texCoord").c_str(); mat->AddProperty(&prop.texCoord, 1, texCoordName, texType, texSlot); + + if (prop.texture->sampler) { + Ref sampler = prop.texture->sampler; + + aiString name(sampler->name); + aiString id(sampler->id); + + mat->AddProperty(&name, (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str(), texType, texSlot); + mat->AddProperty(&id, (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str(), texType, texSlot); + + mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); + + if (sampler->magFilter != SamplerMagFilter::UNSET) { + mat->AddProperty(&sampler->magFilter, 1, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str(), texType, texSlot); + } + + if (sampler->minFilter != SamplerMinFilter::UNSET) { + mat->AddProperty(&sampler->minFilter, 1, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str(), texType, texSlot); + } + } } } From 37527849b771552c9003dc488a5a97d76a196123 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 3 Sep 2017 22:11:20 -0400 Subject: [PATCH 27/56] Export material names properly --- code/glTF2AssetWriter.inl | 4 ---- code/glTF2Importer.cpp | 8 +++++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index f7943172e..c10a6a08b 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -284,10 +284,6 @@ namespace glTF2 { inline void Write(Value& obj, Material& m, AssetWriter& w) { - if (!m.name.empty()) { - obj.AddMember("name", m.name, w.mAl); - } - Value pbrMetallicRoughness; pbrMetallicRoughness.SetObject(); { diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 86301a3f4..82ea5f3e7 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -125,7 +125,6 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool } - //static void CopyValue(const glTF2::vec3& v, aiColor3D& out) //{ // out.r = v[0]; out.g = v[1]; out.b = v[2]; @@ -228,8 +227,11 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) Material& mat = r.materials[i]; - aiString str(mat.id); - aimat->AddProperty(&str, AI_MATKEY_NAME); + if (!mat.name.empty()) { + aiString str(mat.name); + + aimat->AddProperty(&str, AI_MATKEY_NAME); + } SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); From 21259e08357c0b8487ab33ffd87d5f9118420dd7 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 14:39:52 -0400 Subject: [PATCH 28/56] Use different form of index accessor --- code/glTF2Asset.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 5764c6ff6..88dbfcfdb 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -211,7 +211,7 @@ Ref LazyDict::Retrieve(unsigned int i) throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\""); } - Value& obj = mDict->operator[](i); + Value &obj = (*mDict)[i]; if (!obj.IsObject()) { throw DeadlyImportError("GLTF: Object at index \"" + std::to_string(i) + "\" is not a JSON object"); From 1a5823700f17caa6c6cdedfd34ce5bbd3ba85556 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 14:40:27 -0400 Subject: [PATCH 29/56] Remove need for Has by returning an empty Ref in Get --- code/glTF2Asset.h | 2 -- code/glTF2Asset.inl | 12 +----------- code/glTF2Exporter.cpp | 4 ++-- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index aabd462d8..9a70ff4ff 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -958,8 +958,6 @@ namespace glTF2 Ref Get(unsigned int i); Ref Get(const char* id); - bool Has(const char* id); - Ref Create(const char* id); Ref Create(const std::string& id) { return Create(id.c_str()); } diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 88dbfcfdb..1c75d0040 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -244,17 +244,7 @@ Ref LazyDict::Get(const char* id) return Ref(mObjs, it->second); } - return Create(id); -} - -template -bool LazyDict::Has(const char* id) -{ - id = T::TranslateId(mAsset, id); - - typename IdDict::iterator it = mObjsById.find(id); - - return it != mObjsById.end(); + return Ref(); } template diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index fec7236e3..073309b06 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -248,8 +248,8 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, a id = aId.C_Str(); } - if (mAsset->samplers.Has(id.c_str())) { - texture->sampler = mAsset->samplers.Get(id.c_str()); + if (Ref ref = mAsset->samplers.Get(id.c_str())) { + texture->sampler = ref; } else { id = mAsset->FindUniqueID(id, "sampler"); From 03cfa04ee4a4ef85a3eeefa879bec4e088418287 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 15:45:32 -0400 Subject: [PATCH 30/56] Define default material values as static constants for reuse --- code/glTF2Asset.h | 10 +++++++--- code/glTF2Asset.inl | 16 ++++++++-------- code/glTF2AssetWriter.inl | 14 ++------------ 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 9a70ff4ff..486e23bc0 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -135,8 +135,7 @@ namespace glTF2 // Vec/matrix types, as raw float arrays typedef float (vec3)[3]; typedef float (vec4)[4]; - typedef float (mat4)[16]; - + typedef float (mat4)[16]; namespace Util { @@ -670,7 +669,12 @@ namespace glTF2 inline uint8_t* StealData(); inline void SetData(uint8_t* data, size_t length, Asset& r); - }; + }; + + const vec4 defaultBaseColor = {1, 1, 1, 1}; + const vec3 defaultEmissiveFactor = {0, 0, 0}; + const vec4 defaultDiffuseFactor = {1, 1, 1, 1}; + const vec3 defaultSpecularFactor = {1, 1, 1}; struct TextureInfo { diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 1c75d0040..07e0a5e8e 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -803,28 +803,28 @@ inline void Material::Read(Value& material, Asset& r) } namespace { - void SetVector(vec4& v, float x, float y, float z, float w) - { v[0] = x; v[1] = y; v[2] = z; v[3] = w; } + void SetVector(vec4& v, const float(&in)[4]) + { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; v[3] = in[3]; } - void SetVector(vec3& v, float x, float y, float z) - { v[0] = x; v[1] = y; v[2] = z; } + void SetVector(vec3& v, const float(&in)[3]) + { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; } } inline void Material::SetDefaults() { //pbr materials - SetVector(pbrMetallicRoughness.baseColorFactor, 1, 1, 1, 1); + SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor); pbrMetallicRoughness.metallicFactor = 1.0; pbrMetallicRoughness.roughnessFactor = 1.0; - SetVector(emissiveFactor, 0, 0, 0); + SetVector(emissiveFactor, defaultEmissiveFactor); alphaMode = "OPAQUE"; alphaCutoff = 0.5; doubleSided = false; //pbrSpecularGlossiness properties - SetVector(pbrSpecularGlossiness.diffuseFactor, 1, 1, 1, 1); - SetVector(pbrSpecularGlossiness.specularFactor, 1, 1, 1); + SetVector(pbrSpecularGlossiness.diffuseFactor, defaultDiffuseFactor); + SetVector(pbrSpecularGlossiness.specularFactor, defaultSpecularFactor); pbrSpecularGlossiness.glossinessFactor = 1.0; } diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index c10a6a08b..475c7a0d9 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -268,7 +268,7 @@ namespace glTF2 { } template - inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, float(&defaultVal)[N], MemoryPoolAllocator<>& al) + inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al) { if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) { WriteVec(obj, prop, propName, al); @@ -289,10 +289,7 @@ namespace glTF2 { { WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl); WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl); - - //@TODO: define this as a constant? - vec4 defaultEmissiveFactor = {1, 1, 1, 1}; - WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultEmissiveFactor, w.mAl); + WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl); if (m.pbrMetallicRoughness.metallicFactor != 1) { WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl); @@ -310,9 +307,6 @@ namespace glTF2 { WriteTex(obj, m.normalTexture, "normalTexture", w.mAl); WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl); WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl); - - //@TODO: define this as a constant? - vec3 defaultEmissiveFactor = {0, 0, 0}; WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl); if (m.alphaCutoff != 0.5) { @@ -335,11 +329,7 @@ namespace glTF2 { pbrSpecularGlossiness.SetObject(); { //pbrSpecularGlossiness - - vec4 defaultDiffuseFactor = {1, 1, 1, 1}; WriteVec(pbrSpecularGlossiness, m.pbrSpecularGlossiness.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); - - vec3 defaultSpecularFactor = {1, 1, 1}; WriteVec(pbrSpecularGlossiness, m.pbrSpecularGlossiness.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); if (m.pbrSpecularGlossiness.glossinessFactor != 1) { From 44757af34a0047e974ba6d30b9b027d0fffecc5d Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 16:29:00 -0400 Subject: [PATCH 31/56] Implement pbrSpecularGlossiness property as Nullable --- code/glTF2Asset.h | 8 +++++--- code/glTF2Asset.inl | 23 ++++++++++++++--------- code/glTF2AssetWriter.inl | 21 +++++++++++---------- code/glTF2Exporter.cpp | 15 +++++++++------ code/glTF2Importer.cpp | 14 +++++++------- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 486e23bc0..07f8614ab 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -711,12 +711,14 @@ namespace glTF2 struct PbrSpecularGlossiness { - bool on = false; vec4 diffuseFactor; vec3 specularFactor; float glossinessFactor; TextureInfo diffuseTexture; - TextureInfo specularGlossinessTexture; + TextureInfo specularGlossinessTexture; + + PbrSpecularGlossiness() { SetDefaults(); } + void SetDefaults(); }; //! The material appearance of a primitive. @@ -735,7 +737,7 @@ namespace glTF2 bool doubleSided; //extension: KHR_materials_pbrSpecularGlossiness - PbrSpecularGlossiness pbrSpecularGlossiness; + Nullable pbrSpecularGlossiness; Material() { SetDefaults(); } void Read(Value& obj, Asset& r); diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 07e0a5e8e..e2d812563 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -790,13 +790,15 @@ inline void Material::Read(Value& material, Asset& r) if (Value* extensions = FindObject(material, "extensions")) { if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) { - this->pbrSpecularGlossiness.on = true; + PbrSpecularGlossiness pbrSG; - ReadMember(*pbrSpecularGlossiness, "diffuseFactor", this->pbrSpecularGlossiness.diffuseFactor); - ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", this->pbrSpecularGlossiness.diffuseTexture); - ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", this->pbrSpecularGlossiness.specularGlossinessTexture); - ReadMember(*pbrSpecularGlossiness, "specularFactor", this->pbrSpecularGlossiness.specularFactor); - ReadMember(*pbrSpecularGlossiness, "glossinessFactor", this->pbrSpecularGlossiness.glossinessFactor); + ReadMember(*pbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor); + ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture); + ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture); + ReadMember(*pbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor); + ReadMember(*pbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor); + + this->pbrSpecularGlossiness = Nullable(pbrSG); } } } @@ -821,11 +823,14 @@ inline void Material::SetDefaults() alphaMode = "OPAQUE"; alphaCutoff = 0.5; doubleSided = false; +} +inline void PbrSpecularGlossiness::SetDefaults() +{ //pbrSpecularGlossiness properties - SetVector(pbrSpecularGlossiness.diffuseFactor, defaultDiffuseFactor); - SetVector(pbrSpecularGlossiness.specularFactor, defaultSpecularFactor); - pbrSpecularGlossiness.glossinessFactor = 1.0; + SetVector(diffuseFactor, defaultDiffuseFactor); + SetVector(specularFactor, defaultSpecularFactor); + glossinessFactor = 1.0; } namespace { diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 475c7a0d9..ad68a14e1 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -324,22 +324,23 @@ namespace glTF2 { Value exts; exts.SetObject(); - if (m.pbrSpecularGlossiness.on) { + if (m.pbrSpecularGlossiness.isPresent) { Value pbrSpecularGlossiness; pbrSpecularGlossiness.SetObject(); - { - //pbrSpecularGlossiness - WriteVec(pbrSpecularGlossiness, m.pbrSpecularGlossiness.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); - WriteVec(pbrSpecularGlossiness, m.pbrSpecularGlossiness.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); - if (m.pbrSpecularGlossiness.glossinessFactor != 1) { - WriteFloat(obj, m.pbrSpecularGlossiness.glossinessFactor, "glossinessFactor", w.mAl); - } + PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value; - WriteTex(pbrSpecularGlossiness, m.pbrSpecularGlossiness.diffuseTexture, "diffuseTexture", w.mAl); - WriteTex(pbrSpecularGlossiness, m.pbrSpecularGlossiness.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); + //pbrSpecularGlossiness + WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); + WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); + + if (pbrSG.glossinessFactor != 1) { + WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); } + WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl); + WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); + if (!pbrSpecularGlossiness.ObjectEmpty()) { exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl); } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 073309b06..600e2b3d4 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -439,12 +439,15 @@ void glTF2Exporter::ExportMaterials() KHR_materials_pbrSpecularGlossiness = true; } - m->pbrSpecularGlossiness.on = true; - GetMatColor(mat, m->pbrSpecularGlossiness.diffuseFactor, "$clr.diffuse", 0, 1); - GetMatColor(mat, m->pbrSpecularGlossiness.specularFactor, "$clr.specular", 0, 1); - mat->Get("$mat.gltf.glossinessFactor", 0, 0, m->pbrSpecularGlossiness.glossinessFactor); - GetMatTex(mat, m->pbrSpecularGlossiness.diffuseTexture, aiTextureType_DIFFUSE, 1); - GetMatTex(mat, m->pbrSpecularGlossiness.specularGlossinessTexture, aiTextureType_UNKNOWN, 1); + PbrSpecularGlossiness pbrSG; + + GetMatColor(mat, pbrSG.diffuseFactor, "$clr.diffuse", 0, 1); + GetMatColor(mat, pbrSG.specularFactor, "$clr.specular", 0, 1); + mat->Get("$mat.gltf.glossinessFactor", 0, 0, pbrSG.glossinessFactor); + GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE, 1); + GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_UNKNOWN, 1); + + m->pbrSpecularGlossiness = Nullable(pbrSG); } } } diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 82ea5f3e7..ff806257f 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -249,13 +249,13 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff"); //pbrSpecularGlossiness - if (mat.pbrSpecularGlossiness.on) { - aimat->AddProperty(&mat.pbrSpecularGlossiness.on, 1, "$mat.gltf.pbrSpecularGlossiness.on"); - SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.diffuseFactor, aimat, "$clr.diffuse", 0, 1); - SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.specularFactor, aimat, "$clr.specular", 0, 1); - aimat->AddProperty(&mat.pbrSpecularGlossiness.glossinessFactor, 1, "$mat.gltf.pbrSpecularGlossiness.glossinessFactor"); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.diffuseTexture, aimat, aiTextureType_DIFFUSE, 1); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.specularGlossinessTexture, aimat, aiTextureType_UNKNOWN, 1); + if (mat.pbrSpecularGlossiness.isPresent) { + aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, "$mat.gltf.pbrSpecularGlossiness.on"); + SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.value.diffuseFactor, aimat, "$clr.diffuse", 0, 1); + SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.value.specularFactor, aimat, "$clr.specular", 0, 1); + aimat->AddProperty(&mat.pbrSpecularGlossiness.value.glossinessFactor, 1, "$mat.gltf.pbrSpecularGlossiness.glossinessFactor"); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.value.diffuseTexture, aimat, aiTextureType_DIFFUSE, 1); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.value.specularGlossinessTexture, aimat, aiTextureType_UNKNOWN, 1); } } } From 54dd4804cda6f5f6a6e08781ee4e42325f12755a Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 16:39:34 -0400 Subject: [PATCH 32/56] Fix indentation --- code/glTF2Importer.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index ff806257f..742088042 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -306,7 +306,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) for (unsigned int m = 0; m < r.meshes.Size(); ++m) { Mesh& mesh = r.meshes[m]; - meshOffsets.push_back(k); + meshOffsets.push_back(k); k += unsigned(mesh.primitives.size()); for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { @@ -339,16 +339,17 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) case PrimitiveMode_TRIANGLE_FAN: aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; break; + } Mesh::Primitive::Attributes& attr = prim.attributes; - if (attr.position.size() > 0 && attr.position[0]) { + if (attr.position.size() > 0 && attr.position[0]) { aim->mNumVertices = attr.position[0]->count; attr.position[0]->ExtractData(aim->mVertices); - } + } - if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); + if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals); for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); @@ -362,7 +363,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r) if (prim.indices) { - aiFace* faces = 0; + aiFace* faces = 0; unsigned int nFaces = 0; unsigned int count = prim.indices->count; @@ -638,7 +639,7 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO // TODO: it does not split the loaded vertices, should it? //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; - MakeVerboseFormatProcess process; + MakeVerboseFormatProcess process; process.Execute(pScene); From 3ba00ca4219ea12fdcab9f20c32720cb533b26b2 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 18:04:09 -0400 Subject: [PATCH 33/56] Define gltf material property names as constants --- code/glTF2Asset.h | 26 +++++++++++++++++++++++++- code/glTF2Exporter.cpp | 30 +++++++++++++++--------------- code/glTF2Importer.cpp | 36 ++++++++++++++++++------------------ 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 07f8614ab..b4369fe71 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -163,7 +163,31 @@ namespace glTF2 //! Magic number for GLB files - #define AI_GLB_MAGIC_NUMBER "glTF" + #define AI_GLB_MAGIC_NUMBER "glTF" + + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0,0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 + #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 + #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR "$clr.diffuse", 0, 1 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR "$clr.specular", 0, 1 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0,0 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE aiTextureType_DIFFUSE, 1 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE aiTextureType_UNKNOWN, 1 + + #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE (std::string(_AI_MATKEY_TEXTURE_BASE) + ".texCoord").c_str() + #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str() + #define _AI_MATKEY_GLTF_MAPPINGID_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str() + #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str() + #define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str() + + #define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N #ifdef ASSIMP_API #include "./../include/assimp/Compiler/pushpack1.h" diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 600e2b3d4..931e491e3 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -244,7 +244,7 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, a { aiString aId; std::string id; - if (aiGetMaterialString(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str(), tt, slot, &aId) == AI_SUCCESS) { + if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) { id = aId.C_Str(); } @@ -267,16 +267,16 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, a SetSamplerWrap(texture->sampler->wrapT, mapV); } - if (aiGetMaterialInteger(mat, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str(), 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, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str(), 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, (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str(), tt, slot, &name) == AI_SUCCESS) { + if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) { texture->sampler->name = name.C_Str(); } } @@ -416,10 +416,10 @@ void glTF2Exporter::ExportMaterials() m->name = name; GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); - GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, aiTextureType_UNKNOWN, 0);//get unknown slot + GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); - mat->Get("$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0, m->pbrMetallicRoughness.metallicFactor); - mat->Get("$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0, m->pbrMetallicRoughness.roughnessFactor); + mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor); + mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor); GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS); GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP); @@ -427,11 +427,11 @@ void glTF2Exporter::ExportMaterials() GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE); mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); - mat->Get("$mat.gltf.alphaCutoff", 0, 0, m->alphaCutoff); - mat->Get("$mat.gltf.alphaMode", 0, 0, m->alphaMode); + mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); + mat->Get(AI_MATKEY_GLTF_ALPHAMODE, m->alphaMode); bool hasPbrSpecularGlossiness; - mat->Get("$mat.gltf.pbrSpecularGlossiness.on", 0, 0, hasPbrSpecularGlossiness); + mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness); if (hasPbrSpecularGlossiness) { @@ -441,11 +441,11 @@ void glTF2Exporter::ExportMaterials() PbrSpecularGlossiness pbrSG; - GetMatColor(mat, pbrSG.diffuseFactor, "$clr.diffuse", 0, 1); - GetMatColor(mat, pbrSG.specularFactor, "$clr.specular", 0, 1); - mat->Get("$mat.gltf.glossinessFactor", 0, 0, pbrSG.glossinessFactor); - GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE, 1); - GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_UNKNOWN, 1); + GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR); + GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR); + mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor); + GetMatTex(mat, pbrSG.diffuseTexture, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE); + GetMatTex(mat, pbrSG.specularGlossinessTexture, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE); m->pbrSpecularGlossiness = Nullable(pbrSG); } diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 742088042..860974243 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -190,9 +190,7 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& } mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); - - const char *texCoordName = (std::string(_AI_MATKEY_TEXTURE_BASE) + ".texCoord").c_str(); - mat->AddProperty(&prop.texCoord, 1, texCoordName, texType, texSlot); + mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); if (prop.texture->sampler) { Ref sampler = prop.texture->sampler; @@ -200,18 +198,18 @@ inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& aiString name(sampler->name); aiString id(sampler->id); - mat->AddProperty(&name, (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str(), texType, texSlot); - mat->AddProperty(&id, (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str(), texType, texSlot); + mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot)); + mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot)); mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); if (sampler->magFilter != SamplerMagFilter::UNSET) { - mat->AddProperty(&sampler->magFilter, 1, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str(), texType, texSlot); + mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot)); } if (sampler->minFilter != SamplerMinFilter::UNSET) { - mat->AddProperty(&sampler->minFilter, 1, (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str(), texType, texSlot); + mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); } } } @@ -235,9 +233,9 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_UNKNOWN); - aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, "$mat.gltf.pbrMetallicRoughness.metallicFactor"); - aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, "$mat.gltf.pbrMetallicRoughness.roughnessFactor"); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); + aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP); @@ -245,17 +243,19 @@ void glTF2Importer::ImportMaterials(glTF2::Asset& r) SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE); aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); - aimat->AddProperty(&mat.alphaMode, 1, "$mat.gltf.alphaMode"); - aimat->AddProperty(&mat.alphaCutoff, 1, "$mat.gltf.alphaCutoff"); + aimat->AddProperty(&mat.alphaMode, 1, AI_MATKEY_GLTF_ALPHAMODE); + aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF); //pbrSpecularGlossiness if (mat.pbrSpecularGlossiness.isPresent) { - aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, "$mat.gltf.pbrSpecularGlossiness.on"); - SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.value.diffuseFactor, aimat, "$clr.diffuse", 0, 1); - SetMaterialColorProperty(r, mat.pbrSpecularGlossiness.value.specularFactor, aimat, "$clr.specular", 0, 1); - aimat->AddProperty(&mat.pbrSpecularGlossiness.value.glossinessFactor, 1, "$mat.gltf.pbrSpecularGlossiness.glossinessFactor"); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.value.diffuseTexture, aimat, aiTextureType_DIFFUSE, 1); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrSpecularGlossiness.value.specularGlossinessTexture, aimat, aiTextureType_UNKNOWN, 1); + PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; + + aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS); + SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR); + SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR); + aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE); } } } From da6a252efbb433e25d61e0dbdae9873d3829da76 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 5 Sep 2017 18:06:59 -0400 Subject: [PATCH 34/56] Fix METALLIC_FACTOR typo --- code/glTF2Asset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index b4369fe71..d894e9473 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -166,7 +166,7 @@ namespace glTF2 #define AI_GLB_MAGIC_NUMBER "glTF" #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0,0 - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 From 37582131f494babbf3ad4ba878796fb0384dc085 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 6 Sep 2017 14:16:52 -0400 Subject: [PATCH 35/56] =?UTF-8?q?Set=20the=20metallicFactor=20to=200=20if?= =?UTF-8?q?=20source=20file=20doesn=E2=80=99t=20have=20metallicFactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, the models have full metallic materials and appear very dim --- code/glTF2Exporter.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 931e491e3..a5c74fd46 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -418,7 +418,12 @@ void glTF2Exporter::ExportMaterials() GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); - mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor); + + if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) { + //if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0 + m->pbrMetallicRoughness.metallicFactor = 0; + } + mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor); GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS); From 0a8183531e0fc43780e51008c04bb2d34ecb5eb5 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 6 Sep 2017 14:17:24 -0400 Subject: [PATCH 36/56] =?UTF-8?q?Set=20alphaMode,=20baseColorFactor=20opac?= =?UTF-8?q?ity=20when=20model=E2=80=99s=20opacity=20isn=E2=80=99t=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/glTF2Exporter.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index a5c74fd46..9130c750c 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -433,7 +433,17 @@ void glTF2Exporter::ExportMaterials() mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); - mat->Get(AI_MATKEY_GLTF_ALPHAMODE, m->alphaMode); + + if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, m->alphaMode) != AI_SUCCESS) { + float opacity; + + if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { + if (opacity < 1) { + m->alphaMode = "MASK"; + m->pbrMetallicRoughness.baseColorFactor[3] *= opacity; + } + } + } bool hasPbrSpecularGlossiness; mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness); From a5e8e0b2bd8fbdd625920ccf448d9475f327fed5 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 6 Sep 2017 14:17:37 -0400 Subject: [PATCH 37/56] Remove commented out code --- code/glTF2Asset.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index d894e9473..12cad25ba 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -717,13 +717,6 @@ namespace glTF2 float strength = 1; }; - //! Holds a material property that can be a texture or a color (fallback for glTF 1) - /*struct FallbackTexProperty - { - Ref texture; - vec4 color; - };*/ - struct PbrMetallicRoughness { vec4 baseColorFactor; From 2ee7991558be791115087670026b9039cfac6bff Mon Sep 17 00:00:00 2001 From: John Senneker Date: Wed, 6 Sep 2017 14:49:25 -0400 Subject: [PATCH 38/56] Restrict search for OFF header to first 3 bytes --- code/OFFLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index 2723beb0e..5038176e2 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -94,7 +94,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool { if (!pIOHandler)return true; const char* tokens[] = {"off"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3); } return false; } From 19876e98227ebf3a76ad994cd1f190c1b382ca82 Mon Sep 17 00:00:00 2001 From: John Senneker Date: Wed, 6 Sep 2017 14:50:02 -0400 Subject: [PATCH 39/56] Add support for importing both glTF and glTF2 files --- code/ImporterRegistry.cpp | 2 ++ code/glTF2Importer.cpp | 28 ++++++++++++---------------- code/glTFAsset.inl | 4 ---- code/glTFImporter.cpp | 26 ++++++++++---------------- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index 2b5d9c1a0..b4d2c3dcf 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -181,6 +181,7 @@ corresponding preprocessor flag to selectively disable formats. # include "AssbinLoader.h" #endif #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER +# include "glTFImporter.h" # include "glTF2Importer.h" #endif #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER @@ -335,6 +336,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) out.push_back( new AssbinImporter() ); #endif #if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) + out.push_back( new glTFImporter() ); out.push_back( new glTF2Importer() ); #endif #if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER ) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 860974243..1ab23fd18 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -58,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "glTF2Asset.h" // This is included here so WriteLazyDict's definition is found. #include "glTF2AssetWriter.h" +#include +#include using namespace Assimp; using namespace glTF2; @@ -100,24 +102,18 @@ const aiImporterDesc* glTF2Importer::GetInfo() const bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - const std::string& extension = GetExtension(pFile); + const std::string &extension = GetExtension(pFile); - if (extension == "gltf" || extension == "glb") - return true; + if (extension != "gltf") // We currently can't read glTF2 binary files (.glb) + return false; - if ((checkSig || !extension.length()) && pIOHandler) { - char buffer[4]; - - std::unique_ptr pStream(pIOHandler->Open(pFile)); - if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { - if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { - return true; // Has GLB header - } - else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0 - || memcmp(buffer, "{\n ", sizeof(buffer)) == 0) { - // seems a JSON file, and we're the only format that can read them - return true; - } + if (checkSig && pIOHandler) { + glTF2::Asset asset(pIOHandler); + try { + asset.Load(pFile, extension == "glb"); + return asset.asset.version >= 2; + } catch (...) { + return false; } } diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 91d36c59b..32fe77288 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -1243,10 +1243,6 @@ inline void AssetMetadata::Read(Document& doc) } version = std::max(statedVersion, version); - if (version == 0) { - // if missing version, we'll assume version 1... - version = 1; - } if (version != 1) { char msg[128]; diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 0ded26294..6dbeb7e91 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -100,24 +100,18 @@ const aiImporterDesc* glTFImporter::GetInfo() const bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - const std::string& extension = GetExtension(pFile); + const std::string &extension = GetExtension(pFile); - if (extension == "gltf" || extension == "glb") - return true; + if (extension != "gltf" && extension != "glb") + return false; - if ((checkSig || !extension.length()) && pIOHandler) { - char buffer[4]; - - std::unique_ptr pStream(pIOHandler->Open(pFile)); - if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { - if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { - return true; // Has GLB header - } - else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0 - || memcmp(buffer, "{\n ", sizeof(buffer)) == 0) { - // seems a JSON file, and we're the only format that can read them - return true; - } + if (checkSig && pIOHandler) { + glTF::Asset asset(pIOHandler); + try { + asset.Load(pFile, extension == "glb"); + return asset.asset.version < 2; + } catch (...) { + return false; } } From 140b903d7a062216016597ef30f4885b28e5c767 Mon Sep 17 00:00:00 2001 From: John Senneker Date: Wed, 6 Sep 2017 15:32:44 -0400 Subject: [PATCH 40/56] Fix parsing of glTF version Handle version as int in gltf Fix format specifiers in glTF version parser --- code/glTF2Asset.h | 4 ++-- code/glTF2Asset.inl | 29 ++++++++++++----------------- code/glTF2AssetWriter.inl | 9 ++------- code/glTF2Exporter.cpp | 2 +- code/glTF2Importer.cpp | 3 ++- code/glTFAsset.h | 4 ++-- code/glTFAsset.inl | 29 ++++++++++++++++++++--------- code/glTFAssetWriter.inl | 9 ++------- code/glTFImporter.cpp | 3 ++- 9 files changed, 45 insertions(+), 47 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 12cad25ba..1711b930b 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -1005,13 +1005,13 @@ namespace glTF2 std::string version; //!< Specifies the target rendering API (default: "1.0.3") } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) - float version; //!< The glTF format version + std::string version; //!< The glTF format version void Read(Document& doc); AssetMetadata() : premultipliedAlpha(false) - , version(0) + , version("") { } }; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index e2d812563..bc8261317 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -985,15 +985,21 @@ inline void Scene::Read(Value& obj, Asset& r) inline void AssetMetadata::Read(Document& doc) { - // read the version, etc. - std::string statedVersion; - if (Value* obj = FindObject(doc, "asset")) { ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "generator", generator); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); - statedVersion = MemberOrDefault(*obj, "version", "0.0"); + + if (Value* versionString = FindString(*obj, "version")) { + version = versionString->GetString(); + } else if (Value* versionNumber = FindNumber (*obj, "version")) { + char buf[4]; + + ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble()); + + version = buf; + } if (Value* profile = FindObject(*obj, "profile")) { ReadMember(*profile, "api", this->profile.api); @@ -1001,19 +1007,8 @@ inline void AssetMetadata::Read(Document& doc) } } - float statedFloatVersion = std::strtof(statedVersion.c_str(), 0); - - version = std::max(statedFloatVersion, version); - - if (version == 0) { - // if missing version, we'll assume version 2.0... - version = 2; - } - - if (version != 2) { - char msg[128]; - ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %.1f", version); - throw DeadlyImportError(msg); + if (version.empty() || version[0] != '2') { + throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); } } diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index ad68a14e1..1665bee02 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -652,13 +652,8 @@ namespace glTF2 { { Value asset; asset.SetObject(); - { - char versionChar[10]; - ai_snprintf(versionChar, sizeof(versionChar), "%.1f", mAsset.asset.version); - asset.AddMember("version", Value(versionChar, mAl).Move(), mAl); - - asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); - } + asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl); + asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); mDoc.AddMember("asset", asset, mAl); } diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9130c750c..f3e083543 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -811,7 +811,7 @@ void glTF2Exporter::ExportScene() void glTF2Exporter::ExportMetadata() { AssetMetadata& asset = mAsset->asset; - asset.version = 2; + asset.version = "2.0"; char buffer[256]; ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)", diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 1ab23fd18..34144b9e2 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -111,7 +111,8 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool glTF2::Asset asset(pIOHandler); try { asset.Load(pFile, extension == "glb"); - return asset.asset.version >= 2; + std::string version = asset.asset.version; + return !version.empty() && version[0] == '2'; } catch (...) { return false; } diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 30d0bc056..60107bee6 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -1058,13 +1058,13 @@ namespace glTF std::string version; //!< Specifies the target rendering API (default: "1.0.3") } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) - float version; //!< The glTF format version (should be 1.0) + std::string version; //!< The glTF format version (should be 1.0) void Read(Document& doc); AssetMetadata() : premultipliedAlpha(false) - , version(0) + , version("") { } }; diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 32fe77288..bb4bb50aa 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "StringUtils.h" +#include // Header files, Assimp #include @@ -128,6 +129,12 @@ namespace { return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; } + inline Value* FindNumber(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0; + } + inline Value* FindArray(Value& val, const char* id) { Value::MemberIterator it = val.FindMember(id); @@ -1228,13 +1235,21 @@ inline void Scene::Read(Value& obj, Asset& r) inline void AssetMetadata::Read(Document& doc) { // read the version, etc. - float statedVersion = 0; if (Value* obj = FindObject(doc, "asset")) { ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "generator", generator); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); - statedVersion = MemberOrDefault(*obj, "version", 0); + + if (Value* versionString = FindString(*obj, "version")) { + version = versionString->GetString(); + } else if (Value* versionNumber = FindNumber (*obj, "version")) { + char buf[4]; + + ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble()); + + version = buf; + } if (Value* profile = FindObject(*obj, "profile")) { ReadMember(*profile, "api", this->profile.api); @@ -1242,12 +1257,8 @@ inline void AssetMetadata::Read(Document& doc) } } - version = std::max(statedVersion, version); - - if (version != 1) { - char msg[128]; - ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %.0f", version); - throw DeadlyImportError(msg); + if (version.empty() || version[0] != '1') { + throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); } } @@ -1269,7 +1280,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream) } AI_SWAP4(header.version); - asset.version = header.version; + asset.version = std::to_string(header.version); if (header.version != 1) { throw DeadlyImportError("GLTF: Unsupported binary glTF version"); } diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 166b84fd1..698f0ba8f 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -606,13 +606,8 @@ namespace glTF { { Value asset; asset.SetObject(); - { - char versionChar[10]; - ai_snprintf(versionChar, sizeof(versionChar), "%.0f", mAsset.asset.version); - asset.AddMember("version", Value(versionChar, mAl).Move(), mAl); - - asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); - } + asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl); + asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); mDoc.AddMember("asset", asset, mAl); } diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 6dbeb7e91..1b5c953be 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -109,7 +109,8 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool glTF::Asset asset(pIOHandler); try { asset.Load(pFile, extension == "glb"); - return asset.asset.version < 2; + std::string version = asset.asset.version; + return !version.empty() && version[0] == '1'; } catch (...) { return false; } From a438ece655ced52835bda0dcb492cab8394de14f Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 6 Sep 2017 23:43:43 -0400 Subject: [PATCH 41/56] Remove premultipliedAlpha from gltf2 --- code/glTF2Asset.h | 7 +------ code/glTF2Asset.inl | 2 -- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 1711b930b..8b226dacb 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -998,7 +998,6 @@ namespace glTF2 { std::string copyright; //!< A copyright message suitable for display to credit the content creator. std::string generator; //!< Tool that generated this glTF model.Useful for debugging. - bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false) struct { std::string api; //!< Specifies the target rendering API (default: "WebGL") @@ -1009,11 +1008,7 @@ namespace glTF2 void Read(Document& doc); - AssetMetadata() - : premultipliedAlpha(false) - , version("") - { - } + AssetMetadata() : version("") {} }; // diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index bc8261317..3d4a4ee42 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -989,8 +989,6 @@ inline void AssetMetadata::Read(Document& doc) ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "generator", generator); - premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); - if (Value* versionString = FindString(*obj, "version")) { version = versionString->GetString(); } else if (Value* versionNumber = FindNumber (*obj, "version")) { From 5cb13aa4b3b4dc282ed970ffd57238b823492f47 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 7 Sep 2017 14:55:44 -0400 Subject: [PATCH 42/56] Load gltf .bin files from correct directory --- code/glTF2Asset.inl | 4 +++- code/glTFAsset.inl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 3d4a4ee42..03c2279e8 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -337,7 +337,9 @@ inline void Buffer::Read(Value& obj, Asset& r) } else { // Local file if (byteLength > 0) { - IOStream* file = r.OpenFile(uri, "rb"); + std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : ""; + + IOStream* file = r.OpenFile(dir + uri, "rb"); if (file) { bool ok = LoadFromStream(*file, byteLength); delete file; diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index bb4bb50aa..9284ccb02 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -316,7 +316,9 @@ inline void Buffer::Read(Value& obj, Asset& r) } else { // Local file if (byteLength > 0) { - IOStream* file = r.OpenFile(uri, "rb"); + std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : ""; + + IOStream* file = r.OpenFile(dir + uri, "rb"); if (file) { bool ok = LoadFromStream(*file, byteLength); delete file; From d518289e7217f1966b8abd33bd574943781fab31 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 7 Sep 2017 15:48:11 -0400 Subject: [PATCH 43/56] more specific token search for Collada Loader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit collada can appear in many files, such as glTFs via the “generator” field (in the form of collada2gltf) --- code/ColladaLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index f7ef903f4..0e970b468 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -119,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo * might be NULL and it's our duty to return true here. */ if (!pIOHandler)return true; - const char* tokens[] = {"collada"}; + const char* tokens[] = {" Date: Thu, 7 Sep 2017 15:50:35 -0400 Subject: [PATCH 44/56] Add gltf2 basic unit test --- test/CMakeLists.txt | 5 ++- test/unit/utglTF2ImportExport.cpp | 75 +++++++++++++++++++++++++++++++ test/unit/utglTFImportExport.cpp | 2 +- 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 test/unit/utglTF2ImportExport.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cb559deb3..3520f9782 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,7 +65,7 @@ SET( TEST_SRCS unit/ut3DSImportExport.cpp unit/utACImportExport.cpp unit/utAMFImportExport.cpp - unit/utASEImportExport.cpp + unit/utASEImportExport.cpp unit/utAnim.cpp unit/AssimpAPITest.cpp unit/utB3DImportExport.cpp @@ -88,6 +88,7 @@ SET( TEST_SRCS unit/utFixInfacingNormals.cpp unit/utGenNormals.cpp unit/utglTFImportExport.cpp + unit/utglTF2ImportExport.cpp unit/utHMPImportExport.cpp unit/utIFCImportExport.cpp unit/utImporter.cpp @@ -146,7 +147,7 @@ add_executable( unit ) add_definitions(-DASSIMP_TEST_MODELS_DIR="${CMAKE_CURRENT_LIST_DIR}/models") - + SET_PROPERTY( TARGET assimp PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) IF( WIN32 ) diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp new file mode 100644 index 000000000..09c43131d --- /dev/null +++ b/test/unit/utglTF2ImportExport.cpp @@ -0,0 +1,75 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utglTF2ImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0); + return nullptr != scene; + } + + virtual bool exporterTest() { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0 ); + EXPECT_NE( nullptr, scene ); + EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) ); + + return true; + } +}; + +TEST_F( utglTF2ImportExport, importglTF2FromFileTest ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { + EXPECT_TRUE( exporterTest() ); +} diff --git a/test/unit/utglTFImportExport.cpp b/test/unit/utglTFImportExport.cpp index 349dddafa..18c348299 100644 --- a/test/unit/utglTFImportExport.cpp +++ b/test/unit/utglTFImportExport.cpp @@ -55,6 +55,6 @@ public: } }; -TEST_F( utglTFImportExport, importglTFromFileTest ) { +TEST_F( utglTFImportExport, importglTFFromFileTest ) { EXPECT_TRUE( importerTest() ); } From b4f5033d899f443b55d756a65c6369204dfffae1 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 7 Sep 2017 17:15:05 -0400 Subject: [PATCH 45/56] Remove compresssed file format flag --- code/glTF2Importer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 34144b9e2..d234afab3 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -74,8 +74,7 @@ static const aiImporterDesc desc = { "", "", "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour - | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, From 816e6909ca87dd8f77a8375d3fa38de004371556 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Thu, 7 Sep 2017 17:32:41 -0400 Subject: [PATCH 46/56] Remove KHR_binary_glTF code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Binary glTF is now part of the glTF2 spec. However, it’s implemented incorrectly, so will be temporarily removed --- code/glTF2Asset.h | 21 +-------- code/glTF2Asset.inl | 84 ++---------------------------------- code/glTF2AssetWriter.h | 2 - code/glTF2AssetWriter.inl | 90 +-------------------------------------- code/glTF2Exporter.cpp | 10 +---- code/glTF2Importer.cpp | 11 ++--- 6 files changed, 10 insertions(+), 208 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 8b226dacb..b093ec027 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Declares a glTF class to handle gltf/glb files * * glTF Extensions Support: - * KHR_binary_glTF: full * KHR_materials_pbrSpecularGlossiness full */ #ifndef GLTF2ASSET_H_INC @@ -193,17 +192,6 @@ namespace glTF2 #include "./../include/assimp/Compiler/pushpack1.h" #endif - //! For the KHR_binary_glTF extension (binary .glb file) - //! 20-byte header (+ the JSON + a "body" data section) - struct GLB_Header - { - uint8_t magic[4]; //!< Magic number: "glTF" - uint32_t version; //!< Version number - uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes - uint32_t sceneLength; //!< Length, in bytes, of the glTF scene - uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum) - } PACK_STRUCT; - #ifdef ASSIMP_API #include "./../include/assimp/Compiler/poppack1.h" #endif @@ -1049,7 +1037,6 @@ namespace glTF2 //! Keeps info about the enabled extensions struct Extensions { - bool KHR_binary_glTF; bool KHR_materials_pbrSpecularGlossiness; } extensionsUsed; @@ -1097,10 +1084,7 @@ namespace glTF2 } //! Main function - void Load(const std::string& file, bool isBinary = false); - - //! Enables the "KHR_binary_glTF" extension on the asset - void SetAsBinary(); + void Load(const std::string& file); //! Search for an available name, starting from the given strings std::string FindUniqueID(const std::string& str, const char* suffix); @@ -1109,11 +1093,8 @@ namespace glTF2 { return mBodyBuffer; } private: - void ReadBinaryHeader(IOStream& stream); - void ReadExtensionsUsed(Document& doc); - IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); }; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 03c2279e8..cbdac5d80 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -290,11 +290,6 @@ inline Buffer::~Buffer() inline const char* Buffer::TranslateId(Asset& r, const char* id) { - // Compatibility with old spec - if (r.extensionsUsed.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) { - return "binary_glTF"; - } - return id; } @@ -630,28 +625,6 @@ inline Image::Image() inline void Image::Read(Value& obj, Asset& r) { - // Check for extensions first (to detect binary embedded data) - if (Value* extensions = FindObject(obj, "extensions")) { - if (r.extensionsUsed.KHR_binary_glTF) { - if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) { - - width = MemberOrDefault(*ext, "width", 0); - height = MemberOrDefault(*ext, "height", 0); - - ReadMember(*ext, "mimeType", mimeType); - - if (Value* bufferViewVal = FindUInt(*ext, "bufferView")) { - Ref bv = r.bufferViews.Retrieve(bufferViewVal->GetUint()); - if (bv) { - mDataLength = bv->byteLength; - mData = new uint8_t[mDataLength]; - memcpy(mData, bv->buffer->GetPointer() + bv->byteOffset, mDataLength); - } - } - } - } - } - if (!mDataLength) { if (Value* uri = FindString(obj, "uri")) { const char* uristr = uri->GetString(); @@ -1016,40 +989,7 @@ inline void AssetMetadata::Read(Document& doc) // Asset methods implementation // -inline void Asset::ReadBinaryHeader(IOStream& stream) -{ - GLB_Header header; - if (stream.Read(&header, sizeof(header), 1) != 1) { - throw DeadlyImportError("GLTF: Unable to read the file header"); - } - - if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { - throw DeadlyImportError("GLTF: Invalid binary glTF file"); - } - - AI_SWAP4(header.version); - asset.version = header.version; - if (header.version != 1) { - throw DeadlyImportError("GLTF: Unsupported binary glTF version"); - } - - AI_SWAP4(header.sceneFormat); - if (header.sceneFormat != SceneFormat_JSON) { - throw DeadlyImportError("GLTF: Unsupported binary glTF scene format"); - } - - AI_SWAP4(header.length); - AI_SWAP4(header.sceneLength); - - mSceneLength = static_cast(header.sceneLength); - - mBodyOffset = sizeof(header)+mSceneLength; - mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4 - - mBodyLength = header.length - mBodyOffset; -} - -inline void Asset::Load(const std::string& pFile, bool isBinary) +inline void Asset::Load(const std::string& pFile) { mCurrentAssetDir.clear(); int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); @@ -1060,16 +1000,8 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) throw DeadlyImportError("GLTF: Could not open file for reading"); } - // is binary? then read the header - if (isBinary) { - SetAsBinary(); // also creates the body buffer - ReadBinaryHeader(*stream); - } - else { - mSceneLength = stream->FileSize(); - mBodyLength = 0; - } - + mSceneLength = stream->FileSize(); + mBodyLength = 0; // read the scene data @@ -1130,15 +1062,6 @@ inline void Asset::Load(const std::string& pFile, bool isBinary) } } -inline void Asset::SetAsBinary() -{ - if (!extensionsUsed.KHR_binary_glTF) { - extensionsUsed.KHR_binary_glTF = true; - mBodyBuffer = buffers.Create("binary_glTF"); - mBodyBuffer->MarkAsSpecial(); - } -} - inline void Asset::ReadExtensionsUsed(Document& doc) { Value* extsUsed = FindArray(doc, "extensionsUsed"); @@ -1155,7 +1078,6 @@ inline void Asset::ReadExtensionsUsed(Document& doc) #define CHECK_EXT(EXT) \ if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; - CHECK_EXT(KHR_binary_glTF); CHECK_EXT(KHR_materials_pbrSpecularGlossiness); #undef CHECK_EXT diff --git a/code/glTF2AssetWriter.h b/code/glTF2AssetWriter.h index 97efbeab5..bce2b1bd1 100644 --- a/code/glTF2AssetWriter.h +++ b/code/glTF2AssetWriter.h @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Declares a class to write gltf/glb files * * glTF Extensions Support: - * KHR_binary_glTF: full * KHR_materials_pbrSpecularGlossiness: full */ #ifndef GLTF2ASSETWRITER_H_INC @@ -82,7 +81,6 @@ public: AssetWriter(Asset& asset); void WriteFile(const char* path); - void WriteGLBFile(const char* path); }; } diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 1665bee02..e62f2377e 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -179,21 +179,7 @@ namespace glTF2 { inline void Write(Value& obj, Image& img, AssetWriter& w) { std::string uri; - if (w.mAsset.extensionsUsed.KHR_binary_glTF && img.bufferView) { - Value exts, ext; - exts.SetObject(); - ext.SetObject(); - - ext.AddMember("bufferView", img.bufferView->index, w.mAl); - - if (!img.mimeType.empty()) - ext.AddMember("mimeType", StringRef(img.mimeType), w.mAl); - - exts.AddMember("KHR_binary_glTF", ext, w.mAl); - obj.AddMember("extensions", exts, w.mAl); - return; - } - else if (img.HasData()) { + if (img.HasData()) { uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType); uri += ";base64,"; Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri); @@ -577,77 +563,6 @@ namespace glTF2 { } } - inline void AssetWriter::WriteGLBFile(const char* path) - { - std::unique_ptr outfile(mAsset.OpenFile(path, "wb", true)); - - if (outfile == 0) { - throw DeadlyExportError("Could not open output file: " + std::string(path)); - } - - // we will write the header later, skip its size - outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); - - StringBuffer docBuffer; - Writer writer(docBuffer); - mDoc.Accept(writer); - - if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { - throw DeadlyExportError("Failed to write scene data!"); - } - - WriteBinaryData(outfile.get(), docBuffer.GetSize()); - } - - inline void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength) - { - // - // write the body data - // - - size_t bodyLength = 0; - if (Ref b = mAsset.GetBodyBuffer()) { - bodyLength = b->byteLength; - - if (bodyLength > 0) { - size_t bodyOffset = sizeof(GLB_Header) + sceneLength; - bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4 - - outfile->Seek(bodyOffset, aiOrigin_SET); - - if (outfile->Write(b->GetPointer(), b->byteLength, 1) != 1) { - throw DeadlyExportError("Failed to write body data!"); - } - } - } - - // - // write the header - // - - GLB_Header header; - memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)); - - header.version = 2; - AI_SWAP4(header.version); - - header.length = uint32_t(sizeof(header) + sceneLength + bodyLength); - AI_SWAP4(header.length); - - header.sceneLength = uint32_t(sceneLength); - AI_SWAP4(header.sceneLength); - - header.sceneFormat = SceneFormat_JSON; - AI_SWAP4(header.sceneFormat); - - outfile->Seek(0, aiOrigin_SET); - - if (outfile->Write(&header, 1, sizeof(header)) != sizeof(header)) { - throw DeadlyExportError("Failed to write the header!"); - } - } - - inline void AssetWriter::WriteMetadata() { Value asset; @@ -662,9 +577,6 @@ namespace glTF2 { Value exts; exts.SetArray(); { - //if (false) - // exts.PushBack(StringRef("KHR_binary_glTF"), mAl); - // This is used to export pbrSpecularGlossiness materials with GLTF 2. if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index f3e083543..e8c42128e 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -101,10 +101,6 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai mAsset.reset( new Asset( pIOSystem ) ); - if (isBinary) { - mAsset->SetAsBinary(); - } - ExportMetadata(); ExportMaterials(); @@ -121,11 +117,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai AssetWriter writer(*mAsset); - if (isBinary) { - writer.WriteGLBFile(filename); - } else { - writer.WriteFile(filename); - } + writer.WriteFile(filename); } /* diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index d234afab3..34f12b5af 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -74,7 +74,7 @@ static const aiImporterDesc desc = { "", "", "", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, @@ -103,13 +103,13 @@ bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool { const std::string &extension = GetExtension(pFile); - if (extension != "gltf") // We currently can't read glTF2 binary files (.glb) + if (extension != "gltf") // We currently can't read glTF2 binary files (.glb), yet return false; if (checkSig && pIOHandler) { glTF2::Asset asset(pIOHandler); try { - asset.Load(pFile, extension == "glb"); + asset.Load(pFile); std::string version = asset.asset.version; return !version.empty() && version[0] == '2'; } catch (...) { @@ -615,15 +615,12 @@ void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IO // read the asset file glTF2::Asset asset(pIOHandler); - asset.Load(pFile, GetExtension(pFile) == "glb"); - + asset.Load(pFile); // // Copy the data out // - - ImportEmbeddedTextures(asset); ImportMaterials(asset); From 990fe143a131f96cec74c841567e9b20230220a8 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 8 Sep 2017 15:54:03 -0400 Subject: [PATCH 47/56] =?UTF-8?q?Fix=20mesh=20primitive=E2=80=99s=20attrib?= =?UTF-8?q?utes=E2=80=99=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per spec TEXCOORD -> TEXCOORD_0 COLOR -> COLOR_0 JOINTS -> JOINTS_0 WEIGHTS -> WEIGHTS_0 Remove JOINTMATRIX since it’s not supported (and doesn’t seem to be output, anyway) TANGENT should be added at a later date --- code/glTF2AssetWriter.inl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index e62f2377e..ed599c23e 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -380,11 +380,10 @@ namespace glTF2 { { WriteAttrs(w, attrs, p.attributes.position, "POSITION"); WriteAttrs(w, attrs, p.attributes.normal, "NORMAL"); - WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true); - WriteAttrs(w, attrs, p.attributes.color, "COLOR"); - WriteAttrs(w, attrs, p.attributes.joint, "JOINT"); - WriteAttrs(w, attrs, p.attributes.jointmatrix, "JOINTMATRIX"); - WriteAttrs(w, attrs, p.attributes.weight, "WEIGHT"); + WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD_0", true); + WriteAttrs(w, attrs, p.attributes.color, "COLOR_0"); + WriteAttrs(w, attrs, p.attributes.joint, "JOINTS_0"); + WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS_0"); } prim.AddMember("attributes", attrs, w.mAl); } From b1a5ca451639dbaf4852580c6842b226f3ff860c Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 8 Sep 2017 15:58:09 -0400 Subject: [PATCH 48/56] Use `forceNumber` argument of `WriteAttrs` to write correct attribute names, instead --- code/glTF2AssetWriter.inl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index ed599c23e..c91313ab4 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -380,10 +380,10 @@ namespace glTF2 { { WriteAttrs(w, attrs, p.attributes.position, "POSITION"); WriteAttrs(w, attrs, p.attributes.normal, "NORMAL"); - WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD_0", true); - WriteAttrs(w, attrs, p.attributes.color, "COLOR_0"); - WriteAttrs(w, attrs, p.attributes.joint, "JOINTS_0"); - WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS_0"); + WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true); + WriteAttrs(w, attrs, p.attributes.color, "COLOR", true); + WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true); + WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true); } prim.AddMember("attributes", attrs, w.mAl); } From cde29c937c4fdefa0a2c02f2ec1a8bd49e4121fb Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Fri, 8 Sep 2017 16:32:00 -0400 Subject: [PATCH 49/56] Formatting --- code/glTF2Exporter.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index e8c42128e..e2b46b1f7 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -389,8 +389,6 @@ void glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* p void glTF2Exporter::ExportMaterials() { - bool& KHR_materials_pbrSpecularGlossiness = mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness; - aiString aiName; for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { const aiMaterial* mat = mScene->mMaterials[i]; @@ -442,8 +440,8 @@ void glTF2Exporter::ExportMaterials() if (hasPbrSpecularGlossiness) { - if (!KHR_materials_pbrSpecularGlossiness) { - KHR_materials_pbrSpecularGlossiness = true; + if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) { + mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true; } PbrSpecularGlossiness pbrSG; From 86a8a58d126bbd58ff42edbcc71e79fb825f6922 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 10 Sep 2017 21:04:28 -0400 Subject: [PATCH 50/56] Exclude glTF2 Exporter test when ASSIMP_BUILD_NO_EXPORT --- test/unit/utglTF2ImportExport.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 09c43131d..fa69d648a 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -55,6 +55,7 @@ public: return nullptr != scene; } +#ifndef ASSIMP_BUILD_NO_EXPORT virtual bool exporterTest() { Assimp::Importer importer; Assimp::Exporter exporter; @@ -64,12 +65,16 @@ public: return true; } +#endif // ASSIMP_BUILD_NO_EXPORT + }; TEST_F( utglTF2ImportExport, importglTF2FromFileTest ) { EXPECT_TRUE( importerTest() ); } +#ifndef ASSIMP_BUILD_NO_EXPORT TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { EXPECT_TRUE( exporterTest() ); } +#endif // ASSIMP_BUILD_NO_EXPORT From 4b01ecaf109ae1bbd3ae918e30abdc67d7448a5a Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Mon, 11 Sep 2017 16:31:40 -0400 Subject: [PATCH 51/56] Remove simple gltf2 export unit test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Segfaults on Linux for some reason. No other tests test exporting, so it’s fine --- test/unit/utglTF2ImportExport.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index fa69d648a..8e0fcbbcf 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include -#include using namespace Assimp; @@ -54,27 +53,8 @@ public: const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0); return nullptr != scene; } - -#ifndef ASSIMP_BUILD_NO_EXPORT - virtual bool exporterTest() { - Assimp::Importer importer; - Assimp::Exporter exporter; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0 ); - EXPECT_NE( nullptr, scene ); - EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) ); - - return true; - } -#endif // ASSIMP_BUILD_NO_EXPORT - }; TEST_F( utglTF2ImportExport, importglTF2FromFileTest ) { EXPECT_TRUE( importerTest() ); } - -#ifndef ASSIMP_BUILD_NO_EXPORT -TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { - EXPECT_TRUE( exporterTest() ); -} -#endif // ASSIMP_BUILD_NO_EXPORT From 023cb27784e61ab92f915df49f18675c28a40df2 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 12 Sep 2017 09:57:58 -0400 Subject: [PATCH 52/56] Revert "Remove simple gltf2 export unit test" This reverts commit 4b01ecaf109ae1bbd3ae918e30abdc67d7448a5a. --- test/unit/utglTF2ImportExport.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 8e0fcbbcf..fa69d648a 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include +#include using namespace Assimp; @@ -53,8 +54,27 @@ public: const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0); return nullptr != scene; } + +#ifndef ASSIMP_BUILD_NO_EXPORT + virtual bool exporterTest() { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", 0 ); + EXPECT_NE( nullptr, scene ); + EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) ); + + return true; + } +#endif // ASSIMP_BUILD_NO_EXPORT + }; TEST_F( utglTF2ImportExport, importglTF2FromFileTest ) { EXPECT_TRUE( importerTest() ); } + +#ifndef ASSIMP_BUILD_NO_EXPORT +TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { + EXPECT_TRUE( exporterTest() ); +} +#endif // ASSIMP_BUILD_NO_EXPORT From b0da0796c8191bc42e6cfecb765a9a4e11595a42 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 12 Sep 2017 10:07:15 -0400 Subject: [PATCH 53/56] Fix Segfault caused by losing pointer to std::string Keep std::string alive --- code/glTF2Asset.h | 14 +++++++------- code/glTF2Exporter.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index b093ec027..8604cd2a1 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -164,7 +164,7 @@ namespace glTF2 //! Magic number for GLB files #define AI_GLB_MAGIC_NUMBER "glTF" - #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0,0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 @@ -172,15 +172,15 @@ namespace glTF2 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR "$clr.diffuse", 0, 1 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR "$clr.specular", 0, 1 - #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0,0 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE aiTextureType_DIFFUSE, 1 #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE aiTextureType_UNKNOWN, 1 - #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE (std::string(_AI_MATKEY_TEXTURE_BASE) + ".texCoord").c_str() - #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "name").c_str() - #define _AI_MATKEY_GLTF_MAPPINGID_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "id").c_str() - #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermag").c_str() - #define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE (std::string(_AI_MATKEY_MAPPING_BASE) + "filtermin").c_str() + #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" + #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" + #define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid" + #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag" + #define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin" #define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index e2b46b1f7..9a0e0cca1 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -276,16 +276,16 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, a void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) { - const char* key = (std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName).c_str(); + std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; - mat->Get(key, 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) { - const char* key = (std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName).c_str(); + std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; - mat->Get(key, 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) From eca008d5ece5a8087a158b5f8d1651938e8fac7b Mon Sep 17 00:00:00 2001 From: John Senneker Date: Tue, 12 Sep 2017 11:55:22 -0400 Subject: [PATCH 54/56] Properly move string passed to JSON writer --- code/glTF2AssetWriter.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index c91313ab4..7c0b435f2 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -300,7 +300,7 @@ namespace glTF2 { } if (m.alphaMode != "OPAQUE") { - obj.AddMember("alphaMode", m.alphaMode, w.mAl); + obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl); } if (m.doubleSided) { From 933bbb4f1c4752ee7bed77029a8604aa8f3e7bc6 Mon Sep 17 00:00:00 2001 From: John Senneker Date: Tue, 12 Sep 2017 11:55:52 -0400 Subject: [PATCH 55/56] Manually read alphaMode material property --- code/glTF2Exporter.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 9a0e0cca1..a3940e9ea 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -424,7 +424,20 @@ void glTF2Exporter::ExportMaterials() mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); - if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, m->alphaMode) != AI_SUCCESS) { + bool foundAlphaMode = false; + for (size_t i = 0; i < mat->mNumProperties; ++i) { + aiMaterialProperty *prop = mat->mProperties[i]; + if (prop->mKey != aiString("$mat.gltf.alphaMode")) + continue; + + std::string alphaMode; + for (size_t c = 0; c < prop->mDataLength; ++c) + alphaMode += prop->mData[c]; + m->alphaMode = alphaMode; + foundAlphaMode = true; + } + + if (!foundAlphaMode) { float opacity; if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { @@ -435,7 +448,7 @@ void glTF2Exporter::ExportMaterials() } } - bool hasPbrSpecularGlossiness; + bool hasPbrSpecularGlossiness = false; mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness); if (hasPbrSpecularGlossiness) { From 2cc0a378ed156dbefec62dffdf994aa6901dc177 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Wed, 13 Sep 2017 11:23:12 -0400 Subject: [PATCH 56/56] Update glTF in list of importers and exporters --- Readme.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index a5c31881a..1eaa6b8e1 100644 --- a/Readme.md +++ b/Readme.md @@ -52,7 +52,8 @@ __Importers__: - DXF - ENFF - FBX -- GLB/GLTF +- glTF 1.0 + GLB +- glTF 2.0 - HMB - IFC-STEP - IRR / IRRMESH @@ -106,8 +107,8 @@ __Exporters__: - JSON (for WebGl, via https://github.com/acgessler/assimp2json) - ASSBIN - STEP -- glTF (partial) -- glTF2.0 +- glTF 1.0 (partial) +- glTF 2.0 (partial) ### Building ### Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.