From 5147acfe65978fd9d5400c4d39f521c85f9a660c Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 17 Sep 2017 15:11:01 -0400 Subject: [PATCH 1/6] Revert "store node mesh vs. meshes" This reverts commit a0d97505e5a53a9aa3a734d6bd3ad790234e6e09. --- code/glTF2Asset.h | 2 +- code/glTF2Asset.inl | 9 ++++++++- code/glTF2AssetWriter.inl | 4 +--- code/glTF2Exporter.cpp | 19 ++++++++++--------- code/glTF2Importer.cpp | 28 +++++++++++++--------------- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h index 8604cd2a1..e2b61c646 100644 --- a/code/glTF2Asset.h +++ b/code/glTF2Asset.h @@ -781,7 +781,7 @@ namespace glTF2 struct Node : public Object { std::vector< Ref > children; - Ref mesh; + std::vector< Ref > meshes; Nullable matrix; Nullable translation; diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index cbdac5d80..0a3e2b051 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -934,9 +934,16 @@ 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->mesh = meshRef; + if (meshRef) this->meshes.push_back(meshRef); } if (Value* camera = FindUInt(obj, "camera")) { diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index 7c0b435f2..dd90ec576 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -417,9 +417,7 @@ namespace glTF2 { AddRefsVector(obj, "children", n.children, w.mAl); - if (n.mesh) { - obj.AddMember("mesh", n.mesh->index, w.mAl); - } + AddRefsVector(obj, "meshes", n.meshes, w.mAl); AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index a3940e9ea..56932dba7 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -476,15 +476,16 @@ void glTF2Exporter::ExportMaterials() */ bool FindMeshNode(Ref& nodeIn, Ref& meshNode, std::string meshID) { - - if (nodeIn->mesh && meshID.compare(nodeIn->mesh->id) == 0) { - meshNode = nodeIn; - return true; + for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) { + if (meshID.compare(nodeIn->meshes[i]->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; } } @@ -755,8 +756,8 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n) CopyValue(n->mTransformation, node->matrix.value); } - if (n->mNumMeshes > 0) { - node->mesh = mAsset->meshes.Get(n->mMeshes[0]); + for (unsigned int i = 0; i < n->mNumMeshes; ++i) { + node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); } for (unsigned int i = 0; i < n->mNumChildren; ++i) { @@ -784,8 +785,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref& parent) CopyValue(n->mTransformation, node->matrix.value); } - if (n->mNumMeshes > 0) { - node->mesh = mAsset->meshes.Get(n->mMeshes[0]); + for (unsigned int i = 0; i < n->mNumMeshes; ++i) { + node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); } for (unsigned int i = 0; i < n->mNumChildren; ++i) { diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp index 6de482981..d9dade3b2 100644 --- a/code/glTF2Importer.cpp +++ b/code/glTF2Importer.cpp @@ -517,24 +517,22 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& } } - if (node.mesh) { + 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; - int idx = node.mesh.GetIndex(); + ainode->mMeshes = new unsigned int[count]; - ai_assert(idx >= 0 && idx < meshOffsets.size()); - - unsigned int offBegin = meshOffsets[idx]; - unsigned int offEnd = meshOffsets[idx + 1]; int k = 0; - - ai_assert(offEnd >= offBegin); - - ainode->mNumMeshes = offEnd - offBegin; - ainode->mMeshes = new unsigned int[ainode->mNumMeshes]; - - for (unsigned int j = offBegin; j < offEnd; ++j, ++k) { - ai_assert(k < ainode->mNumMeshes); - ainode->mMeshes[k] = j; + 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; + } } } From 28523232cf735a28ec794a557af48163d84174c0 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Sun, 17 Sep 2017 17:00:57 -0400 Subject: [PATCH 2/6] Merge multiple meshes in a node into one mesh with many primtives; write out only one mesh per node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To do: - clean up MergeMeshes - see if there’s a way to do this earlier in the flow --- code/glTF2AssetWriter.inl | 4 +++- code/glTF2Exporter.cpp | 22 ++++++++++++++++++++++ code/glTF2Exporter.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl index dd90ec576..df28cb681 100644 --- a/code/glTF2AssetWriter.inl +++ b/code/glTF2AssetWriter.inl @@ -417,7 +417,9 @@ namespace glTF2 { AddRefsVector(obj, "children", n.children, w.mAl); - AddRefsVector(obj, "meshes", n.meshes, w.mAl); + if (!n.meshes.empty()) { + obj.AddMember("mesh", n.meshes[0]->index, w.mAl); + } AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 56932dba7..f63c8e89c 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -110,6 +110,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai } ExportMeshes(); + MergeMeshes(); ExportScene(); @@ -743,6 +744,27 @@ void glTF2Exporter::ExportMeshes() } } +void glTF2Exporter::MergeMeshes() +{ + for (unsigned int n = 0; n < mAsset->nodes.Size(); ++n) { + Ref node = mAsset->nodes.Get(n); + + unsigned int nMeshes = node->meshes.size(); + + if (nMeshes) { + Ref firstMesh = node->meshes.at(0); + + for (unsigned int m = 1; m < nMeshes; ++m) { + Ref mesh = node->meshes.at(m); + Mesh::Primitive primitive = mesh->primitives.at(0); + firstMesh->primitives.push_back(primitive); + } + + node->meshes.erase(node->meshes.begin() + 1, node->meshes.end()); + } + } +} + /* * Export the root node of the node hierarchy. * Calls ExportNode for all children. diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h index 420c2afa6..3aed35ae6 100644 --- a/code/glTF2Exporter.h +++ b/code/glTF2Exporter.h @@ -120,6 +120,7 @@ namespace Assimp void ExportMetadata(); void ExportMaterials(); void ExportMeshes(); + void MergeMeshes(); unsigned int ExportNodeHierarchy(const aiNode* n); unsigned int ExportNode(const aiNode* node, glTF2::Ref& parent); void ExportScene(); From 814e8b3f8eb2f10263378f0a840f3d3d55a98916 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Mon, 18 Sep 2017 10:20:02 -0400 Subject: [PATCH 3/6] Formatting --- code/glTF2Asset.inl | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl index 0a3e2b051..47904b38f 100644 --- a/code/glTF2Asset.inl +++ b/code/glTF2Asset.inl @@ -934,11 +934,8 @@ 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()); From 2efd2cdef88f498eb68c143902804d41e8ebcc50 Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Mon, 18 Sep 2017 10:43:05 -0400 Subject: [PATCH 4/6] tweaks to primitive merging logic; comments + formatting --- code/glTF2Exporter.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index f63c8e89c..888721c41 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -744,6 +744,7 @@ void glTF2Exporter::ExportMeshes() } } +//merges a node's multiple meshes (with one primitive each) into one mesh with multiple primitives void glTF2Exporter::MergeMeshes() { for (unsigned int n = 0; n < mAsset->nodes.Size(); ++n) { @@ -751,16 +752,34 @@ void glTF2Exporter::MergeMeshes() unsigned int nMeshes = node->meshes.size(); - if (nMeshes) { + //skip if it's 1 or less meshes per node + if (nMeshes > 1) { Ref firstMesh = node->meshes.at(0); + Mesh::Primitive firstPrimitive = firstMesh->primitives.at(0); - for (unsigned int m = 1; m < nMeshes; ++m) { + //loop backwards to allow easy removal of a mesh from a node once it's merged + for (unsigned int m = nMeshes - 1; m >= 1; --m) { Ref mesh = node->meshes.at(m); - Mesh::Primitive primitive = mesh->primitives.at(0); - firstMesh->primitives.push_back(primitive); + bool primitivesPushed = false; + + for (unsigned int p = 0; p < mesh->primitives.size(); ++p) { + Mesh::Primitive primitive = mesh->primitives.at(p); + + if (firstPrimitive.mode == primitive.mode) { + firstMesh->primitives.push_back(primitive); + primitivesPushed = true; + } + } + + if (primitivesPushed) { + //remove the merged meshes from the node + node->meshes.erase(node->meshes.begin() + m); + } } - node->meshes.erase(node->meshes.begin() + 1, node->meshes.end()); + //since we were looping backwards, reverse the order of merged primitives to their original order + std::reverse(firstMesh->primitives.begin() + 1, firstMesh->primitives.end()); + } } } From 8743d28ec54df8d303097ebd0c7741f6e882c21f Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Mon, 18 Sep 2017 12:16:30 -0400 Subject: [PATCH 5/6] SImplify mesh merging code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My assumption that primitives of different types (modes) can’t be in the same mesh was incorrect. --- code/glTF2Exporter.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 888721c41..576e8c723 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -755,31 +755,18 @@ void glTF2Exporter::MergeMeshes() //skip if it's 1 or less meshes per node if (nMeshes > 1) { Ref firstMesh = node->meshes.at(0); - Mesh::Primitive firstPrimitive = firstMesh->primitives.at(0); //loop backwards to allow easy removal of a mesh from a node once it's merged for (unsigned int m = nMeshes - 1; m >= 1; --m) { Ref mesh = node->meshes.at(m); - bool primitivesPushed = false; - for (unsigned int p = 0; p < mesh->primitives.size(); ++p) { - Mesh::Primitive primitive = mesh->primitives.at(p); + firstMesh->primitives.insert(firstMesh->primitives.end(), mesh->primitives.begin(), mesh->primitives.end()); - if (firstPrimitive.mode == primitive.mode) { - firstMesh->primitives.push_back(primitive); - primitivesPushed = true; - } - } - - if (primitivesPushed) { - //remove the merged meshes from the node - node->meshes.erase(node->meshes.begin() + m); - } + node->meshes.erase(node->meshes.begin() + m); } //since we were looping backwards, reverse the order of merged primitives to their original order std::reverse(firstMesh->primitives.begin() + 1, firstMesh->primitives.end()); - } } } From 798542d7bde204b8bf896d260885be76065d40aa Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Mon, 18 Sep 2017 14:48:07 -0400 Subject: [PATCH 6/6] Formatting --- code/glTF2Exporter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp index 576e8c723..fb94e1c95 100644 --- a/code/glTF2Exporter.cpp +++ b/code/glTF2Exporter.cpp @@ -479,14 +479,14 @@ 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; + 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; } }