diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 1699722215..ec58f15a95 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -751,7 +751,7 @@ void GLTFSerializer::getSkinInverseBindMatrices(std::vector>& } } -void GLTFSerializer::getNodeQueueByDepthFirstChildren(std::vector& children, int stride, std::vector& result) { +void GLTFSerializer::getNodeQueueByDepthFirstChildren(std::vector& children, int stride, bool order, std::vector& result) { int startingIndex = 0; int finalIndex = (int)children.size(); if (stride == -1) { @@ -763,10 +763,12 @@ void GLTFSerializer::getNodeQueueByDepthFirstChildren(std::vector& children result.push_back(c); std::vector nested = _file.nodes[c].children.toStdVector(); if (nested.size() != 0) { - std::sort(nested.begin(), nested.end()); + if (order) { + std::sort(nested.begin(), nested.end()); + } for (int r : nested) { if (result.end() == std::find(result.begin(), result.end(), r)) { - getNodeQueueByDepthFirstChildren(nested, stride, result); + getNodeQueueByDepthFirstChildren(nested, stride, order, result); } } } @@ -776,13 +778,18 @@ void GLTFSerializer::getNodeQueueByDepthFirstChildren(std::vector& children bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { int numNodes = _file.nodes.size(); + bool skinnedModel = !_file.skins.isEmpty(); //Build dependencies QVector> nodeDependencies(numNodes); int nodecount = 0; + bool parentOutOfOrder = false; foreach(auto &node, _file.nodes) { //nodes_transforms.push_back(getModelTransform(node)); - foreach(int child, node.children) nodeDependencies[child].push_back(nodecount); + foreach(int child, node.children) { + nodeDependencies[child].push_back(nodecount); + parentOutOfOrder |= nodecount < child; + } nodecount++; } @@ -806,20 +813,27 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { // initialize order in which nodes will be parsed + bool sortNodes = (!parentOutOfOrder && skinnedModel) || !skinnedModel; std::vector nodeQueue; nodeQueue.reserve(numNodes); int rootNode = 0; int finalNode = numNodes; - if (!_file.scenes[_file.scene].nodes.contains(0)) { - rootNode = numNodes - 1; - finalNode = -1; + for (int sceneNode : _file.scenes[_file.scene].nodes) { + if (!_file.nodes[sceneNode].defined["camera"] && sceneNode != 0) { + rootNode = numNodes - 1; + finalNode = -1; + break; + } } bool rootAtStartOfList = rootNode < finalNode; int nodeListStride = 1; if (!rootAtStartOfList) { nodeListStride = -1; } QVector initialSceneNodes = _file.scenes[_file.scene].nodes; - std::sort(initialSceneNodes.begin(), initialSceneNodes.end()); + if (sortNodes) { + std::sort(initialSceneNodes.begin(), initialSceneNodes.end()); + } + int sceneRootNode = 0; int sceneFinalNode = initialSceneNodes.size(); if (!rootAtStartOfList) { @@ -830,10 +844,13 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { int i = initialSceneNodes[index]; nodeQueue.push_back(i); std::vector children = _file.nodes[i].children.toStdVector(); - std::sort(children.begin(), children.end()); - getNodeQueueByDepthFirstChildren(children, nodeListStride, nodeQueue); + if (sortNodes) { + std::sort(children.begin(), children.end()); + } + getNodeQueueByDepthFirstChildren(children, nodeListStride, sortNodes, nodeQueue); } + // Build joints HFMJoint joint; joint.distanceToParent = 0; diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index d9c477bd99..dd3649478e 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -713,7 +713,7 @@ private: glm::mat4 getModelTransform(const GLTFNode& node); void getSkinInverseBindMatrices(std::vector>& inverseBindMatrixValues); - void getNodeQueueByDepthFirstChildren(std::vector& children, int stride, std::vector& result); + void getNodeQueueByDepthFirstChildren(std::vector& children, int stride, bool order, std::vector& result); bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url); bool parseGLTF(const hifi::ByteArray& data);