Merge pull request #1446 from Matter-and-Form/feature/gltf2-primitives

glTF2 primitives fixes
pull/1461/head
Kim Kulling 2017-09-19 15:39:11 +02:00 committed by GitHub
commit adec1b2175
6 changed files with 59 additions and 27 deletions

View File

@ -781,7 +781,7 @@ namespace glTF2
struct Node : public Object
{
std::vector< Ref<Node> > children;
Ref<Mesh> mesh;
std::vector< Ref<Mesh> > meshes;
Nullable<mat4> matrix;
Nullable<vec3> translation;

View File

@ -934,9 +934,13 @@ inline void Node::Read(Value& obj, Asset& r)
}
if (Value* mesh = FindUInt(obj, "mesh")) {
unsigned numMeshes = 1;
this->meshes.reserve(numMeshes);
Ref<Mesh> meshRef = r.meshes.Retrieve((*mesh).GetUint());
if (meshRef) this->mesh = meshRef;
if (meshRef) this->meshes.push_back(meshRef);
}
if (Value* camera = FindUInt(obj, "camera")) {

View File

@ -417,8 +417,8 @@ namespace glTF2 {
AddRefsVector(obj, "children", n.children, w.mAl);
if (n.mesh) {
obj.AddMember("mesh", n.mesh->index, w.mAl);
if (!n.meshes.empty()) {
obj.AddMember("mesh", n.meshes[0]->index, w.mAl);
}
AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);

View File

@ -110,6 +110,7 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
}
ExportMeshes();
MergeMeshes();
ExportScene();
@ -476,10 +477,11 @@ void glTF2Exporter::ExportMaterials()
*/
bool FindMeshNode(Ref<Node>& nodeIn, Ref<Node>& 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) {
@ -742,6 +744,33 @@ 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) {
Ref<Node> node = mAsset->nodes.Get(n);
unsigned int nMeshes = node->meshes.size();
//skip if it's 1 or less meshes per node
if (nMeshes > 1) {
Ref<Mesh> firstMesh = node->meshes.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> mesh = node->meshes.at(m);
firstMesh->primitives.insert(firstMesh->primitives.end(), mesh->primitives.begin(), mesh->primitives.end());
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());
}
}
}
/*
* Export the root node of the node hierarchy.
* Calls ExportNode for all children.
@ -755,8 +784,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 +813,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref<Node>& 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) {

View File

@ -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<glTF2::Node>& parent);
void ExportScene();

View File

@ -517,24 +517,22 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
}
}
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;
}
}
}