From 5480c9f5ca0f85349d7a2631209df143034298ed Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Thu, 28 Mar 2019 15:27:49 -0700 Subject: [PATCH 1/9] skinning, skeleton for models, avatar --- libraries/fbx/src/GLTFSerializer.cpp | 270 +++++++++++++++++++++++---- libraries/fbx/src/GLTFSerializer.h | 2 + 2 files changed, 232 insertions(+), 40 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index b8d4e53b65..1b6f5767f4 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -711,19 +711,19 @@ glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) { node.matrix[12], node.matrix[13], node.matrix[14], node.matrix[15]); } else { - if (node.defined["rotation"] && node.rotation.size() == 4) { - //quat(x,y,z,w) to quat(w,x,y,z) - glm::quat rotquat = glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2]); - tmat = glm::mat4_cast(rotquat) * tmat; - } - if (node.defined["scale"] && node.scale.size() == 3) { glm::vec3 scale = glm::vec3(node.scale[0], node.scale[1], node.scale[2]); glm::mat4 s = glm::mat4(1.0); s = glm::scale(s, scale); tmat = s * tmat; } - + + if (node.defined["rotation"] && node.rotation.size() == 4) { + //quat(x,y,z,w) to quat(w,x,y,z) + glm::quat rotquat = glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2]); + tmat = glm::mat4_cast(rotquat) * tmat; + } + if (node.defined["translation"] && node.translation.size() == 3) { glm::vec3 trans = glm::vec3(node.translation[0], node.translation[1], node.translation[2]); glm::mat4 t = glm::mat4(1.0); @@ -734,15 +734,58 @@ glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) { return tmat; } +std::vector<QVector<float>> GLTFSerializer::getSkinInverseBindMatrices() { + std::vector<QVector<float>> inverseBindMatrixValues; + for (auto &skin : _file.skins) { + GLTFAccessor& indicesAccessor = _file.accessors[skin.inverseBindMatrices]; + GLTFBufferView& indicesBufferview = _file.bufferviews[indicesAccessor.bufferView]; + GLTFBuffer& indicesBuffer = _file.buffers[indicesBufferview.buffer]; + int accBoffset = indicesAccessor.defined["byteOffset"] ? indicesAccessor.byteOffset : 0; + QVector<float> matrices; + addArrayOfType(indicesBuffer.blob, + indicesBufferview.byteOffset + accBoffset, + indicesAccessor.count, + matrices, + indicesAccessor.type, + indicesAccessor.componentType); + inverseBindMatrixValues.push_back(matrices); + } + return inverseBindMatrixValues; +} + +QVector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool order) { + QVector<int> result; + result.append(n); + int begin = 0; + int finish = children.size(); + if (order) { + begin = children.size() - 1; + finish = -1; + } + int index = begin; + while (index != finish) { + int c = children[index]; + std::vector<int> nested = _file.nodes[c].children.toStdVector(); + if (nested.size() != 0) { + std::sort(nested.begin(), nested.end()); + result.append(nodeDFS(c, nested, order)); + } else { + result.append(c); + } + begin < finish ? index++ : index--; + } + return result; +} + + bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { + int nodesSize = _file.nodes.size(); //Build dependencies - QVector<QVector<int>> nodeDependencies(_file.nodes.size()); + QVector<QVector<int>> nodeDependencies(nodesSize); int nodecount = 0; - bool hasChildren = false; foreach(auto &node, _file.nodes) { //nodes_transforms.push_back(getModelTransform(node)); - hasChildren |= !node.children.isEmpty(); foreach(int child, node.children) nodeDependencies[child].push_back(nodecount); nodecount++; } @@ -764,26 +807,99 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { nodecount++; } - - HFMJoint joint; - joint.isSkeletonJoint = true; - joint.bindTransformFoundInCluster = false; - joint.distanceToParent = 0; - joint.parentIndex = -1; - hfmModel.joints.resize(_file.nodes.size()); - hfmModel.jointIndices["x"] = _file.nodes.size(); - int jointInd = 0; - for (auto& node : _file.nodes) { - int size = node.transforms.size(); - if (hasChildren) { size--; } - joint.preTransform = glm::mat4(1); - for (int i = 0; i < size; i++) { - joint.preTransform = node.transforms[i] * joint.preTransform; - } - joint.name = node.name; - hfmModel.joints[jointInd] = joint; - jointInd++; + + + // initialize order in which nodes will be parsed + QVector<int> nodeQueue; + int start = 0; + int end = nodesSize; + if (!_file.scenes[_file.scene].nodes.contains(0)) { + end = -1; + start = nodesSize - 1; } + QVector<int> init = _file.scenes[_file.scene].nodes; + std::sort(init.begin(), init.end()); + int begin = 0; + int finish = init.size(); + if (start > end) { + begin = init.size() - 1; + finish = -1; + } + int index = begin; + while (index != finish) { + int i = init[index]; + std::vector<int> children = _file.nodes[i].children.toStdVector(); + std::sort(children.begin(), children.end()); + nodeQueue.append(nodeDFS(i, children, start > end)); + begin < finish ? index++ : index--; + } + + + // Build joints + HFMJoint joint; + joint.distanceToParent = 0; + hfmModel.jointIndices["x"] = nodesSize; + hfmModel.hasSkeletonJoints = false; + + for (int nodeIndex : nodeQueue) { + auto& node = _file.nodes[nodeIndex]; + + joint.parentIndex = -1; + if (!_file.scenes[_file.scene].nodes.contains(nodeIndex)) { + joint.parentIndex = nodeQueue.indexOf(nodeDependencies[nodeIndex][0]); + } + joint.transform = node.transforms.first(); + joint.postTransform = glm::mat4(); + glm:vec3 scale = extractScale(joint.transform); + joint.postTransform[0][0] = scale.x; + joint.postTransform[1][1] = scale.y; + joint.postTransform[2][2] = scale.z; + joint.rotation = glmExtractRotation(joint.transform); + joint.translation = extractTranslation(joint.transform); + + joint.name = node.name; + hfmModel.joints.push_back(joint); + } + + + // Build skeleton + int matrixIndex = 0; + std::vector<QVector<float>> inverseBindValues = getSkinInverseBindMatrices(); + std::vector<glm::mat4> jointInverseBindTransforms; + jointInverseBindTransforms.resize(nodesSize); + + int jointIndex = end; + while (jointIndex != start) { + start < end ? jointIndex-- : jointIndex++; + int jOffset = nodeQueue[jointIndex]; + auto joint = hfmModel.joints[jointIndex]; + + joint.isSkeletonJoint = false; + if (!_file.skins.isEmpty()) { + hfmModel.hasSkeletonJoints = true; + for (int s = 0; s < _file.skins.size(); s++) { + auto skin = _file.skins[s]; + joint.isSkeletonJoint = skin.joints.contains(jOffset); + + if (joint.isSkeletonJoint) { + QVector<float> value = inverseBindValues[s]; + int matrixCount = 16 * skin.joints.indexOf(jOffset); + jointInverseBindTransforms[jointIndex] = + glm::mat4(value[matrixCount], value[matrixCount + 1], value[matrixCount + 2], value[matrixCount + 3], + value[matrixCount + 4], value[matrixCount + 5], value[matrixCount + 6], value[matrixCount + 7], + value[matrixCount + 8], value[matrixCount + 9], value[matrixCount + 10], value[matrixCount + 11], + value[matrixCount + 12], value[matrixCount + 13], value[matrixCount + 14], value[matrixCount + 15]); + matrixIndex++; + } else { + jointInverseBindTransforms[jointIndex] = glm::mat4(); + } + } + glm::vec3 bindTranslation = extractTranslation(hfmModel.offset * glm::inverse(jointInverseBindTransforms[jointIndex])); + hfmModel.bindExtents.addPoint(bindTranslation); + } + hfmModel.joints[jointIndex] = joint; + } + //Build materials QVector<QString> materialIDs; @@ -803,23 +919,34 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } - - nodecount = 0; // Build meshes - foreach(auto &node, _file.nodes) { + nodecount = 0; + int nodeIndex = start; + while (nodeIndex != end) { + auto& node = _file.nodes[nodeIndex]; if (node.defined["mesh"]) { qCDebug(modelformat) << "node_transforms" << node.transforms; foreach(auto &primitive, _file.meshes[node.mesh].primitives) { hfmModel.meshes.append(HFMMesh()); HFMMesh& mesh = hfmModel.meshes[hfmModel.meshes.size() - 1]; - HFMCluster cluster; - cluster.jointIndex = nodecount; - cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - mesh.clusters.append(cluster); + if (!hfmModel.hasSkeletonJoints) { + HFMCluster cluster; + cluster.jointIndex = nodecount; + cluster.inverseBindMatrix = glm::mat4(); + cluster.inverseBindTransform = Transform(cluster.inverseBindMatrix); + mesh.clusters.append(cluster); + } else { + int j = start; + while (j != end) { + HFMCluster cluster; + cluster.jointIndex = j; + cluster.inverseBindMatrix = jointInverseBindTransforms[j]; + cluster.inverseBindTransform = Transform(cluster.inverseBindMatrix); + mesh.clusters.append(cluster); + start < end ? j++ : j--; + } + } HFMMeshPart part = HFMMeshPart(); @@ -848,6 +975,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } QList<QString> keys = primitive.attributes.values.keys(); + QVector<uint16_t> clusterJoints; + QVector<float> clusterWeights; foreach(auto &key, keys) { int accessorIdx = primitive.attributes.values[key]; @@ -949,8 +1078,68 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { for (int n = 0; n < texcoords.size(); n = n + 2) { mesh.texCoords1.push_back(glm::vec2(texcoords[n], texcoords[n + 1])); } + } else if (key == "JOINTS_0") { + QVector<uint16_t> joints; + success = addArrayOfType(buffer.blob, + bufferview.byteOffset + accBoffset, + accessor.count, + joints, + accessor.type, + accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF JOINTS_0 data for model " << _url; + continue; + } + for (int n = 0; n < joints.size(); n++) { + clusterJoints.push_back(joints[n]); + } + } else if (key == "WEIGHTS_0") { + QVector<float> weights; + success = addArrayOfType(buffer.blob, + bufferview.byteOffset + accBoffset, + accessor.count, + weights, + accessor.type, + accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF WEIGHTS_0 data for model " << _url; + continue; + } + for (int n = 0; n < weights.size(); n++) { + clusterWeights.push_back(weights[n]); + } + } + } + + // adapted from FBXSerializer.cpp + if (hfmModel.hasSkeletonJoints) { + int numClusterIndices = clusterJoints.size(); + const int WEIGHTS_PER_VERTEX = 4; + const float ALMOST_HALF = 0.499f; + int numVertices = mesh.vertices.size(); + mesh.clusterIndices.fill(0, numClusterIndices); + mesh.clusterWeights.fill(0, numClusterIndices); + + for (int c = 0; c < clusterJoints.size(); c++) { + mesh.clusterIndices[c] = _file.skins[node.skin].joints[clusterJoints[c]]; } + // normalize and compress to 16-bits + for (int i = 0; i < numVertices; ++i) { + int j = i * WEIGHTS_PER_VERTEX; + + float totalWeight = 0.0f; + for (int k = j; k < j + WEIGHTS_PER_VERTEX; ++k) { + totalWeight += clusterWeights[k]; + } + const float ALMOST_HALF = 0.499f; + if (totalWeight > 0.0f) { + float weightScalingFactor = (float)(UINT16_MAX) / totalWeight; + for (int k = j; k < j + WEIGHTS_PER_VERTEX; ++k) { + mesh.clusterWeights[k] = (uint16_t)(weightScalingFactor * clusterWeights[k] + ALMOST_HALF); + } + } + } } if (primitive.defined["material"]) { @@ -959,7 +1148,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { mesh.parts.push_back(part); // populate the texture coordinates if they don't exist - if (mesh.texCoords.size() == 0) { + if (mesh.texCoords.size() == 0 && !hfmModel.hasSkeletonJoints) { for (int i = 0; i < part.triangleIndices.size(); i++) mesh.texCoords.push_back(glm::vec2(0.0, 1.0)); } mesh.meshExtents.reset(); @@ -973,6 +1162,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } nodecount++; + start < end ? nodeIndex++ : nodeIndex--; } diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index 05dc526f79..331f5937ed 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -712,6 +712,8 @@ private: hifi::ByteArray _glbBinary; glm::mat4 getModelTransform(const GLTFNode& node); + std::vector<QVector<float>> getSkinInverseBindMatrices(); + QVector<int> nodeDFS(int n, std::vector<int>& children, bool order); bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url); bool parseGLTF(const hifi::ByteArray& data); From b283bb303d83fb9bf460216ffc99aedfa46ee1ee Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Thu, 28 Mar 2019 17:55:51 -0700 Subject: [PATCH 2/9] jenkins warning fixes --- libraries/fbx/src/GLTFSerializer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 1b6f5767f4..cf8d40cfc1 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -757,9 +757,9 @@ QVector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool ord QVector<int> result; result.append(n); int begin = 0; - int finish = children.size(); + int finish = (int)children.size(); if (order) { - begin = children.size() - 1; + begin = (int)children.size() - 1; finish = -1; } int index = begin; @@ -850,7 +850,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } joint.transform = node.transforms.first(); joint.postTransform = glm::mat4(); - glm:vec3 scale = extractScale(joint.transform); + glm::vec3 scale = extractScale(joint.transform); joint.postTransform[0][0] = scale.x; joint.postTransform[1][1] = scale.y; joint.postTransform[2][2] = scale.z; @@ -1132,7 +1132,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { for (int k = j; k < j + WEIGHTS_PER_VERTEX; ++k) { totalWeight += clusterWeights[k]; } - const float ALMOST_HALF = 0.499f; if (totalWeight > 0.0f) { float weightScalingFactor = (float)(UINT16_MAX) / totalWeight; for (int k = j; k < j + WEIGHTS_PER_VERTEX; ++k) { From 269b910d24a8423ec2e73048bf40829c0115bc31 Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Fri, 29 Mar 2019 18:25:17 -0700 Subject: [PATCH 3/9] update variables, loops --- libraries/fbx/src/GLTFSerializer.cpp | 105 ++++++++++++++------------- libraries/fbx/src/GLTFSerializer.h | 4 +- 2 files changed, 56 insertions(+), 53 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index cf8d40cfc1..d29c09992f 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -734,8 +734,8 @@ glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) { return tmat; } -std::vector<QVector<float>> GLTFSerializer::getSkinInverseBindMatrices() { - std::vector<QVector<float>> inverseBindMatrixValues; +std::vector<std::vector<float>> GLTFSerializer::getSkinInverseBindMatrices() { + std::vector<std::vector<float>> inverseBindMatrixValues; for (auto &skin : _file.skins) { GLTFAccessor& indicesAccessor = _file.accessors[skin.inverseBindMatrices]; GLTFBufferView& indicesBufferview = _file.bufferviews[indicesAccessor.bufferView]; @@ -748,14 +748,14 @@ std::vector<QVector<float>> GLTFSerializer::getSkinInverseBindMatrices() { matrices, indicesAccessor.type, indicesAccessor.componentType); - inverseBindMatrixValues.push_back(matrices); + inverseBindMatrixValues.push_back(matrices.toStdVector()); } return inverseBindMatrixValues; } -QVector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool order) { - QVector<int> result; - result.append(n); +std::vector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool order) { + std::vector<int> result; + result.push_back(n); int begin = 0; int finish = (int)children.size(); if (order) { @@ -768,9 +768,11 @@ QVector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool ord std::vector<int> nested = _file.nodes[c].children.toStdVector(); if (nested.size() != 0) { std::sort(nested.begin(), nested.end()); - result.append(nodeDFS(c, nested, order)); + for (int n : nodeDFS(c, nested, order)) { + result.push_back(n); + } } else { - result.append(c); + result.push_back(c); } begin < finish ? index++ : index--; } @@ -779,10 +781,10 @@ QVector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool ord bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { - int nodesSize = _file.nodes.size(); + int numNodes = _file.nodes.size(); //Build dependencies - QVector<QVector<int>> nodeDependencies(nodesSize); + QVector<QVector<int>> nodeDependencies(numNodes); int nodecount = 0; foreach(auto &node, _file.nodes) { //nodes_transforms.push_back(getModelTransform(node)); @@ -810,35 +812,40 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { // initialize order in which nodes will be parsed - QVector<int> nodeQueue; - int start = 0; - int end = nodesSize; + QVector<int> nodeQueue; + nodeQueue.reserve(numNodes); + int rootNode = 0; + int finalNode = numNodes; if (!_file.scenes[_file.scene].nodes.contains(0)) { - end = -1; - start = nodesSize - 1; + rootNode = numNodes - 1; + finalNode = -1; } - QVector<int> init = _file.scenes[_file.scene].nodes; - std::sort(init.begin(), init.end()); - int begin = 0; - int finish = init.size(); - if (start > end) { - begin = init.size() - 1; - finish = -1; + bool rootAtStartOfList = rootNode < finalNode; + int nodeListStride = 1; + if (!rootAtStartOfList) { nodeListStride = -1; } + + QVector<int> initialSceneNodes = _file.scenes[_file.scene].nodes; + std::sort(initialSceneNodes.begin(), initialSceneNodes.end()); + int sceneRootNode = 0; + int sceneFinalNode = initialSceneNodes.size(); + if (!rootAtStartOfList) { + sceneRootNode = initialSceneNodes.size() - 1; + sceneFinalNode = -1; } - int index = begin; - while (index != finish) { - int i = init[index]; + for (int index = sceneRootNode; index != sceneFinalNode; index += nodeListStride) { + int i = initialSceneNodes[index]; std::vector<int> children = _file.nodes[i].children.toStdVector(); std::sort(children.begin(), children.end()); - nodeQueue.append(nodeDFS(i, children, start > end)); - begin < finish ? index++ : index--; + for (int n : nodeDFS(i, children, !rootAtStartOfList)) { + nodeQueue.append(n); + } } // Build joints HFMJoint joint; joint.distanceToParent = 0; - hfmModel.jointIndices["x"] = nodesSize; + hfmModel.jointIndices["x"] = numNodes; hfmModel.hasSkeletonJoints = false; for (int nodeIndex : nodeQueue) { @@ -858,46 +865,46 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { joint.translation = extractTranslation(joint.transform); joint.name = node.name; + joint.isSkeletonJoint = false; hfmModel.joints.push_back(joint); } // Build skeleton - int matrixIndex = 0; - std::vector<QVector<float>> inverseBindValues = getSkinInverseBindMatrices(); std::vector<glm::mat4> jointInverseBindTransforms; - jointInverseBindTransforms.resize(nodesSize); + if (!_file.skins.isEmpty()) { + int matrixIndex = 0; + std::vector<std::vector<float>> inverseBindValues = getSkinInverseBindMatrices(); + jointInverseBindTransforms.resize(numNodes); - int jointIndex = end; - while (jointIndex != start) { - start < end ? jointIndex-- : jointIndex++; - int jOffset = nodeQueue[jointIndex]; - auto joint = hfmModel.joints[jointIndex]; + int jointIndex = finalNode; + while (jointIndex != rootNode) { + rootAtStartOfList ? jointIndex-- : jointIndex++; + int jOffset = nodeQueue[jointIndex]; + auto joint = hfmModel.joints[jointIndex]; - joint.isSkeletonJoint = false; - if (!_file.skins.isEmpty()) { hfmModel.hasSkeletonJoints = true; for (int s = 0; s < _file.skins.size(); s++) { auto skin = _file.skins[s]; joint.isSkeletonJoint = skin.joints.contains(jOffset); if (joint.isSkeletonJoint) { - QVector<float> value = inverseBindValues[s]; + std::vector<float> value = inverseBindValues[s]; int matrixCount = 16 * skin.joints.indexOf(jOffset); jointInverseBindTransforms[jointIndex] = - glm::mat4(value[matrixCount], value[matrixCount + 1], value[matrixCount + 2], value[matrixCount + 3], + glm::mat4(value[matrixCount], value[matrixCount + 1], value[matrixCount + 2], value[matrixCount + 3], value[matrixCount + 4], value[matrixCount + 5], value[matrixCount + 6], value[matrixCount + 7], - value[matrixCount + 8], value[matrixCount + 9], value[matrixCount + 10], value[matrixCount + 11], + value[matrixCount + 8], value[matrixCount + 9], value[matrixCount + 10], value[matrixCount + 11], value[matrixCount + 12], value[matrixCount + 13], value[matrixCount + 14], value[matrixCount + 15]); matrixIndex++; } else { jointInverseBindTransforms[jointIndex] = glm::mat4(); } + glm::vec3 bindTranslation = extractTranslation(hfmModel.offset * glm::inverse(jointInverseBindTransforms[jointIndex])); + hfmModel.bindExtents.addPoint(bindTranslation); } - glm::vec3 bindTranslation = extractTranslation(hfmModel.offset * glm::inverse(jointInverseBindTransforms[jointIndex])); - hfmModel.bindExtents.addPoint(bindTranslation); + hfmModel.joints[jointIndex] = joint; } - hfmModel.joints[jointIndex] = joint; } @@ -921,8 +928,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { // Build meshes nodecount = 0; - int nodeIndex = start; - while (nodeIndex != end) { + for (int nodeIndex = rootNode; nodeIndex != finalNode; nodeIndex += nodeListStride) { auto& node = _file.nodes[nodeIndex]; if (node.defined["mesh"]) { @@ -937,14 +943,12 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { cluster.inverseBindTransform = Transform(cluster.inverseBindMatrix); mesh.clusters.append(cluster); } else { - int j = start; - while (j != end) { + for (int j = rootNode; j != finalNode; j += nodeListStride) { HFMCluster cluster; cluster.jointIndex = j; cluster.inverseBindMatrix = jointInverseBindTransforms[j]; cluster.inverseBindTransform = Transform(cluster.inverseBindMatrix); mesh.clusters.append(cluster); - start < end ? j++ : j--; } } @@ -1148,7 +1152,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { // populate the texture coordinates if they don't exist if (mesh.texCoords.size() == 0 && !hfmModel.hasSkeletonJoints) { - for (int i = 0; i < part.triangleIndices.size(); i++) mesh.texCoords.push_back(glm::vec2(0.0, 1.0)); + for (int i = 0; i < part.triangleIndices.size(); i++) { mesh.texCoords.push_back(glm::vec2(0.0, 1.0)); } } mesh.meshExtents.reset(); foreach(const glm::vec3& vertex, mesh.vertices) { @@ -1161,7 +1165,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } nodecount++; - start < end ? nodeIndex++ : nodeIndex--; } diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index 331f5937ed..e383e6581c 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -712,8 +712,8 @@ private: hifi::ByteArray _glbBinary; glm::mat4 getModelTransform(const GLTFNode& node); - std::vector<QVector<float>> getSkinInverseBindMatrices(); - QVector<int> nodeDFS(int n, std::vector<int>& children, bool order); + std::vector<std::vector<float>> getSkinInverseBindMatrices(); + std::vector<int> nodeDFS(int n, std::vector<int>& children, bool order); bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url); bool parseGLTF(const hifi::ByteArray& data); From 2920fdc966b93e0e50f498168a50a25454d99883 Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Mon, 1 Apr 2019 21:09:14 +0100 Subject: [PATCH 4/9] variables, cluster size --- libraries/fbx/src/GLTFSerializer.cpp | 33 ++++++++++++---------------- libraries/fbx/src/GLTFSerializer.h | 2 +- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index d29c09992f..1192952b9e 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -753,28 +753,26 @@ std::vector<std::vector<float>> GLTFSerializer::getSkinInverseBindMatrices() { return inverseBindMatrixValues; } -std::vector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, bool order) { +std::vector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, int stride) { std::vector<int> result; result.push_back(n); - int begin = 0; - int finish = (int)children.size(); - if (order) { - begin = (int)children.size() - 1; - finish = -1; + int rootDFS = 0; + int finalDFS = (int)children.size(); + if (stride == -1) { + rootDFS = (int)children.size() - 1; + finalDFS = -1; } - int index = begin; - while (index != finish) { + for (int index = rootDFS; index != finalDFS; index += stride) { int c = children[index]; std::vector<int> nested = _file.nodes[c].children.toStdVector(); if (nested.size() != 0) { std::sort(nested.begin(), nested.end()); - for (int n : nodeDFS(c, nested, order)) { + for (int n : nodeDFS(c, nested, stride)) { result.push_back(n); } } else { result.push_back(c); } - begin < finish ? index++ : index--; } return result; } @@ -836,7 +834,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { int i = initialSceneNodes[index]; std::vector<int> children = _file.nodes[i].children.toStdVector(); std::sort(children.begin(), children.end()); - for (int n : nodeDFS(i, children, !rootAtStartOfList)) { + for (int n : nodeDFS(i, children, nodeListStride)) { nodeQueue.append(n); } } @@ -856,14 +854,11 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { joint.parentIndex = nodeQueue.indexOf(nodeDependencies[nodeIndex][0]); } joint.transform = node.transforms.first(); - joint.postTransform = glm::mat4(); - glm::vec3 scale = extractScale(joint.transform); - joint.postTransform[0][0] = scale.x; - joint.postTransform[1][1] = scale.y; - joint.postTransform[2][2] = scale.z; - joint.rotation = glmExtractRotation(joint.transform); joint.translation = extractTranslation(joint.transform); - + joint.rotation = glmExtractRotation(joint.transform); + glm::vec3 scale = extractScale(joint.transform); + joint.postTransform = glm::scale(glm::mat4(), scale); + joint.name = node.name; joint.isSkeletonJoint = false; hfmModel.joints.push_back(joint); @@ -1121,7 +1116,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { const int WEIGHTS_PER_VERTEX = 4; const float ALMOST_HALF = 0.499f; int numVertices = mesh.vertices.size(); - mesh.clusterIndices.fill(0, numClusterIndices); + mesh.clusterIndices.fill(mesh.clusters.size() - 1, numClusterIndices); mesh.clusterWeights.fill(0, numClusterIndices); for (int c = 0; c < clusterJoints.size(); c++) { diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index e383e6581c..af91a1753d 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -713,7 +713,7 @@ private: glm::mat4 getModelTransform(const GLTFNode& node); std::vector<std::vector<float>> getSkinInverseBindMatrices(); - std::vector<int> nodeDFS(int n, std::vector<int>& children, bool order); + std::vector<int> nodeDFS(int n, std::vector<int>& children, int stride); bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url); bool parseGLTF(const hifi::ByteArray& data); From 8439019c4eef997a05fe768aad22da3b83b65c6b Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Tue, 2 Apr 2019 19:56:17 +0100 Subject: [PATCH 5/9] update use of vectors --- libraries/fbx/src/GLTFSerializer.cpp | 43 ++++++++++++---------------- libraries/fbx/src/GLTFSerializer.h | 4 +-- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 1192952b9e..84609be250 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -734,8 +734,7 @@ glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) { return tmat; } -std::vector<std::vector<float>> GLTFSerializer::getSkinInverseBindMatrices() { - std::vector<std::vector<float>> inverseBindMatrixValues; +void GLTFSerializer::getSkinInverseBindMatrices(std::vector<std::vector<float>>& inverseBindMatrixValues) { for (auto &skin : _file.skins) { GLTFAccessor& indicesAccessor = _file.accessors[skin.inverseBindMatrices]; GLTFBufferView& indicesBufferview = _file.bufferviews[indicesAccessor.bufferView]; @@ -750,31 +749,28 @@ std::vector<std::vector<float>> GLTFSerializer::getSkinInverseBindMatrices() { indicesAccessor.componentType); inverseBindMatrixValues.push_back(matrices.toStdVector()); } - return inverseBindMatrixValues; } -std::vector<int> GLTFSerializer::nodeDFS(int n, std::vector<int>& children, int stride) { - std::vector<int> result; - result.push_back(n); - int rootDFS = 0; - int finalDFS = (int)children.size(); +void GLTFSerializer::getNodeQueueByDepthFirstChildren(std::vector<int>& children, int stride, std::vector<int>& result) { + int startingIndex = 0; + int finalIndex = (int)children.size(); if (stride == -1) { - rootDFS = (int)children.size() - 1; - finalDFS = -1; + startingIndex = (int)children.size() - 1; + finalIndex = -1; } - for (int index = rootDFS; index != finalDFS; index += stride) { + for (int index = startingIndex; index != finalIndex; index += stride) { int c = children[index]; + result.push_back(c); std::vector<int> nested = _file.nodes[c].children.toStdVector(); if (nested.size() != 0) { std::sort(nested.begin(), nested.end()); - for (int n : nodeDFS(c, nested, stride)) { - result.push_back(n); + for (int r : nested) { + if (result.end() == std::find(result.begin(), result.end(), r)) { + getNodeQueueByDepthFirstChildren(nested, stride, result); + } } - } else { - result.push_back(c); - } + } } - return result; } @@ -810,7 +806,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { // initialize order in which nodes will be parsed - QVector<int> nodeQueue; + std::vector<int> nodeQueue; nodeQueue.reserve(numNodes); int rootNode = 0; int finalNode = numNodes; @@ -832,14 +828,12 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } for (int index = sceneRootNode; index != sceneFinalNode; index += nodeListStride) { int i = initialSceneNodes[index]; + nodeQueue.push_back(i); std::vector<int> children = _file.nodes[i].children.toStdVector(); std::sort(children.begin(), children.end()); - for (int n : nodeDFS(i, children, nodeListStride)) { - nodeQueue.append(n); - } + getNodeQueueByDepthFirstChildren(children, nodeListStride, nodeQueue); } - // Build joints HFMJoint joint; joint.distanceToParent = 0; @@ -851,7 +845,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { joint.parentIndex = -1; if (!_file.scenes[_file.scene].nodes.contains(nodeIndex)) { - joint.parentIndex = nodeQueue.indexOf(nodeDependencies[nodeIndex][0]); + joint.parentIndex = std::distance(nodeQueue.begin(), std::find(nodeQueue.begin(), nodeQueue.end(), nodeDependencies[nodeIndex][0])); } joint.transform = node.transforms.first(); joint.translation = extractTranslation(joint.transform); @@ -869,7 +863,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { std::vector<glm::mat4> jointInverseBindTransforms; if (!_file.skins.isEmpty()) { int matrixIndex = 0; - std::vector<std::vector<float>> inverseBindValues = getSkinInverseBindMatrices(); + std::vector<std::vector<float>> inverseBindValues; + getSkinInverseBindMatrices(inverseBindValues); jointInverseBindTransforms.resize(numNodes); int jointIndex = finalNode; diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h index af91a1753d..d9c477bd99 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -712,8 +712,8 @@ private: hifi::ByteArray _glbBinary; glm::mat4 getModelTransform(const GLTFNode& node); - std::vector<std::vector<float>> getSkinInverseBindMatrices(); - std::vector<int> nodeDFS(int n, std::vector<int>& children, int stride); + void getSkinInverseBindMatrices(std::vector<std::vector<float>>& inverseBindMatrixValues); + void getNodeQueueByDepthFirstChildren(std::vector<int>& children, int stride, std::vector<int>& result); bool buildGeometry(HFMModel& hfmModel, const hifi::URL& url); bool parseGLTF(const hifi::ByteArray& data); From 14352452793f4e9d1b477c86176276b9e4fdbbcf Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Tue, 2 Apr 2019 21:18:16 +0100 Subject: [PATCH 6/9] root cluster --- libraries/fbx/src/GLTFSerializer.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 84609be250..5e4716c56d 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -861,11 +861,11 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { // Build skeleton std::vector<glm::mat4> jointInverseBindTransforms; + jointInverseBindTransforms.resize(numNodes); if (!_file.skins.isEmpty()) { int matrixIndex = 0; std::vector<std::vector<float>> inverseBindValues; getSkinInverseBindMatrices(inverseBindValues); - jointInverseBindTransforms.resize(numNodes); int jointIndex = finalNode; while (jointIndex != rootNode) { @@ -941,6 +941,12 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { mesh.clusters.append(cluster); } } + HFMCluster root; + root.jointIndex = rootNode; + if (root.jointIndex == -1) { root.jointIndex = 0; } + root.inverseBindMatrix = jointInverseBindTransforms[root.jointIndex]; + root.inverseBindTransform = Transform(root.inverseBindMatrix); + mesh.clusters.append(root); HFMMeshPart part = HFMMeshPart(); @@ -1131,6 +1137,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { for (int k = j; k < j + WEIGHTS_PER_VERTEX; ++k) { mesh.clusterWeights[k] = (uint16_t)(weightScalingFactor * clusterWeights[k] + ALMOST_HALF); } + } else { + mesh.clusterWeights[j] = (uint16_t)((float)(UINT16_MAX) + ALMOST_HALF); } } } From fcc7e9af3048b23f551bec322ec1595fab8ff16f Mon Sep 17 00:00:00 2001 From: raveenajain <jain.rav@husky.neu.edu> Date: Wed, 3 Apr 2019 00:09:36 +0100 Subject: [PATCH 7/9] minor syntax fix --- libraries/fbx/src/GLTFSerializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 5e4716c56d..1699722215 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -863,7 +863,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { std::vector<glm::mat4> jointInverseBindTransforms; jointInverseBindTransforms.resize(numNodes); if (!_file.skins.isEmpty()) { - int matrixIndex = 0; std::vector<std::vector<float>> inverseBindValues; getSkinInverseBindMatrices(inverseBindValues); @@ -886,7 +885,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { value[matrixCount + 4], value[matrixCount + 5], value[matrixCount + 6], value[matrixCount + 7], value[matrixCount + 8], value[matrixCount + 9], value[matrixCount + 10], value[matrixCount + 11], value[matrixCount + 12], value[matrixCount + 13], value[matrixCount + 14], value[matrixCount + 15]); - matrixIndex++; } else { jointInverseBindTransforms[jointIndex] = glm::mat4(); } @@ -943,7 +941,9 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::URL& url) { } HFMCluster root; root.jointIndex = rootNode; - if (root.jointIndex == -1) { root.jointIndex = 0; } + if (root.jointIndex == -1) { + root.jointIndex = 0; + } root.inverseBindMatrix = jointInverseBindTransforms[root.jointIndex]; root.inverseBindTransform = Transform(root.inverseBindMatrix); mesh.clusters.append(root); From ff3e5bbc6129762c1ce0fa18fb3cbad3e759d75a Mon Sep 17 00:00:00 2001 From: danteruiz <danteruiz102@gmail.com> Date: Tue, 2 Apr 2019 16:20:10 -0700 Subject: [PATCH 8/9] make sure to delete avatar when thier is no reason --- interface/src/avatar/AvatarManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 38bdd061c0..7a64edae11 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -497,7 +497,7 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar // it might not fire until after we create a new instance for the same remote avatar, which creates a race // on the creation of entities for that avatar instance and the deletion of entities for this instance avatar->removeAvatarEntitiesFromTree(); - if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { + if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble || removalReason == KillAvatarReason::NoReason) { emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID()); emit DependencyManager::get<UsersScriptingInterface>()->enteredIgnoreRadius(); From 44fc0d21dbc6542fcb56e26c86f02bed059d6e23 Mon Sep 17 00:00:00 2001 From: Brad Davis <bdavis@saintandreas.org> Date: Wed, 3 Apr 2019 13:43:39 -0700 Subject: [PATCH 9/9] Revert "Remove _compositeFramebuffer from display plugins" This reverts commit cb311408c68f2d465a80d76e0fdfe979cde96e13. --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 6 +- .../Basic2DWindowOpenGLDisplayPlugin.h | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 175 ++++++++++-------- .../src/display-plugins/OpenGLDisplayPlugin.h | 28 +-- .../hmd/DebugHmdDisplayPlugin.h | 2 +- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 64 ++++--- .../display-plugins/hmd/HmdDisplayPlugin.h | 11 +- .../stereo/InterleavedStereoDisplayPlugin.cpp | 4 +- .../stereo/InterleavedStereoDisplayPlugin.h | 2 +- .../src/OculusMobileDisplayPlugin.cpp | 10 +- .../src/OculusMobileDisplayPlugin.h | 4 +- .../plugins/src/plugins/DisplayPlugin.cpp | 12 +- libraries/plugins/src/plugins/DisplayPlugin.h | 8 +- .../render-utils/src/RenderCommonTask.cpp | 4 +- libraries/render/src/render/Args.h | 2 +- plugins/oculus/src/OculusDebugDisplayPlugin.h | 2 +- plugins/oculus/src/OculusDisplayPlugin.cpp | 28 +-- plugins/oculus/src/OculusDisplayPlugin.h | 2 +- .../src/OculusLegacyDisplayPlugin.cpp | 4 +- .../src/OculusLegacyDisplayPlugin.h | 2 +- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 16 +- plugins/openvr/src/OpenVrDisplayPlugin.h | 4 +- 22 files changed, 211 insertions(+), 181 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index f55f5919f5..9828a8beda 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -109,7 +109,7 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() { return Parent::internalActivate(); } -void Basic2DWindowOpenGLDisplayPlugin::compositeExtra(const gpu::FramebufferPointer& compositeFramebuffer) { +void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { #if defined(Q_OS_ANDROID) auto& virtualPadManager = VirtualPad::Manager::instance(); if(virtualPadManager.getLeftVirtualPad()->isShown()) { @@ -121,7 +121,7 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra(const gpu::FramebufferPoin render([&](gpu::Batch& batch) { batch.enableStereo(false); - batch.setFramebuffer(compositeFramebuffer); + batch.setFramebuffer(_compositeFramebuffer); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); batch.setPipeline(_cursorPipeline); @@ -140,7 +140,7 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra(const gpu::FramebufferPoin }); } #endif - Parent::compositeExtra(compositeFramebuffer); + Parent::compositeExtra(); } static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index d4c321a571..cc304c19c2 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -33,7 +33,7 @@ public: virtual bool isThrottled() const override; - virtual void compositeExtra(const gpu::FramebufferPointer&) override; + virtual void compositeExtra() override; virtual void pluginUpdate() override {}; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 5bc84acc6a..c536e6b6e2 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -379,6 +379,14 @@ void OpenGLDisplayPlugin::customizeContext() { scissorState->setDepthTest(gpu::State::DepthTest(false)); scissorState->setScissorEnable(true); + { +#ifdef Q_OS_ANDROID + gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTextureGammaLinearToSRGB); +#else + gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture); +#endif + _simplePipeline = gpu::Pipeline::create(program, scissorState); + } { #ifdef Q_OS_ANDROID gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTextureGammaLinearToSRGB); @@ -388,59 +396,29 @@ void OpenGLDisplayPlugin::customizeContext() { _presentPipeline = gpu::Pipeline::create(program, scissorState); } - - // HUD operator { - gpu::PipelinePointer hudPipeline; - { - gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture); - hudPipeline = gpu::Pipeline::create(program, blendState); - } - - gpu::PipelinePointer hudMirrorPipeline; - { - gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTextureMirroredX); - hudMirrorPipeline = gpu::Pipeline::create(program, blendState); - } - - - _hudOperator = [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, const gpu::FramebufferPointer& compositeFramebuffer, bool mirror) { - auto hudStereo = isStereo(); - auto hudCompositeFramebufferSize = compositeFramebuffer->getSize(); - std::array<glm::ivec4, 2> hudEyeViewports; - for_each_eye([&](Eye eye) { - hudEyeViewports[eye] = eyeViewport(eye); - }); - if (hudPipeline && hudTexture) { - batch.enableStereo(false); - batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline); - batch.setResourceTexture(0, hudTexture); - if (hudStereo) { - for_each_eye([&](Eye eye) { - batch.setViewportTransform(hudEyeViewports[eye]); - batch.draw(gpu::TRIANGLE_STRIP, 4); - }); - } else { - batch.setViewportTransform(ivec4(uvec2(0), hudCompositeFramebufferSize)); - batch.draw(gpu::TRIANGLE_STRIP, 4); - } - } - }; - + gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture); + _hudPipeline = gpu::Pipeline::create(program, blendState); + } + { + gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTextureMirroredX); + _mirrorHUDPipeline = gpu::Pipeline::create(program, blendState); } - { gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTransformedTexture); _cursorPipeline = gpu::Pipeline::create(program, blendState); } } + updateCompositeFramebuffer(); } void OpenGLDisplayPlugin::uncustomizeContext() { _presentPipeline.reset(); _cursorPipeline.reset(); - _hudOperator = DEFAULT_HUD_OPERATOR; + _hudPipeline.reset(); + _mirrorHUDPipeline.reset(); + _compositeFramebuffer.reset(); withPresentThreadLock([&] { _currentFrame.reset(); _lastFrame = nullptr; @@ -532,16 +510,24 @@ void OpenGLDisplayPlugin::captureFrame(const std::string& filename) const { }); } +void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor) { + renderFromTexture(batch, texture, viewport, scissor, nullptr); +} -void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& destFbo, const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) { +void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& copyFbo /*=gpu::FramebufferPointer()*/) { + auto fbo = gpu::FramebufferPointer(); batch.enableStereo(false); batch.resetViewTransform(); - batch.setFramebuffer(destFbo); + batch.setFramebuffer(fbo); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); batch.setStateScissorRect(scissor); batch.setViewportTransform(viewport); batch.setResourceTexture(0, texture); +#ifndef USE_GLES batch.setPipeline(_presentPipeline); +#else + batch.setPipeline(_simplePipeline); +#endif batch.draw(gpu::TRIANGLE_STRIP, 4); if (copyFbo) { gpu::Vec4i copyFboRect(0, 0, copyFbo->getWidth(), copyFbo->getHeight()); @@ -567,7 +553,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.setViewportTransform(copyFboRect); batch.setStateScissorRect(copyFboRect); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); - batch.blit(destFbo, sourceRect, copyFbo, copyRect); + batch.blit(fbo, sourceRect, copyFbo, copyRect); } } @@ -595,14 +581,41 @@ void OpenGLDisplayPlugin::updateFrameData() { }); } -void OpenGLDisplayPlugin::compositePointer(const gpu::FramebufferPointer& compositeFramebuffer) { +std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> OpenGLDisplayPlugin::getHUDOperator() { + auto hudPipeline = _hudPipeline; + auto hudMirrorPipeline = _mirrorHUDPipeline; + auto hudStereo = isStereo(); + auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize(); + std::array<glm::ivec4, 2> hudEyeViewports; + for_each_eye([&](Eye eye) { + hudEyeViewports[eye] = eyeViewport(eye); + }); + return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + if (hudPipeline && hudTexture) { + batch.enableStereo(false); + batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline); + batch.setResourceTexture(0, hudTexture); + if (hudStereo) { + for_each_eye([&](Eye eye) { + batch.setViewportTransform(hudEyeViewports[eye]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + } else { + batch.setViewportTransform(ivec4(uvec2(0), hudCompositeFramebufferSize)); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } + } + }; +} + +void OpenGLDisplayPlugin::compositePointer() { auto& cursorManager = Cursor::Manager::instance(); const auto& cursorData = _cursorsData[cursorManager.getCursor()->getIcon()]; auto cursorTransform = DependencyManager::get<CompositorHelper>()->getReticleTransform(glm::mat4()); render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.setProjectionTransform(mat4()); - batch.setFramebuffer(compositeFramebuffer); + batch.setFramebuffer(_compositeFramebuffer); batch.setPipeline(_cursorPipeline); batch.setResourceTexture(0, cursorData.texture); batch.resetViewTransform(); @@ -613,13 +626,34 @@ void OpenGLDisplayPlugin::compositePointer(const gpu::FramebufferPointer& compos batch.draw(gpu::TRIANGLE_STRIP, 4); }); } else { - batch.setViewportTransform(ivec4(uvec2(0), compositeFramebuffer->getSize())); + batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize())); batch.draw(gpu::TRIANGLE_STRIP, 4); } }); } -void OpenGLDisplayPlugin::compositeLayers(const gpu::FramebufferPointer& compositeFramebuffer) { +void OpenGLDisplayPlugin::compositeScene() { + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(_compositeFramebuffer); + batch.setViewportTransform(ivec4(uvec2(), _compositeFramebuffer->getSize())); + batch.setStateScissorRect(ivec4(uvec2(), _compositeFramebuffer->getSize())); + batch.resetViewTransform(); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_simplePipeline); + batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); +} + +void OpenGLDisplayPlugin::compositeLayers() { + updateCompositeFramebuffer(); + + { + PROFILE_RANGE_EX(render_detail, "compositeScene", 0xff0077ff, (uint64_t)presentCount()) + compositeScene(); + } + #ifdef HIFI_ENABLE_NSIGHT_DEBUG if (false) // do not draw the HUD if running nsight debug #endif @@ -633,35 +667,23 @@ void OpenGLDisplayPlugin::compositeLayers(const gpu::FramebufferPointer& composi { PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) - compositeExtra(compositeFramebuffer); + compositeExtra(); } // Draw the pointer last so it's on top of everything auto compositorHelper = DependencyManager::get<CompositorHelper>(); if (compositorHelper->getReticleVisible()) { PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) - compositePointer(compositeFramebuffer); + compositePointer(); } } -void OpenGLDisplayPlugin::internalPresent(const gpu::FramebufferPointer& compositeFramebuffer) { +void OpenGLDisplayPlugin::internalPresent() { render([&](gpu::Batch& batch) { // Note: _displayTexture must currently be the same size as the display. uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels(); auto viewport = ivec4(uvec2(0), dims); - - gpu::TexturePointer finalTexture; - if (_displayTexture) { - finalTexture = _displayTexture; - } else if (compositeFramebuffer) { - finalTexture = compositeFramebuffer->getRenderBuffer(0); - } else { - qCWarning(displayPlugins) << "No valid texture for output"; - } - - if (finalTexture) { - renderFromTexture(batch, finalTexture, viewport, viewport); - } + renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); }); swapBuffers(); _presentRate.increment(); @@ -678,7 +700,7 @@ void OpenGLDisplayPlugin::present() { } incrementPresentCount(); - if (_currentFrame && _currentFrame->framebuffer) { + if (_currentFrame) { auto correction = getViewCorrection(); getGLBackend()->setCameraCorrection(correction, _prevRenderView); _prevRenderView = correction * _currentFrame->view; @@ -698,18 +720,18 @@ void OpenGLDisplayPlugin::present() { // Write all layers to a local framebuffer { PROFILE_RANGE_EX(render, "composite", 0xff00ffff, frameId) - compositeLayers(_currentFrame->framebuffer); + compositeLayers(); } // Take the composite framebuffer and send it to the output device { PROFILE_RANGE_EX(render, "internalPresent", 0xff00ffff, frameId) - internalPresent(_currentFrame->framebuffer); + internalPresent(); } gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory()); } else if (alwaysPresent()) { - internalPresent(nullptr); + internalPresent(); } _movingAveragePresent.addSample((float)(usecTimestampNow() - startPresent)); } @@ -766,12 +788,7 @@ bool OpenGLDisplayPlugin::setDisplayTexture(const QString& name) { } QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { - if (!_currentFrame || !_currentFrame->framebuffer) { - return QImage(); - } - - auto compositeFramebuffer = _currentFrame->framebuffer; - auto size = compositeFramebuffer->getSize(); + auto size = _compositeFramebuffer->getSize(); if (isHmd()) { size.x /= 2; } @@ -789,7 +806,7 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const { auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend(); QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32); withOtherThreadContext([&] { - glBackend->downloadFramebuffer(compositeFramebuffer, ivec4(corner, bestSize), screenshot); + glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot); }); return screenshot.mirrored(false, true); } @@ -841,7 +858,7 @@ bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { } ivec4 OpenGLDisplayPlugin::eyeViewport(Eye eye) const { - auto vpSize = glm::uvec2(getRecommendedRenderSize()); + uvec2 vpSize = _compositeFramebuffer->getSize(); vpSize.x /= 2; uvec2 vpPos; if (eye == Eye::Right) { @@ -874,6 +891,14 @@ void OpenGLDisplayPlugin::render(std::function<void(gpu::Batch& batch)> f) { OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } +void OpenGLDisplayPlugin::updateCompositeFramebuffer() { + auto renderSize = glm::uvec2(getRecommendedRenderSize()); + if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); + // _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); + } +} + void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) { #if !defined(USE_GLES) auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 3c48e8fc48..49a38ecb4c 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -94,10 +94,14 @@ protected: // is not populated virtual bool alwaysPresent() const { return false; } + void updateCompositeFramebuffer(); + virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; } - virtual void compositeLayers(const gpu::FramebufferPointer&); - virtual void compositePointer(const gpu::FramebufferPointer&); - virtual void compositeExtra(const gpu::FramebufferPointer&) {}; + virtual void compositeLayers(); + virtual void compositeScene(); + virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator(); + virtual void compositePointer(); + virtual void compositeExtra() {}; // These functions must only be called on the presentation thread virtual void customizeContext(); @@ -112,10 +116,10 @@ protected: virtual void deactivateSession() {} // Plugin specific functionality to send the composed scene to the output window or device - virtual void internalPresent(const gpu::FramebufferPointer&); + virtual void internalPresent(); - - void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& destFbo = nullptr, const gpu::FramebufferPointer& copyFbo = nullptr); + void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor, const gpu::FramebufferPointer& fbo); + void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer& texture, const glm::ivec4& viewport, const glm::ivec4& scissor); virtual void updateFrameData(); virtual glm::mat4 getViewCorrection() { return glm::mat4(); } @@ -138,8 +142,14 @@ protected: gpu::FramePointer _currentFrame; gpu::Frame* _lastFrame { nullptr }; mat4 _prevRenderView; + gpu::FramebufferPointer _compositeFramebuffer; + gpu::PipelinePointer _hudPipeline; + gpu::PipelinePointer _mirrorHUDPipeline; + gpu::ShaderPointer _mirrorHUDPS; + gpu::PipelinePointer _simplePipeline; + gpu::PipelinePointer _presentPipeline; gpu::PipelinePointer _cursorPipeline; - gpu::TexturePointer _displayTexture; + gpu::TexturePointer _displayTexture{}; float _compositeHUDAlpha { 1.0f }; struct CursorData { @@ -175,9 +185,5 @@ protected: // be serialized through this mutex mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; - -private: - gpu::PipelinePointer _presentPipeline; - }; diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h index 95592cc490..f2b1f36419 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h @@ -24,7 +24,7 @@ public: protected: void updatePresentPose() override; - void hmdPresent(const gpu::FramebufferPointer&) override {} + void hmdPresent() override {} bool isHmdMounted() const override { return true; } bool internalActivate() override; private: diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index a515232b3f..321bcc3fd2 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -114,23 +114,20 @@ void HmdDisplayPlugin::internalDeactivate() { void HmdDisplayPlugin::customizeContext() { Parent::customizeContext(); - _hudOperator = _hudRenderer.build(); + _hudRenderer.build(); } void HmdDisplayPlugin::uncustomizeContext() { // This stops the weirdness where if the preview was disabled, on switching back to 2D, // the vsync was stuck in the disabled state. No idea why that happens though. _disablePreview = false; - if (_currentFrame && _currentFrame->framebuffer) { - render([&](gpu::Batch& batch) { - batch.enableStereo(false); - batch.resetViewTransform(); - batch.setFramebuffer(_currentFrame->framebuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); - }); - - } - _hudRenderer = {}; + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.resetViewTransform(); + batch.setFramebuffer(_compositeFramebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); + }); + _hudRenderer = HUDRenderer(); _previewTexture.reset(); Parent::uncustomizeContext(); } @@ -177,11 +174,11 @@ float HmdDisplayPlugin::getLeftCenterPixel() const { return leftCenterPixel; } -void HmdDisplayPlugin::internalPresent(const gpu::FramebufferPointer& compositeFramebuffer) { +void HmdDisplayPlugin::internalPresent() { PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) // Composite together the scene, hud and mouse cursor - hmdPresent(compositeFramebuffer); + hmdPresent(); if (_displayTexture) { // Note: _displayTexture must currently be the same size as the display. @@ -263,7 +260,7 @@ void HmdDisplayPlugin::internalPresent(const gpu::FramebufferPointer& compositeF viewport.z *= 2; } - renderFromTexture(batch, compositeFramebuffer->getRenderBuffer(0), viewport, scissor, nullptr, fbo); + renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo); }); swapBuffers(); @@ -348,7 +345,7 @@ glm::mat4 HmdDisplayPlugin::getViewCorrection() { } } -DisplayPlugin::HUDOperator HmdDisplayPlugin::HUDRenderer::build() { +void HmdDisplayPlugin::HUDRenderer::build() { vertices = std::make_shared<gpu::Buffer>(); indices = std::make_shared<gpu::Buffer>(); @@ -383,7 +380,7 @@ DisplayPlugin::HUDOperator HmdDisplayPlugin::HUDRenderer::build() { indexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; // Compute indices order - std::vector<GLushort> indexData; + std::vector<GLushort> indices; for (int i = 0; i < stacks - 1; i++) { for (int j = 0; j < slices - 1; j++) { GLushort bottomLeftIndex = i * slices + j; @@ -391,21 +388,24 @@ DisplayPlugin::HUDOperator HmdDisplayPlugin::HUDRenderer::build() { GLushort topLeftIndex = bottomLeftIndex + slices; GLushort topRightIndex = topLeftIndex + 1; // FIXME make a z-order curve for better vertex cache locality - indexData.push_back(topLeftIndex); - indexData.push_back(bottomLeftIndex); - indexData.push_back(topRightIndex); + indices.push_back(topLeftIndex); + indices.push_back(bottomLeftIndex); + indices.push_back(topRightIndex); - indexData.push_back(topRightIndex); - indexData.push_back(bottomLeftIndex); - indexData.push_back(bottomRightIndex); + indices.push_back(topRightIndex); + indices.push_back(bottomLeftIndex); + indices.push_back(bottomRightIndex); } } - indices->append(indexData); + this->indices->append(indices); format = std::make_shared<gpu::Stream::Format>(); // 1 for everyone format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); uniformsBuffer = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr); + updatePipeline(); +} +void HmdDisplayPlugin::HUDRenderer::updatePipeline() { if (!pipeline) { auto program = gpu::Shader::createProgram(shader::render_utils::program::hmd_ui); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -416,6 +416,10 @@ DisplayPlugin::HUDOperator HmdDisplayPlugin::HUDRenderer::build() { pipeline = gpu::Pipeline::create(program, state); } +} + +std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) { + updatePipeline(); auto hudPipeline = pipeline; auto hudFormat = format; @@ -424,9 +428,9 @@ DisplayPlugin::HUDOperator HmdDisplayPlugin::HUDRenderer::build() { auto hudUniformBuffer = uniformsBuffer; auto hudUniforms = uniforms; auto hudIndexCount = indexCount; - return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, const gpu::FramebufferPointer&, const bool mirror) { - if (pipeline && hudTexture) { - batch.setPipeline(pipeline); + return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + if (hudPipeline && hudTexture) { + batch.setPipeline(hudPipeline); batch.setInputFormat(hudFormat); gpu::BufferView posView(hudVertices, VERTEX_OFFSET, hudVertices->getSize(), VERTEX_STRIDE, hudFormat->getAttributes().at(gpu::Stream::POSITION)._element); @@ -450,7 +454,7 @@ DisplayPlugin::HUDOperator HmdDisplayPlugin::HUDRenderer::build() { }; } -void HmdDisplayPlugin::compositePointer(const gpu::FramebufferPointer& compositeFramebuffer) { +void HmdDisplayPlugin::compositePointer() { auto& cursorManager = Cursor::Manager::instance(); const auto& cursorData = _cursorsData[cursorManager.getCursor()->getIcon()]; auto compositorHelper = DependencyManager::get<CompositorHelper>(); @@ -459,7 +463,7 @@ void HmdDisplayPlugin::compositePointer(const gpu::FramebufferPointer& composite render([&](gpu::Batch& batch) { // FIXME use standard gpu stereo rendering for this. batch.enableStereo(false); - batch.setFramebuffer(compositeFramebuffer); + batch.setFramebuffer(_compositeFramebuffer); batch.setPipeline(_cursorPipeline); batch.setResourceTexture(0, cursorData.texture); batch.resetViewTransform(); @@ -474,6 +478,10 @@ void HmdDisplayPlugin::compositePointer(const gpu::FramebufferPointer& composite }); } +std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDisplayPlugin::getHUDOperator() { + return _hudRenderer.render(*this); +} + HmdDisplayPlugin::~HmdDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 6755c5b7e0..d8c0ce8e1d 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -53,15 +53,16 @@ signals: void hmdVisibleChanged(bool visible); protected: - virtual void hmdPresent(const gpu::FramebufferPointer&) = 0; + virtual void hmdPresent() = 0; virtual bool isHmdMounted() const = 0; virtual void postPreview() {}; virtual void updatePresentPose(); bool internalActivate() override; void internalDeactivate() override; - void compositePointer(const gpu::FramebufferPointer&) override; - void internalPresent(const gpu::FramebufferPointer&) override; + std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator() override; + void compositePointer() override; + void internalPresent() override; void customizeContext() override; void uncustomizeContext() override; void updateFrameData() override; @@ -119,6 +120,8 @@ private: static const size_t TEXTURE_OFFSET { offsetof(Vertex, uv) }; static const int VERTEX_STRIDE { sizeof(Vertex) }; - HUDOperator build(); + void build(); + void updatePipeline(); + std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> render(HmdDisplayPlugin& plugin); } _hudRenderer; }; diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp index 69aa7fc344..0ae0f9b1b6 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp @@ -37,13 +37,13 @@ glm::uvec2 InterleavedStereoDisplayPlugin::getRecommendedRenderSize() const { return result; } -void InterleavedStereoDisplayPlugin::internalPresent(const gpu::FramebufferPointer& compositeFramebuffer) { +void InterleavedStereoDisplayPlugin::internalPresent() { render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.resetViewTransform(); batch.setFramebuffer(gpu::FramebufferPointer()); batch.setViewportTransform(ivec4(uvec2(0), getSurfacePixels())); - batch.setResourceTexture(0, compositeFramebuffer->getRenderBuffer(0)); + batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); batch.setPipeline(_interleavedPresentPipeline); batch.draw(gpu::TRIANGLE_STRIP, 4); }); diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h index 52dfa8f402..debd340f24 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -21,7 +21,7 @@ protected: // initialize OpenGL context settings needed by the plugin void customizeContext() override; void uncustomizeContext() override; - void internalPresent(const gpu::FramebufferPointer&) override; + void internalPresent() override; private: static const QString NAME; diff --git a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp index 12a9b12adc..9809d02866 100644 --- a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp +++ b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp @@ -245,7 +245,7 @@ void OculusMobileDisplayPlugin::updatePresentPose() { }); } -void OculusMobileDisplayPlugin::internalPresent(const gpu::FramebufferPointer& compsiteFramebuffer) { +void OculusMobileDisplayPlugin::internalPresent() { VrHandler::pollTask(); if (!vrActive()) { @@ -253,12 +253,8 @@ void OculusMobileDisplayPlugin::internalPresent(const gpu::FramebufferPointer& c return; } - GLuint sourceTexture = 0; - glm::uvec2 sourceSize; - if (compsiteFramebuffer) { - sourceTexture = getGLBackend()->getTextureID(compsiteFramebuffer->getRenderBuffer(0)); - sourceSize = { compsiteFramebuffer->getWidth(), compsiteFramebuffer->getHeight() }; - } + auto sourceTexture = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); + glm::uvec2 sourceSize{ _compositeFramebuffer->getWidth(), _compositeFramebuffer->getHeight() }; VrHandler::presentFrame(sourceTexture, sourceSize, presentTracking); _presentRate.increment(); } diff --git a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h index b5f7aa57b0..a98989655e 100644 --- a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h +++ b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h @@ -54,8 +54,8 @@ protected: void uncustomizeContext() override; void updatePresentPose() override; - void internalPresent(const gpu::FramebufferPointer&) override; - void hmdPresent(const gpu::FramebufferPointer&) override { throw std::runtime_error("Unused"); } + void internalPresent() override; + void hmdPresent() override { throw std::runtime_error("Unused"); } bool isHmdMounted() const override; bool alwaysPresent() const override { return true; } diff --git a/libraries/plugins/src/plugins/DisplayPlugin.cpp b/libraries/plugins/src/plugins/DisplayPlugin.cpp index 71db87557c..47503e8f85 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.cpp +++ b/libraries/plugins/src/plugins/DisplayPlugin.cpp @@ -2,12 +2,6 @@ #include <NumericalConstants.h> - -const DisplayPlugin::HUDOperator DisplayPlugin::DEFAULT_HUD_OPERATOR{ std::function<void(gpu::Batch&, const gpu::TexturePointer&, const gpu::FramebufferPointer&, bool mirror)>() }; - -DisplayPlugin::DisplayPlugin() : _hudOperator{ DEFAULT_HUD_OPERATOR } { -} - int64_t DisplayPlugin::getPaintDelayUsecs() const { std::lock_guard<std::mutex> lock(_paintDelayMutex); return _paintDelayTimer.isValid() ? _paintDelayTimer.nsecsElapsed() / NSECS_PER_USEC : 0; @@ -41,8 +35,8 @@ void DisplayPlugin::waitForPresent() { } } -std::function<void(gpu::Batch&, const gpu::TexturePointer&, const gpu::FramebufferPointer& compositeFramebuffer, bool mirror)> DisplayPlugin::getHUDOperator() { - HUDOperator hudOperator; +std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> DisplayPlugin::getHUDOperator() { + std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> hudOperator; { QMutexLocker locker(&_presentMutex); hudOperator = _hudOperator; @@ -54,5 +48,3 @@ glm::mat4 HmdDisplay::getEyeToHeadTransform(Eye eye) const { static const glm::mat4 xform; return xform; } - - diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 9194fde3ac..aa52e57c3f 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -121,8 +121,6 @@ class DisplayPlugin : public Plugin, public HmdDisplay { Q_OBJECT using Parent = Plugin; public: - DisplayPlugin(); - virtual int getRequiredThreadCount() const { return 0; } virtual bool isHmd() const { return false; } virtual int getHmdScreen() const { return -1; } @@ -216,8 +214,7 @@ public: void waitForPresent(); float getAveragePresentTime() { return _movingAveragePresent.average / (float)USECS_PER_MSEC; } // in msec - using HUDOperator = std::function<void(gpu::Batch&, const gpu::TexturePointer&, const gpu::FramebufferPointer&, bool mirror)>; - virtual HUDOperator getHUDOperator() final; + std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> getHUDOperator(); static const QString& MENU_PATH(); @@ -234,8 +231,7 @@ protected: gpu::ContextPointer _gpuContext; - static const HUDOperator DEFAULT_HUD_OPERATOR; - HUDOperator _hudOperator; + std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> _hudOperator { std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)>() }; MovingAverage<float, 10> _movingAveragePresent; diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index e021465ff3..b1a62625b2 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -126,8 +126,8 @@ void CompositeHUD::run(const RenderContextPointer& renderContext, const gpu::Fra if (inputs) { batch.setFramebuffer(inputs); } - if (renderContext->args->_hudOperator && renderContext->args->_blitFramebuffer) { - renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_blitFramebuffer, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE); + if (renderContext->args->_hudOperator) { + renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture, renderContext->args->_renderMode == RenderArgs::RenderMode::MIRROR_RENDER_MODE); } }); #endif diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 8b2fff68c6..b5c98e3428 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -131,7 +131,7 @@ namespace render { render::ScenePointer _scene; int8_t _cameraMode { -1 }; - std::function<void(gpu::Batch&, const gpu::TexturePointer&, const gpu::FramebufferPointer&, bool mirror)> _hudOperator; + std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> _hudOperator; gpu::TexturePointer _hudTexture; }; diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.h b/plugins/oculus/src/OculusDebugDisplayPlugin.h index 690a488b34..ec05cd92e2 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.h +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.h @@ -16,7 +16,7 @@ public: bool isSupported() const override; protected: - void hmdPresent(const gpu::FramebufferPointer&) override {} + void hmdPresent() override {} bool isHmdMounted() const override { return true; } private: diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 48440ac80f..df01591639 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -108,16 +108,13 @@ void OculusDisplayPlugin::customizeContext() { } void OculusDisplayPlugin::uncustomizeContext() { - #if 0 - if (_currentFrame && _currentFrame->framebuffer) { - // Present a final black frame to the HMD - _currentFrame->framebuffer->Bound(FramebufferTarget::Draw, [] { - Context::ClearColor(0, 0, 0, 1); - Context::Clear().ColorBuffer(); - }); - hmdPresent(); - } + // Present a final black frame to the HMD + _compositeFramebuffer->Bound(FramebufferTarget::Draw, [] { + Context::ClearColor(0, 0, 0, 1); + Context::Clear().ColorBuffer(); + }); + hmdPresent(); #endif ovr_DestroyTextureSwapChain(_session, _textureSwapChain); @@ -130,7 +127,7 @@ void OculusDisplayPlugin::uncustomizeContext() { static const uint64_t FRAME_BUDGET = (11 * USECS_PER_MSEC); static const uint64_t FRAME_OVER_BUDGET = (15 * USECS_PER_MSEC); -void OculusDisplayPlugin::hmdPresent(const gpu::FramebufferPointer& compositeFramebuffer) { +void OculusDisplayPlugin::hmdPresent() { static uint64_t lastSubmitEnd = 0; if (!_customized) { @@ -160,8 +157,15 @@ void OculusDisplayPlugin::hmdPresent(const gpu::FramebufferPointer& compositeFra auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0); render([&](gpu::Batch& batch) { - auto viewport = ivec4(uvec2(), _outputFramebuffer->getSize()); - renderFromTexture(batch, compositeFramebuffer->getRenderBuffer(0), viewport, viewport, _outputFramebuffer); + batch.enableStereo(false); + batch.setFramebuffer(_outputFramebuffer); + batch.setViewportTransform(ivec4(uvec2(), _outputFramebuffer->getSize())); + batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); + batch.resetViewTransform(); + batch.setProjectionTransform(mat4()); + batch.setPipeline(_presentPipeline); + batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); + batch.draw(gpu::TRIANGLE_STRIP, 4); }); glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, 0, 0); } diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index a0126d2e58..9209fd373e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -28,7 +28,7 @@ protected: QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; } bool internalActivate() override; - void hmdPresent(const gpu::FramebufferPointer&) override; + void hmdPresent() override; bool isHmdMounted() const override; void customizeContext() override; void uncustomizeContext() override; diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp index a928887866..e6b555443f 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp @@ -237,7 +237,7 @@ void OculusLegacyDisplayPlugin::uncustomizeContext() { Parent::uncustomizeContext(); } -void OculusLegacyDisplayPlugin::hmdPresent(const gpu::FramebufferPointer& compositeFramebuffer) { +void OculusLegacyDisplayPlugin::hmdPresent() { if (!_hswDismissed) { ovrHSWDisplayState hswState; ovrHmd_GetHSWDisplayState(_hmd, &hswState); @@ -252,7 +252,7 @@ void OculusLegacyDisplayPlugin::hmdPresent(const gpu::FramebufferPointer& compos memset(eyePoses, 0, sizeof(ovrPosef) * 2); eyePoses[0].Orientation = eyePoses[1].Orientation = ovrRotation; - GLint texture = getGLBackend()->getTextureID(compositeFramebuffer->getRenderBuffer(0)); + GLint texture = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); if (_hmdWindow->makeCurrent()) { diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index 241d626f0c..36bdd1c792 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -39,7 +39,7 @@ protected: void customizeContext() override; void uncustomizeContext() override; - void hmdPresent(const gpu::FramebufferPointer&) override; + void hmdPresent() override; bool isHmdMounted() const override { return true; } private: diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 3d22268472..11d941dcd0 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -511,13 +511,13 @@ void OpenVrDisplayPlugin::customizeContext() { Parent::customizeContext(); if (_threadedSubmit) { -// _compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0); + _compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0); for (size_t i = 0; i < COMPOSITING_BUFFER_SIZE; ++i) { -// if (0 != i) { + if (0 != i) { _compositeInfos[i].texture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT)); -// } + } _compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture); } _submitThread->_canvas = _submitCanvas; @@ -613,17 +613,17 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { return Parent::beginFrameRender(frameIndex); } -void OpenVrDisplayPlugin::compositeLayers(const gpu::FramebufferPointer& compositeFramebuffer) { +void OpenVrDisplayPlugin::compositeLayers() { if (_threadedSubmit) { ++_renderingIndex; _renderingIndex %= COMPOSITING_BUFFER_SIZE; auto& newComposite = _compositeInfos[_renderingIndex]; newComposite.pose = _currentPresentFrameInfo.presentPose; - compositeFramebuffer->setRenderBuffer(0, newComposite.texture); + _compositeFramebuffer->setRenderBuffer(0, newComposite.texture); } - Parent::compositeLayers(compositeFramebuffer); + Parent::compositeLayers(); if (_threadedSubmit) { auto& newComposite = _compositeInfos[_renderingIndex]; @@ -645,13 +645,13 @@ void OpenVrDisplayPlugin::compositeLayers(const gpu::FramebufferPointer& composi } } -void OpenVrDisplayPlugin::hmdPresent(const gpu::FramebufferPointer& compositeFramebuffer) { +void OpenVrDisplayPlugin::hmdPresent() { PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) if (_threadedSubmit) { _submitThread->waitForPresent(); } else { - GLuint glTexId = getGLBackend()->getTextureID(compositeFramebuffer->getRenderBuffer(0)); + GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); vr::Texture_t vrTexture{ (void*)(uintptr_t)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 923a0f7a8f..265f328920 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -72,8 +72,8 @@ protected: void internalDeactivate() override; void updatePresentPose() override; - void compositeLayers(const gpu::FramebufferPointer&) override; - void hmdPresent(const gpu::FramebufferPointer&) override; + void compositeLayers() override; + void hmdPresent() override; bool isHmdMounted() const override; void postPreview() override;