diff --git a/.clang-format b/.clang-format
index 04e0284f97..ef3ce64192 100644
--- a/.clang-format
+++ b/.clang-format
@@ -13,6 +13,7 @@ AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: None
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: true
+BinPackParameters: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
diff --git a/Code/Sandbox/Editor/AboutDialog.ui b/Code/Sandbox/Editor/AboutDialog.ui
index 67767c0de1..0b86f15542 100644
--- a/Code/Sandbox/Editor/AboutDialog.ui
+++ b/Code/Sandbox/Editor/AboutDialog.ui
@@ -75,14 +75,14 @@
- 161
- 49
+ 175
+ 66
- 161
- 49
+ 175
+ 66
diff --git a/Code/Sandbox/Editor/StartupLogoDialog.ui b/Code/Sandbox/Editor/StartupLogoDialog.ui
index 6e01808a84..0815fa8b18 100644
--- a/Code/Sandbox/Editor/StartupLogoDialog.ui
+++ b/Code/Sandbox/Editor/StartupLogoDialog.ui
@@ -42,14 +42,14 @@
- 161
- 49
+ 175
+ 66
- 161
- 50
+ 175
+ 66
diff --git a/Code/Sandbox/Editor/o3de_logo.svg b/Code/Sandbox/Editor/o3de_logo.svg
index ba44566ce8..35a880c5c8 100644
--- a/Code/Sandbox/Editor/o3de_logo.svg
+++ b/Code/Sandbox/Editor/o3de_logo.svg
@@ -1,22 +1,35 @@
-
\ No newline at end of file
diff --git a/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/license.txt b/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/license.txt
new file mode 100644
index 0000000000..158138973a
--- /dev/null
+++ b/Gems/Atom/RHI/Vulkan/External/glad/2.0.0-beta/include/glad/license.txt
@@ -0,0 +1,209 @@
+vulkan.h was generated using a code generator from https://github.com/Dav1dde/glad
+
+/*
+** Copyright (c) 2014-2020 The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0
+*/
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelKdTree.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelKdTree.h
index 9cd33eda6c..832681d7f1 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelKdTree.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Model/ModelKdTree.h
@@ -35,7 +35,15 @@ namespace AZ
ModelKdTree() = default;
bool Build(const ModelAsset* model);
- bool RayIntersection(const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance, AZ::Vector3& normal) const;
+ //! Return if a ray intersected the model.
+ //! @param raySrc The starting point of the ray.
+ //! @param rayDir The direction and length of the ray (magnitude is encoded in the direction).
+ //! @param[out] The normalized distance of the intersection (in the range 0.0-1.0) - to calculate the actual
+ //! distance, multiply distanceNormalized by the magnitude of rayDir.
+ //! @param[out] The surface normal of the intersection with the model.
+ //! @return Return true if there was an intersection with the model, false otherwise.
+ bool RayIntersection(
+ const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const;
void GetPenetratedBoxes(const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, AZStd::vector& outBoxes);
enum ESplitAxis
@@ -53,8 +61,14 @@ namespace AZ
private:
void BuildRecursively(ModelKdTreeNode* pNode, const AZ::Aabb& boundbox, AZStd::vector& indices);
- bool RayIntersectionRecursively(ModelKdTreeNode* pNode, const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance, AZ::Vector3& normal) const;
- void GetPenetratedBoxesRecursively(ModelKdTreeNode* pNode, const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, AZStd::vector& outBoxes);
+ bool RayIntersectionRecursively(
+ ModelKdTreeNode* pNode,
+ const AZ::Vector3& raySrc,
+ const AZ::Vector3& rayDir,
+ float& distanceNormalized,
+ AZ::Vector3& normal) const;
+ void GetPenetratedBoxesRecursively(
+ ModelKdTreeNode* pNode, const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, AZStd::vector& outBoxes);
void ConstructMeshList(const ModelAsset* model, const AZ::Transform& matParent);
static const int s_MinimumVertexSizeInLeafNode = 3 * 10;
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp
index 15c8aaf528..86477bf785 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp
@@ -140,8 +140,9 @@ namespace AZ
bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distance, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
- float firstHit;
- const int result = Intersect::IntersectRayAABB2(rayStart, dir.GetReciprocal(), m_aabb, firstHit, distance);
+ float start;
+ float end;
+ const int result = Intersect::IntersectRayAABB2(rayStart, dir.GetReciprocal(), m_aabb, start, end);
if (Intersect::ISECT_RAY_AABB_NONE != result)
{
if (ModelAsset* modelAssetPtr = m_modelAsset.Get())
@@ -164,7 +165,9 @@ namespace AZ
return false;
}
- bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const
+ bool Model::RayIntersection(
+ const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir,
+ float& distanceFactor, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
const AZ::Vector3 clampedScale = nonUniformScale.GetMax(AZ::Vector3(AZ::MinTransformScale));
diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelKdTree.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelKdTree.cpp
index 6a1897815f..bee489c2fd 100644
--- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelKdTree.cpp
+++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelKdTree.cpp
@@ -11,6 +11,7 @@
*/
#include
+#include
#include
#include
@@ -191,10 +192,10 @@ namespace AZ
if (ModelLodAsset* lodAssetPtr = model->GetLodAssets()[0].Get())
{
- AZ_Warning("ModelKdTree", lodAssetPtr->GetMeshes().size() <= std::numeric_limits::max() + 1,
+ AZ_Warning("ModelKdTree", lodAssetPtr->GetMeshes().size() <= AZStd::numeric_limits::max() + 1,
"KdTree generation doesn't support models with greater than 256 meshes. RayIntersection results will be incorrect "
"unless the meshes are merged or broken up into multiple models");
- const size_t size = AZStd::min(lodAssetPtr->GetMeshes().size(), std::numeric_limits::max() + 1);
+ const size_t size = AZStd::min(lodAssetPtr->GetMeshes().size(), AZStd::numeric_limits::max() + 1);
m_meshes.reserve(size);
AZStd::transform(
lodAssetPtr->GetMeshes().begin(), AZStd::next(lodAssetPtr->GetMeshes().begin(), size),
@@ -204,20 +205,42 @@ namespace AZ
}
}
- bool ModelKdTree::RayIntersection(const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance, AZ::Vector3& normal) const
+ bool ModelKdTree::RayIntersection(
+ const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const
{
- return RayIntersectionRecursively(m_pRootNode.get(), raySrc, rayDir, distance, normal);
+ float closestDistanceNormalized = AZStd::numeric_limits::max();
+ if (RayIntersectionRecursively(m_pRootNode.get(), raySrc, rayDir, closestDistanceNormalized, normal))
+ {
+ distanceNormalized = closestDistanceNormalized;
+ return true;
+ }
+
+ return false;
}
- bool ModelKdTree::RayIntersectionRecursively(ModelKdTreeNode* pNode, const AZ::Vector3& raySrc, const AZ::Vector3& rayDir, float& distance, AZ::Vector3& normal) const
+ bool ModelKdTree::RayIntersectionRecursively(
+ ModelKdTreeNode* pNode,
+ const AZ::Vector3& raySrc,
+ const AZ::Vector3& rayDir,
+ float& distanceNormalized,
+ AZ::Vector3& normal) const
{
+ using Intersect::IntersectRayAABB2;
+ using Intersect::IntersectSegmentTriangleCCW;
+ using Intersect::ISECT_RAY_AABB_NONE;
+
if (!pNode)
{
return false;
}
float start, end;
- if (AZ::Intersect::IntersectRayAABB2(raySrc, rayDir.GetReciprocal(), pNode->GetBoundBox(), start, end) == Intersect::ISECT_RAY_AABB_NONE)
+ if (IntersectRayAABB2(raySrc, rayDir.GetReciprocal(), pNode->GetBoundBox(), start, end) == ISECT_RAY_AABB_NONE)
+ {
+ return false;
+ }
+
+ if (start > distanceNormalized)
{
return false;
}
@@ -235,17 +258,13 @@ namespace AZ
return false;
}
- AZ::Vector3 intersectionNormal;
- float hitDistanceNormalized;
- const float maxDist(FLT_MAX);
- float nearestDist = maxDist;
-
+ float nearestDistanceNormalized = distanceNormalized;
for (AZ::u32 i = 0; i < nVBuffSize; ++i)
{
const auto& [first, second, third] = pNode->GetVertexIndex(i);
const AZ::u32 nObjIndex = pNode->GetObjIndex(i);
- AZStd::array_view positionBuffer = m_meshes[nObjIndex].m_vertexData;
+ const AZStd::array_view positionBuffer = m_meshes[nObjIndex].m_vertexData;
if (positionBuffer.empty())
{
@@ -258,25 +277,23 @@ namespace AZ
AZ::Vector3{positionBuffer[third * 3 + 0], positionBuffer[third * 3 + 1], positionBuffer[third * 3 + 2]},
};
- const AZ::Vector3 rayEnd = raySrc + rayDir * distance;
-
- if (AZ::Intersect::IntersectSegmentTriangleCCW(raySrc, rayEnd, trianglePoints[0], trianglePoints[1], trianglePoints[2],
- intersectionNormal, hitDistanceNormalized) != Intersect::ISECT_RAY_AABB_NONE)
+ float hitDistanceNormalized;
+ AZ::Vector3 intersectionNormal;
+ const AZ::Vector3 rayEnd = raySrc + rayDir;
+ if (IntersectSegmentTriangleCCW(raySrc, rayEnd, trianglePoints[0], trianglePoints[1], trianglePoints[2],
+ intersectionNormal, hitDistanceNormalized) != ISECT_RAY_AABB_NONE)
{
- float hitDistance = hitDistanceNormalized * distance;
-
- if (nearestDist > hitDistance)
+ if (nearestDistanceNormalized > hitDistanceNormalized)
{
normal = intersectionNormal;
+ nearestDistanceNormalized = hitDistanceNormalized;
}
-
- nearestDist = AZStd::GetMin(nearestDist, hitDistance);
}
}
- if (nearestDist < maxDist)
+ if (nearestDistanceNormalized < distanceNormalized)
{
- distance = AZStd::GetMin(distance, nearestDist);
+ distanceNormalized = nearestDistanceNormalized;
return true;
}
@@ -284,8 +301,8 @@ namespace AZ
}
// running both sides to find the closest intersection
- const bool bFoundChild0 = RayIntersectionRecursively(pNode->GetChild(0), raySrc, rayDir, distance, normal);
- const bool bFoundChild1 = RayIntersectionRecursively(pNode->GetChild(1), raySrc, rayDir, distance, normal);
+ const bool bFoundChild0 = RayIntersectionRecursively(pNode->GetChild(0), raySrc, rayDir, distanceNormalized, normal);
+ const bool bFoundChild1 = RayIntersectionRecursively(pNode->GetChild(1), raySrc, rayDir, distanceNormalized, normal);
return bFoundChild0 || bFoundChild1;
}
@@ -311,5 +328,5 @@ namespace AZ
GetPenetratedBoxesRecursively(pNode->GetChild(0), raySrc, rayDir, outBoxes);
GetPenetratedBoxesRecursively(pNode->GetChild(1), raySrc, rayDir, outBoxes);
}
- }
-}
+ } // namespace RPI
+} // namespace AZ
diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp
index 1ec14c6169..3ce17bee8b 100644
--- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp
+++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp
@@ -1074,13 +1074,13 @@ namespace UnitTest
}
};
- class KdTreeIntersectsFixture
+ class KdTreeIntersectsParameterizedFixture
: public ModelTests
, public ::testing::WithParamInterface
{
};
- TEST_P(KdTreeIntersectsFixture, KdTreeIntersects)
+ TEST_P(KdTreeIntersectsParameterizedFixture, KdTreeIntersects)
{
TwoSeparatedPlanesMesh mesh;
@@ -1090,7 +1090,10 @@ namespace UnitTest
float distance = AZStd::numeric_limits::max();
AZ::Vector3 normal;
- EXPECT_THAT(kdTree.RayIntersection(AZ::Vector3(GetParam().xpos, GetParam().ypos, GetParam().zpos), AZ::Vector3::CreateAxisZ(-1.0f), distance, normal), testing::Eq(GetParam().expectedShouldIntersect));
+ EXPECT_THAT(
+ kdTree.RayIntersection(
+ AZ::Vector3(GetParam().xpos, GetParam().ypos, GetParam().zpos), AZ::Vector3::CreateAxisZ(-1.0f), distance, normal),
+ testing::Eq(GetParam().expectedShouldIntersect));
EXPECT_THAT(distance, testing::FloatEq(GetParam().expectedDistance));
}
@@ -1119,5 +1122,63 @@ namespace UnitTest
KdTreeIntersectParams{0.778f, 0.111f, 1.0f, 0.5f, true},
KdTreeIntersectParams{0.778f, 0.778f, 1.0f, 0.5f, true},
};
- INSTANTIATE_TEST_CASE_P(KdTreeIntersectsPlane, KdTreeIntersectsFixture, ::testing::ValuesIn(intersectTestData));
+
+ INSTANTIATE_TEST_CASE_P(KdTreeIntersectsPlane, KdTreeIntersectsParameterizedFixture, ::testing::ValuesIn(intersectTestData));
+
+ class KdTreeIntersectsFixture
+ : public ModelTests
+ {
+ public:
+ void SetUp() override
+ {
+ ModelTests::SetUp();
+
+ m_mesh = AZStd::make_unique();
+ m_kdTree = AZStd::make_unique();
+ ASSERT_TRUE(m_kdTree->Build(m_mesh->GetModel().Get()));
+ }
+
+ void TearDown() override
+ {
+ m_kdTree.reset();
+ m_mesh.reset();
+
+ ModelTests::TearDown();
+ }
+
+ AZStd::unique_ptr m_mesh;
+ AZStd::unique_ptr m_kdTree;
+ };
+
+ TEST_F(KdTreeIntersectsFixture, KdTreeIntersectionReturnsNormalizedDistance)
+ {
+ float t = AZStd::numeric_limits::max();
+ AZ::Vector3 normal;
+
+ constexpr float rayLength = 100.0f;
+ EXPECT_THAT(
+ m_kdTree->RayIntersection(
+ AZ::Vector3::CreateZero(), AZ::Vector3::CreateAxisZ(-rayLength), t, normal), testing::Eq(true));
+ EXPECT_THAT(t, testing::FloatEq(0.005f));
+ }
+
+ TEST_F(KdTreeIntersectsFixture, KdTreeIntersectionHandlesInvalidStartingNormalizedDistance)
+ {
+ float t = -0.5f; // invalid starting distance
+ AZ::Vector3 normal;
+
+ constexpr float rayLength = 10.0f;
+ EXPECT_THAT(
+ m_kdTree->RayIntersection(AZ::Vector3::CreateAxisZ(0.75f), AZ::Vector3::CreateAxisZ(-rayLength), t, normal), testing::Eq(true));
+ EXPECT_THAT(t, testing::FloatEq(0.025f));
+ }
+
+ TEST_F(KdTreeIntersectsFixture, KdTreeIntersectionDoesNotScaleRayByStartingDistance)
+ {
+ float t = 10.0f; // starting distance (used to check it is not read from initially by RayIntersection)
+ AZ::Vector3 normal;
+
+ EXPECT_THAT(
+ m_kdTree->RayIntersection(AZ::Vector3::CreateAxisZ(5.0f), -AZ::Vector3::CreateAxisZ(), t, normal), testing::Eq(false));
+ }
} // namespace UnitTest
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
index f2ad9a13e6..e1c9026c74 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp
@@ -140,9 +140,16 @@ namespace AZ
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
+ float t;
AZ::Vector3 ignoreNormal;
+ constexpr float rayLength = 1000.0f;
+ if (m_controller.GetModel()->RayIntersection(transform, nonUniformScale, src, dir * rayLength, t, ignoreNormal))
+ {
+ distance = rayLength * t;
+ return true;
+ }
- return m_controller.GetModel()->RayIntersection(transform, nonUniformScale, src, dir, distance, ignoreNormal);
+ return false;
}
bool EditorMeshComponent::SupportsEditorRayIntersect()
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
index c089dd01f9..e7eecd3c7f 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp
@@ -485,16 +485,12 @@ namespace AZ
m_transformInterface->GetWorldTM(), m_cachedNonUniformScale, ray.m_startWorldPosition,
ray.m_endWorldPosition - ray.m_startWorldPosition, t, normal))
{
- // note: this is a temporary workaround to handle cases where model->RayIntersection
- // returns negative distances, follow-up ATOM-15673
- const auto absT = AZStd::abs(t);
-
// fill in ray result structure after successful intersection
const auto intersectionLine = (ray.m_endWorldPosition - ray.m_startWorldPosition);
result.m_uv = AZ::Vector2::CreateZero();
- result.m_worldPosition = ray.m_startWorldPosition + intersectionLine * absT;
+ result.m_worldPosition = ray.m_startWorldPosition + intersectionLine * t;
result.m_worldNormal = normal;
- result.m_distance = intersectionLine.GetLength() * absT;
+ result.m_distance = intersectionLine.GetLength() * t;
result.m_entityAndComponent = m_entityComponentIdPair;
}
}
diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp
index 294f4c7c99..46760af8f0 100644
--- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp
+++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Commands.cpp
@@ -218,6 +218,10 @@ namespace EMStudio
}
const bool saveResult = manifest.SaveToFile(manifestFilename.c_str());
+ if (saveResult)
+ {
+ actor->SetDirtyFlag(false);
+ }
// Source Control: Add file in case it did not exist before (when saving it the first time).
if (saveResult && !fileExisted)
diff --git a/cmake/3rdParty/FindClang.cmake b/cmake/3rdParty/FindClang.cmake
deleted file mode 100644
index 8062e6ebb2..0000000000
--- a/cmake/3rdParty/FindClang.cmake
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
-# its licensors.
-#
-# For complete copyright and license terms please see the LICENSE at the root of this
-# distribution (the "License"). All use of this software is governed by the License,
-# or, if provided, by the license below or the license accompanying this file. Do not
-# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#
-
-ly_add_external_target(
- NAME Clang
- VERSION 6.0.1-az
-)
diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake
index ebbad6e156..f7a315686f 100644
--- a/cmake/3rdParty/cmake_files.cmake
+++ b/cmake/3rdParty/cmake_files.cmake
@@ -11,7 +11,6 @@
set(FILES
BuiltInPackages.cmake
- FindClang.cmake
FindOpenGLInterface.cmake
FindRadTelemetry.cmake
FindVkValidation.cmake