Showing the changes to libraries/render-utils/src/Model.cpp (1 of 25 files). Show all
Unified · Split
| @@ -82,6 +82,7 @@ Model::Model(QObject* parent) : · 81 unmodified lines | |||
| 82 | _isVisible(true), | 82 | _isVisible(true), |
| 83 | _blendNumber(0), | 83 | _blendNumber(0), |
| 84 | _appliedBlendNumber(0), | 84 | _appliedBlendNumber(0), |
| 85 | _calculatedMeshPartOffsetValid(false), | ||
| 85 | _calculatedMeshPartBoxesValid(false), | 86 | _calculatedMeshPartBoxesValid(false), |
| 86 | _calculatedMeshBoxesValid(false), | 87 | _calculatedMeshBoxesValid(false), |
| 87 | _calculatedMeshTrianglesValid(false), | 88 | _calculatedMeshTrianglesValid(false), |
| @@ -544,6 +545,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 456 unmodified lines | |||
| 544 | // we can use the AABox's ray intersection by mapping our origin and direction into the model frame | 545 | // we can use the AABox's ray intersection by mapping our origin and direction into the model frame |
| 545 | // and testing intersection there. | 546 | // and testing intersection there. |
| 546 | if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { | 547 | if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { |
| 548 | |||
| 549 | if (!_calculatedMeshBoxesValid) { | ||
| 550 | recalculateMeshBoxes(pickAgainstTriangles); | ||
| 551 | } | ||
| 547 | 552 | ||
| 548 | float bestDistance = std::numeric_limits<float>::max(); | 553 | float bestDistance = std::numeric_limits<float>::max(); |
| 549 | 554 | ||
| @@ -660,6 +665,25 @@ bool Model::convexHullContains(glm::vec3 point) { · 110 unmodified lines | |||
| 660 | return false; | 665 | return false; |
| 661 | } | 666 | } |
| 662 | 667 | ||
| 668 | void Model::recalculateMeshPartOffsets() { | ||
| 669 | if (!_calculatedMeshPartOffsetValid) { | ||
| 670 | const FBXGeometry& geometry = _geometry->getFBXGeometry(); | ||
| 671 | int numberOfMeshes = geometry.meshes.size(); | ||
| 672 | _calculatedMeshPartOffset.clear(); | ||
| 673 | for (int i = 0; i < numberOfMeshes; i++) { | ||
| 674 | const FBXMesh& mesh = geometry.meshes.at(i); | ||
| 675 | qint64 partOffset = 0; | ||
| 676 | for (int j = 0; j < mesh.parts.size(); j++) { | ||
| 677 | const FBXMeshPart& part = mesh.parts.at(j); | ||
| 678 | _calculatedMeshPartOffset[QPair<int,int>(i, j)] = partOffset; | ||
| 679 | partOffset += part.quadIndices.size() * sizeof(int); | ||
| 680 | partOffset += part.triangleIndices.size() * sizeof(int); | ||
| 681 | |||
| 682 | } | ||
| 683 | } | ||
| 684 | _calculatedMeshPartOffsetValid = true; | ||
| 685 | } | ||
| 686 | } | ||
| 663 | // TODO: we seem to call this too often when things haven't actually changed... look into optimizing this | 687 | // TODO: we seem to call this too often when things haven't actually changed... look into optimizing this |
| 664 | // Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these | 688 | // Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these |
| 665 | // can occur multiple times. In addition, rendering does it's own ray picking in order to decide which | 689 | // can occur multiple times. In addition, rendering does it's own ray picking in order to decide which |
| @@ -675,7 +699,8 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { · 9 unmodified lines | |||
| 675 | _calculatedMeshTriangles.clear(); | 699 | _calculatedMeshTriangles.clear(); |
| 676 | _calculatedMeshTriangles.resize(numberOfMeshes); | 700 | _calculatedMeshTriangles.resize(numberOfMeshes); |
| 677 | _calculatedMeshPartBoxes.clear(); | 701 | _calculatedMeshPartBoxes.clear(); |
| 678 | _calculatedMeshPartOffet.clear(); | 702 | _calculatedMeshPartOffset.clear(); |
| 703 | _calculatedMeshPartOffsetValid = false; | ||
| 679 | for (int i = 0; i < numberOfMeshes; i++) { | 704 | for (int i = 0; i < numberOfMeshes; i++) { |
| 680 | const FBXMesh& mesh = geometry.meshes.at(i); | 705 | const FBXMesh& mesh = geometry.meshes.at(i); |
| 681 | Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); | 706 | Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); |
| @@ -770,7 +795,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { · 88 unmodified lines | |||
| 770 | } | 795 | } |
| 771 | } | 796 | } |
| 772 | _calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds; | 797 | _calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds; |
| 773 | _calculatedMeshPartOffet[QPair<int,int>(i, j)] = partOffset; | 798 | _calculatedMeshPartOffset[QPair<int,int>(i, j)] = partOffset; |
| 774 | 799 | ||
| 775 | partOffset += part.quadIndices.size() * sizeof(int); | 800 | partOffset += part.quadIndices.size() * sizeof(int); |
| 776 | partOffset += part.triangleIndices.size() * sizeof(int); | 801 | partOffset += part.triangleIndices.size() * sizeof(int); |
| @@ -778,6 +803,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { · 1 unmodified line | |||
| 778 | } | 803 | } |
| 779 | _calculatedMeshTriangles[i] = thisMeshTriangles; | 804 | _calculatedMeshTriangles[i] = thisMeshTriangles; |
| 780 | _calculatedMeshPartBoxesValid = true; | 805 | _calculatedMeshPartBoxesValid = true; |
| 806 | _calculatedMeshPartOffsetValid = true; | ||
| 781 | } | 807 | } |
| 782 | } | 808 | } |
| 783 | _calculatedMeshBoxesValid = true; | 809 | _calculatedMeshBoxesValid = true; |
| @@ -786,16 +812,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { · 2 unmodified lines | |||
| 786 | } | 812 | } |
| 787 | 813 | ||
| 788 | void Model::renderSetup(RenderArgs* args) { | 814 | void Model::renderSetup(RenderArgs* args) { |
| 789 | // if we don't have valid mesh boxes, calculate them now, this only matters in cases | ||
| 790 | // where our caller has passed RenderArgs which will include a view frustum we can cull | ||
| 791 | // against. We cache the results of these calculations so long as the model hasn't been | ||
| 792 | // simulated and the mesh hasn't changed. | ||
| 793 | if (args && !_calculatedMeshBoxesValid) { | ||
| 794 | _mutex.lock(); | ||
| 795 | recalculateMeshBoxes(); | ||
| 796 | _mutex.unlock(); | ||
| 797 | } | ||
| 798 | |||
| 799 | // set up dilated textures on first render after load/simulate | 815 | // set up dilated textures on first render after load/simulate |
| 800 | const FBXGeometry& geometry = _geometry->getFBXGeometry(); | 816 | const FBXGeometry& geometry = _geometry->getFBXGeometry(); |
| 801 | if (_dilatedTextures.isEmpty()) { | 817 | if (_dilatedTextures.isEmpty()) { |
| @@ -1342,18 +1358,15 @@ void Model::snapToRegistrationPoint() { · 540 unmodified lines | |||
| 1342 | } | 1358 | } |
| 1343 | 1359 | ||
| 1344 | void Model::simulate(float deltaTime, bool fullUpdate) { | 1360 | void Model::simulate(float deltaTime, bool fullUpdate) { |
| 1345 | /* | ||
| 1346 | qDebug() << "Model::simulate()"; | ||
| 1347 | qDebug() << " _translation:" << _translation; | ||
| 1348 | qDebug() << " _rotation:" << _rotation; | ||
| 1349 | */ | ||
| 1350 | |||
| 1351 | fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) | 1361 | fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) |
| 1352 | || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); | 1362 | || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); |
| 1353 | 1363 | ||
| 1354 | if (isActive() && fullUpdate) { | 1364 | if (isActive() && fullUpdate) { |
| 1355 | // NOTE: this seems problematic... need to review | 1365 | // NOTE: This is overly aggressive and we are invalidating the MeshBoxes when in fact they may not be invalid |
| 1356 | _calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid | 1366 | // they really only become invalid if something about the transform to world space has changed. This is |
| 1367 | // not too bad at this point, because it doesn't impact rendering. However it does slow down ray picking | ||
| 1368 | // because ray picking needs valid boxes to work | ||
| 1369 | _calculatedMeshBoxesValid = false; | ||
| 1357 | _calculatedMeshTrianglesValid = false; | 1370 | _calculatedMeshTrianglesValid = false; |
| 1358 | 1371 | ||
| 1359 | // check for scale to fit | 1372 | // check for scale to fit |
| @@ -1761,10 +1774,6 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { · 401 unmodified lines | |||
| 1761 | } | 1774 | } |
| 1762 | 1775 | ||
| 1763 | AABox Model::getPartBounds(int meshIndex, int partIndex) { | 1776 | AABox Model::getPartBounds(int meshIndex, int partIndex) { |
| 1764 | if (!_calculatedMeshPartBoxesValid || !_calculatedMeshBoxesValid) { | ||
| 1765 | recalculateMeshBoxes(true); | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | if (meshIndex < _meshStates.size()) { | 1777 | if (meshIndex < _meshStates.size()) { |
| 1769 | const MeshState& state = _meshStates.at(meshIndex); | 1778 | const MeshState& state = _meshStates.at(meshIndex); |
| 1770 | bool isSkinned = state.clusterMatrices.size() > 1; | 1779 | bool isSkinned = state.clusterMatrices.size() > 1; |
| @@ -1774,7 +1783,7 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { · 3 unmodified lines | |||
| 1774 | } | 1783 | } |
| 1775 | } | 1784 | } |
| 1776 | 1785 | ||
| 1777 | if (_calculatedMeshPartBoxesValid && _calculatedMeshPartBoxes.contains(QPair<int,int>(meshIndex, partIndex))) { | 1786 | if (_geometry->getFBXGeometry().meshes.size() > meshIndex) { |
| 1778 | 1787 | ||
| 1779 | // FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding | 1788 | // FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding |
| 1780 | // box of the mesh part fails. It seems to create boxes that are not consistent with where the | 1789 | // box of the mesh part fails. It seems to create boxes that are not consistent with where the |
| @@ -1796,15 +1805,13 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { · 15 unmodified lines | |||
| 1796 | 1805 | ||
| 1797 | void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { | 1806 | void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) { |
| 1798 | PerformanceTimer perfTimer("Model::renderPart"); | 1807 | PerformanceTimer perfTimer("Model::renderPart"); |
| 1799 | |||
| 1800 | if (!_readyWhenAdded) { | 1808 | if (!_readyWhenAdded) { |
| 1801 | return; // bail asap | 1809 | return; // bail asap |
| 1802 | } | 1810 | } |
| 1803 | 1811 | ||
| 1804 | // we always need these properly calculated before we can render, this will likely already have been done | 1812 | // We need to make sure we have valid offsets calculated before we can render |
| 1805 | // since the engine will call our getPartBounds() before rendering us. | 1813 | if (!_calculatedMeshPartOffsetValid) { |
| 1806 | if (!_calculatedMeshPartBoxesValid || !_calculatedMeshBoxesValid) { | 1814 | recalculateMeshPartOffsets(); |
| 1807 | recalculateMeshBoxes(true); | ||
| 1808 | } | 1815 | } |
| 1809 | auto textureCache = DependencyManager::get<TextureCache>(); | 1816 | auto textureCache = DependencyManager::get<TextureCache>(); |
| 1810 | 1817 | ||
| @@ -2012,7 +2019,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran · 201 unmodified lines | |||
| 2012 | } | 2019 | } |
| 2013 | } | 2020 | } |
| 2014 | 2021 | ||
| 2015 | qint64 offset = _calculatedMeshPartOffet[QPair<int,int>(meshIndex, partIndex)]; | 2022 | qint64 offset = _calculatedMeshPartOffset[QPair<int,int>(meshIndex, partIndex)]; |
| 2016 | 2023 | ||
| 2017 | if (part.quadIndices.size() > 0) { | 2024 | if (part.quadIndices.size() > 0) { |
| 2018 | batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); | 2025 | batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); |