Merge branch 'development' into cmake/warn_virtual

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
Esteban Papp
2021-09-07 08:26:37 -07:00
1829 changed files with 8816 additions and 19153 deletions
@@ -628,7 +628,7 @@ int AZ::Intersect::IntersectRayCappedCylinder(
int AZ::Intersect::IntersectRayCone(
const Vector3& rayOrigin, const Vector3& rayDir,
const Vector3& coneApex, const Vector3& coneDir, float coneHeight,
float coneBaseRaidus, float& t1, float& t2)
float coneBaseRadius, float& t1, float& t2)
{
// Q = rayOrgin, A = coneApex
Vector3 AQ = rayOrigin - coneApex;
@@ -646,7 +646,7 @@ int AZ::Intersect::IntersectRayCone(
return 0;
}
float r2 = coneBaseRaidus * coneBaseRaidus;
float r2 = coneBaseRadius * coneBaseRadius;
float h2 = coneHeight * coneHeight;
float m2 = m * m;
@@ -240,7 +240,7 @@ namespace AZ
//! @return The number of intersecting points.
int IntersectRayCone(
const Vector3& rayOrigin, const Vector3& rayDir,
const Vector3& coneApex, const Vector3& coneDir, float coneHeight, float coneBaseRaidus,
const Vector3& coneApex, const Vector3& coneDir, float coneHeight, float coneBaseRadius,
float& t1, float& t2);
//! Test intersection between a ray and a plane in 3D.
+6 -7
View File
@@ -12,10 +12,12 @@
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common)
if(PAL_TRAIT_PROF_PIX_SUPPORTED AND LY_PIX_ENABLED)
set(LY_PIX_PATH "${LY_3RDPARTY_PATH}/winpixeventruntime" CACHE PATH "Path to the Windows Pix Event Runtime.")
set(AZ_CORE_PIX_BUILD_DEPENDENCIES 3rdParty::pix)
set(AZ_CORE_PIX_BUILD_DEFINES "USE_PIX")
if(PAL_TRAIT_PROF_PIX_SUPPORTED)
set(LY_PIX_ENABLED OFF CACHE BOOL "Enables PIX profiler integration.")
if(LY_PIX_ENABLED)
message(STATUS "PIX found, enabling as profiler")
set(AZ_CORE_PIX_BUILD_DEPENDENCIES 3rdParty::pix)
endif()
endif()
ly_add_target(
@@ -41,9 +43,6 @@ ly_add_target(
3rdParty::zstd
3rdParty::cityhash
${AZ_CORE_PIX_BUILD_DEPENDENCIES}
COMPILE_DEFINITIONS
PUBLIC
${AZ_CORE_PIX_BUILD_DEFINES}
)
ly_add_source_properties(
SOURCES
@@ -609,6 +609,21 @@ namespace UnitTest
EXPECT_EQ(hits, 0);
}
// replicates a scenario in the Editor using a cone and a pick ray which should have failed but passed
// note: To replicate this, select an entity so the default translation manipulator appears, move very close to the
// entity, hover the mouse over one of the manipulator linear manipulator arrows (cone part) and move the mouse away
// notice the manipulator will remain highlighted as a successful intersection is still reported
TEST(MATH_IntersectRayConeTestEditor, DISABLED_RayConeEditorScenarioTest)
{
auto rayOrigin = Vector3(0.0f, -0.808944702f, 0.0f);
auto rayDir = Vector3(0.301363617f, 0.939044654f, 0.165454566f);
float t1 = 0.0f;
float t2 = 0.0f;
int hits = Intersect::IntersectRayCone(
rayOrigin, rayDir, AZ::Vector3(0.0f, 0.0f, 0.161788940f), AZ::Vector3(0.0f, 0.0f, -1.0f), 0.0453009047, 0.0113252262, t1, t2);
EXPECT_EQ(hits, 0);
}
class MATH_IntersectRayQuadTest
: public AllocatorsFixture
{
@@ -17,14 +17,14 @@ namespace AzManipulatorTestFramework
//! Implementation of the viewport interaction model to handle viewport interaction requests.
class ViewportInteraction
: public ViewportInteractionInterface
, private AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
, public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
, public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
{
public:
ViewportInteraction();
~ViewportInteraction();
// ViewportInteractionInterface ...
AzFramework::CameraState GetCameraState() override;
// ViewportInteractionInterface overrides ...
void SetCameraState(const AzFramework::CameraState& cameraState) override;
AzFramework::DebugDisplayRequests& GetDebugDisplay() override;
void EnableGridSnaping() override;
@@ -34,20 +34,24 @@ namespace AzManipulatorTestFramework
void SetGridSize(float size) override;
void SetAngularStep(float step) override;
int GetViewportId() const override;
// ViewportInteractionRequestBus overrides ...
AzFramework::CameraState GetCameraState() override;
AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition);
AZStd::optional<AZ::Vector3> ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override;
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> ViewportScreenToWorldRay(
const AzFramework::ScreenPoint& screenPosition) override;
float DeviceScalingFactor() override;
private:
// ViewportInteractionRequestBus ...
bool GridSnappingEnabled() override;
float GridSize() override;
bool ShowGrid() override;
bool AngleSnappingEnabled() override;
float AngleStep() override;
float ManipulatorLineBoundWidth() override;
AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition);
// ViewportSettingsRequestBus overrides ...
bool GridSnappingEnabled() const override;
float GridSize() const override;
bool ShowGrid() const override;
bool AngleSnappingEnabled() const override;
float AngleStep() const override;
float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override;
private:
AZStd::unique_ptr<NullDebugDisplayRequests> m_nullDebugDisplayRequests;
const int m_viewportId = 1234; // Arbitrary viewport id for manipulator tests
@@ -25,10 +25,12 @@ namespace AzManipulatorTestFramework
: m_nullDebugDisplayRequests(AZStd::make_unique<NullDebugDisplayRequests>())
{
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(m_viewportId);
}
ViewportInteraction::~ViewportInteraction()
{
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect();
}
@@ -37,32 +39,37 @@ namespace AzManipulatorTestFramework
return m_cameraState;
}
bool ViewportInteraction::GridSnappingEnabled()
bool ViewportInteraction::GridSnappingEnabled() const
{
return m_gridSnapping;
}
float ViewportInteraction::GridSize()
float ViewportInteraction::GridSize() const
{
return m_gridSize;
}
bool ViewportInteraction::ShowGrid()
bool ViewportInteraction::ShowGrid() const
{
return false;
}
bool ViewportInteraction::AngleSnappingEnabled()
bool ViewportInteraction::AngleSnappingEnabled() const
{
return m_angularSnapping;
}
float ViewportInteraction::AngleStep()
float ViewportInteraction::AngleStep() const
{
return m_angularStep;
}
float ViewportInteraction::ManipulatorLineBoundWidth()
float ViewportInteraction::ManipulatorLineBoundWidth() const
{
return 0.1f;
}
float ViewportInteraction::ManipulatorCircleBoundWidth() const
{
return 0.1f;
}
@@ -49,9 +49,9 @@ namespace UnitTest
bool snapping = false;
m_viewportInteraction->EnableGridSnaping();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, m_viewportInteraction->GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
&AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled);
EXPECT_TRUE(snapping);
}
@@ -61,9 +61,9 @@ namespace UnitTest
bool snapping = true;
m_viewportInteraction->DisableGridSnaping();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, m_viewportInteraction->GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
&AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled);
EXPECT_FALSE(snapping);
}
@@ -76,9 +76,9 @@ namespace UnitTest
m_viewportInteraction->SetGridSize(expectedGridSize);
m_viewportInteraction->DisableGridSnaping();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult(
gridSize, m_viewportInteraction->GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
&AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::GridSize);
EXPECT_EQ(gridSize, expectedGridSize);
}
@@ -88,9 +88,9 @@ namespace UnitTest
bool snapping = false;
m_viewportInteraction->EnableAngularSnaping();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, m_viewportInteraction->GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::AngleSnappingEnabled);
&AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::AngleSnappingEnabled);
EXPECT_TRUE(snapping);
}
@@ -100,9 +100,9 @@ namespace UnitTest
bool snapping = true;
m_viewportInteraction->DisableAngularSnaping();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, m_viewportInteraction->GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::AngleSnappingEnabled);
&AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::AngleSnappingEnabled);
EXPECT_FALSE(snapping);
}
@@ -114,9 +114,9 @@ namespace UnitTest
m_viewportInteraction->SetAngularStep(expectedAngularStep);
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult(
angularStep, m_viewportInteraction->GetViewportId(),
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::AngleStep);
&AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::AngleStep);
EXPECT_EQ(angularStep, expectedAngularStep);
}
@@ -70,8 +70,12 @@ namespace AzToolsFramework
//! Determines if the caller needs to wait for the Python VM to initialize (non-main thread only)
virtual void WaitForInitialization() {}
//! Acquires the Python global interpreter lock (GIL) and executed the callback
//! Acquires the Python global interpreter lock (GIL) and execute the callback
virtual void ExecuteWithLock(AZStd::function<void()> executionCallback) = 0;
//! Tries to acquire the Python global interpreter lock (GIL) and execute the callback.
//! @return Whether it was able to lock the mutex or not.
virtual bool TryExecuteWithLock(AZStd::function<void()> executionCallback) = 0;
};
//! A bus to handle post notifications to the console views of Python output
@@ -226,8 +226,7 @@ namespace AzToolsFramework
m_translationManipulator = AZStd::make_shared<IndexedTranslationManipulator<Vertex>>(
Dimensions(), vertexIndex, vertex, WorldFromLocalWithUniformScale(entityComponentIdPair.GetEntityId()),
GetNonUniformScale(entityComponentIdPair.GetEntityId()));
m_translationManipulator->m_manipulator.SetLineBoundWidth(
AzToolsFramework::ManipulatorLineBoundWidth(AzFramework::InvalidViewportId));
m_translationManipulator->m_manipulator.SetLineBoundWidth(AzToolsFramework::ManipulatorLineBoundWidth());
// setup how the manipulator should look
m_manipulatorConfiguratorFn(&m_translationManipulator->m_manipulator);
@@ -137,8 +137,8 @@ namespace AzToolsFramework
bool GridSnapping(const int viewportId)
{
bool snapping = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
snapping, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled);
return snapping;
}
@@ -146,8 +146,8 @@ namespace AzToolsFramework
float GridSize(const int viewportId)
{
float gridSize = 0.0f;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
gridSize, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
gridSize, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSize);
return gridSize;
}
@@ -168,8 +168,8 @@ namespace AzToolsFramework
bool AngleSnapping(const int viewportId)
{
bool snapping = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
snapping, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::AngleSnappingEnabled);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::AngleSnappingEnabled);
return snapping;
}
@@ -177,8 +177,8 @@ namespace AzToolsFramework
float AngleStep(const int viewportId)
{
float angle = 0.0f;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
angle, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::AngleStep);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
angle, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::AngleStep);
return angle;
}
@@ -186,8 +186,8 @@ namespace AzToolsFramework
bool ShowingGrid(const int viewportId)
{
bool show = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
show, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ShowGrid);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
show, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::ShowGrid);
return show;
}
@@ -8,9 +8,9 @@
#include "ManipulatorView.h"
#include <AzCore/Console/IConsole.h>
#include <AzCore/Component/NonUniformScaleBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Math/VectorConversions.h>
#include <AzCore/std/containers/array.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
@@ -413,8 +413,8 @@ namespace AzToolsFramework
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const auto worldLine = CalculateLine(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_length * viewScale);
const auto worldLine =
CalculateLine(manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_length * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
debugDisplay.SetLineWidth(defaultLineWidth(manipulatorState.m_mouseOver));
@@ -612,13 +612,30 @@ namespace AzToolsFramework
const Picking::BoundShapeTorus torusBound = CalculateTorusBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_axis, m_radius * viewScale, m_width * viewScale);
// transform circle based on delta between default z up axis and other axes
const AZ::Transform worldFromLocalWithOrientation =
AZ::Transform::CreateTranslation(manipulatorState.m_worldFromLocal.GetTranslation()) *
const AZ::Transform orientation =
AZ::Transform::CreateFromQuaternion((QuaternionFromTransformNoScaling(manipulatorState.m_worldFromLocal) *
AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisZ(), m_axis))
.GetNormalized());
// transform circle based on delta between default z up axis and other axes
const AZ::Transform worldFromLocalWithOrientation =
AZ::Transform::CreateTranslation(manipulatorState.m_worldFromLocal.GetTranslation()) * orientation;
if (ed_manipulatorDisplayBoundDebug)
{
debugDisplay.SetColor(AZ::Colors::BlanchedAlmond);
debugDisplay.PushMatrix(orientation);
debugDisplay.DrawCircle(torusBound.m_center + AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius, torusBound.m_majorRadius);
debugDisplay.DrawCircle(
torusBound.m_center + AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius,
torusBound.m_majorRadius + torusBound.m_minorRadius);
debugDisplay.DrawCircle(torusBound.m_center - AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius, torusBound.m_majorRadius);
debugDisplay.DrawCircle(
torusBound.m_center - AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius,
torusBound.m_majorRadius + torusBound.m_minorRadius);
debugDisplay.PopMatrix();
}
debugDisplay.CullOn();
debugDisplay.PushMatrix(worldFromLocalWithOrientation);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
@@ -638,7 +655,10 @@ namespace AzToolsFramework
}
void DrawFullCircle(
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, const float radius, const AZ::Vector3& /*viewPos*/)
AzFramework::DebugDisplayRequests& debugDisplay,
const AZ::Vector3& position,
const float radius,
[[maybe_unused]] const AZ::Vector3& viewPos)
{
debugDisplay.DrawCircle(position, radius);
}
@@ -130,11 +130,13 @@ namespace AzToolsFramework
for (size_t manipulatorIndex = 0; manipulatorIndex < m_localAngularManipulators.size(); ++manipulatorIndex)
{
m_localAngularManipulators[manipulatorIndex]->SetView(CreateManipulatorViewCircle(
*m_localAngularManipulators[manipulatorIndex], colors[manipulatorIndex], radius, 0.05f, DrawHalfDottedCircle));
*m_localAngularManipulators[manipulatorIndex], colors[manipulatorIndex], radius, m_circleBoundWidth, DrawHalfDottedCircle));
}
const float viewAlignedScale = 1.12f;
m_viewAngularManipulator->SetView(CreateManipulatorViewCircle(
*m_viewAngularManipulator, AZ::Color(1.0f, 1.0f, 1.0f, 1.0f), radius + (radius * 0.12f), 0.05f, DrawFullCircle));
*m_viewAngularManipulator, AZ::Color(1.0f, 1.0f, 1.0f, 1.0f), radius * viewAlignedScale, m_circleBoundWidth,
DrawFullCircle));
}
bool RotationManipulators::PerformingActionViewAxis() const
@@ -151,4 +153,9 @@ namespace AzToolsFramework
manipulatorFn(m_viewAngularManipulator.get());
}
void RotationManipulators::SetCircleBoundWidth(const float circleBoundWidth)
{
m_circleBoundWidth = circleBoundWidth;
}
} // namespace AzToolsFramework
@@ -42,6 +42,9 @@ namespace AzToolsFramework
bool PerformingActionViewAxis() const;
//! Sets the bound width to use for the circle (torus) of an angular manipulator.
void SetCircleBoundWidth(float circleBoundWidth);
private:
AZ_DISABLE_COPY_MOVE(RotationManipulators)
@@ -49,5 +52,6 @@ namespace AzToolsFramework
AZStd::array<AZStd::shared_ptr<AngularManipulator>, 3> m_localAngularManipulators;
AZStd::shared_ptr<AngularManipulator> m_viewAngularManipulator;
float m_circleBoundWidth = 0.1f; //!< The default circle bound width for the angular manipulator torus.
};
} // namespace AzToolsFramework
@@ -16,6 +16,79 @@ namespace AzToolsFramework
{
namespace Picking
{
// this intersection algorithm is adapted from 'Capped Cone' by Inigo Quilez
// ref: https://www.iquilezles.org/www/articles/intersectors/intersectors.htm and https://www.shadertoy.com/view/llcfRf
// all algorithms/code snippets are kindly made available under the MIT License - https://www.iquilezles.org/www/index.htm
bool IntersectRayCone(
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZ::Vector3& coneApex,
const AZ::Vector3& coneAxis,
float coneHeight,
float coneBaseRadius,
float& t)
{
const AZ::Vector3& pa = coneApex;
const AZ::Vector3& pb = coneApex + coneHeight * coneAxis;
const AZ::Vector3& ro = rayOrigin;
const AZ::Vector3& rd = rayDirection;
float rb = coneBaseRadius;
AZ::Vector3 ba = pb - pa;
AZ::Vector3 oa = ro - pa;
AZ::Vector3 ob = ro - pb;
float m0 = ba.Dot(ba);
float m1 = oa.Dot(ba);
float m2 = ob.Dot(ba);
float m3 = rd.Dot(ba);
auto dot2 = [](const AZ::Vector3& v)
{
return v.Dot(v);
};
// cap
if (m2 > 0.0f)
{
if (dot2(ob * m3 - rd * m2) < (rb * rb * m3 * m3))
{
t = -m2 / m3;
return true;
}
}
// body
float m4 = rd.Dot(oa);
float m5 = oa.Dot(oa);
float hy = m0 + rb * rb;
float k2 = m0 * m0 - m3 * m3 * hy;
float k1 = m0 * m0 * m4 - m1 * m3 * hy;
float k0 = m0 * m0 * m5 - m1 * m1 * hy;
// note: solving for simultaneously being on the sloping surface of the cone and being on the ray boils down
// to a quadratic equation - the discriminant of the quadratic determines if there are 1, 2 or no solutions
//
// if the discriminant is less than 0 the ray is not intersecting the cone, if it is equal to 0 then the ray
// is intersecting the cone once and if it is greater than 0 the ray is intersecting the cone twice
float discriminant = k1 * k1 - k2 * k0;
if (discriminant < 0.0f)
{
return false;
}
float tt = (-k1 - AZ::Sqrt(discriminant)) / k2;
float y = m1 + tt * m3;
if (y >= 0.0f && y < m0)
{
t = tt;
return true;
}
return false;
}
bool ManipulatorBoundSphere::IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
{
@@ -86,11 +159,10 @@ namespace AzToolsFramework
bool ManipulatorBoundCone::IntersectRay(
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
{
float t1 = std::numeric_limits<float>::max();
float t2 = std::numeric_limits<float>::max();
if (AZ::Intersect::IntersectRayCone(rayOrigin, rayDirection, m_apexPosition, m_dir, m_height, m_radius, t1, t2) > 0)
float t = std::numeric_limits<float>::max();
if (IntersectRayCone(rayOrigin, rayDirection, m_apexPosition, m_dir, m_height, m_radius, t))
{
rayIntersectionDistance = AZStd::GetMin(t1, t2);
rayIntersectionDistance = t;
return true;
}
@@ -23,6 +23,26 @@ namespace AzToolsFramework
{
namespace Picking
{
//! Custom ray/cone intersect function for manipulator bounds to workaround a bug in the current AZ::Intersect implementation.
//! @note Does not give reliable results if the ray origin is inside the cone.
//! @param rayOrigin The origin of the ray to test.
//! @param rayDirection The direction of the ray to test, it must be unit length.
//! @param coneApex The apex of the cone.
//! @param coneAxis The unit-length axis (direction) from the apex to the base.
//! @param coneHeight The height of the cone, from the apex to the base.
//! @param coneBaseRadius The radius of the cone base.
//! @param[out] t A possible coefficient in the ray's explicit equation from which an intersecting point is calculated
//! as "rayOrigin + t * rayDirection". 't' is the closest intersecting point to the ray origin.
//! @return true for intersecting, false for not intersecting.
bool IntersectRayCone(
const AZ::Vector3& rayOrigin,
const AZ::Vector3& rayDirection,
const AZ::Vector3& coneApex,
const AZ::Vector3& coneAxis,
float coneHeight,
float coneBaseRadius,
float& t);
class ManipulatorBoundSphere : public BoundShapeInterface
{
public:
@@ -0,0 +1,46 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/Viewport/ViewportMessages.h>
namespace AzToolsFramework
{
float ManipulatorLineBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/)
{
float lineBoundWidth = 0.0f;
if (viewportId != AzFramework::InvalidViewportId)
{
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
lineBoundWidth, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorLineBoundWidth);
}
else
{
ViewportInteraction::ViewportSettingsRequestBus::BroadcastResult(
lineBoundWidth, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorLineBoundWidth);
}
return lineBoundWidth;
}
float ManipulatorCicleBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/)
{
float circleBoundWidth = 0.0f;
if (viewportId != AzFramework::InvalidViewportId)
{
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
circleBoundWidth, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorCircleBoundWidth);
}
else
{
ViewportInteraction::ViewportSettingsRequestBus::BroadcastResult(
circleBoundWidth, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorCircleBoundWidth);
}
return circleBoundWidth;
}
} // namespace AzToolsFramework
@@ -158,18 +158,6 @@ namespace AzToolsFramework
public:
//! Returns the current camera state for this viewport.
virtual AzFramework::CameraState GetCameraState() = 0;
//! Returns if grid snapping is enabled.
virtual bool GridSnappingEnabled() = 0;
//! Returns the grid snapping size.
virtual float GridSize() = 0;
//! Does the grid currently want to be displayed.
virtual bool ShowGrid() = 0;
//! Returns if angle snapping is enabled.
virtual bool AngleSnappingEnabled() = 0;
//! Returns the angle snapping/step size.
virtual float AngleStep() = 0;
//! Returns the current line bound width for manipulators.
virtual float ManipulatorLineBoundWidth() = 0;
//! Transforms a point in world space to screen space coordinates in Qt Widget space.
//! Multiply by DeviceScalingFactor to get the position in viewport pixel space.
virtual AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) = 0;
@@ -187,12 +175,13 @@ namespace AzToolsFramework
~ViewportInteractionRequests() = default;
};
//! Type to inherit to implement ViewportInteractionRequests.
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
//! Interface to return only viewport specific settings (e.g. snapping).
class ViewportSettings
class ViewportSettingsRequests
{
public:
virtual ~ViewportSettings() = default;
//! Return if grid snapping is enabled.
virtual bool GridSnappingEnabled() const = 0;
//! Return the grid snapping size.
@@ -205,10 +194,15 @@ namespace AzToolsFramework
virtual float AngleStep() const = 0;
//! Returns the current line bound width for manipulators.
virtual float ManipulatorLineBoundWidth() const = 0;
//! Returns the current circle (torus) bound width for manipulators.
virtual float ManipulatorCircleBoundWidth() const = 0;
protected:
~ViewportSettingsRequests() = default;
};
//! Type to inherit to implement ViewportInteractionRequests.
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
//! Type to inherit to implement ViewportSettingsRequests.
using ViewportSettingsRequestBus = AZ::EBus<ViewportSettingsRequests, ViewportEBusTraits>;
//! An interface to notify when changes to viewport settings have happened.
class ViewportSettingNotifications
@@ -346,21 +340,10 @@ namespace AzToolsFramework
}
//! Wrap EBus call to retrieve manipulator line bound width.
//! @note It is possible to pass AzFramework::InvalidViewportId to perform a Broadcast as opposed to a targeted Event.
inline float ManipulatorLineBoundWidth(AzFramework::ViewportId viewportId)
{
float lineBoundWidth = 0.0f;
if (viewportId != AzFramework::InvalidViewportId)
{
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
lineBoundWidth, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ManipulatorLineBoundWidth);
}
else
{
ViewportInteraction::ViewportInteractionRequestBus::BroadcastResult(
lineBoundWidth, &ViewportInteraction::ViewportInteractionRequestBus::Events::ManipulatorLineBoundWidth);
}
//! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event.
float ManipulatorLineBoundWidth(AzFramework::ViewportId viewportId = AzFramework::InvalidViewportId);
return lineBoundWidth;
}
//! Wrap EBus call to retrieve manipulator circle bound width.
//! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event.
float ManipulatorCicleBoundWidth(AzFramework::ViewportId viewportId = AzFramework::InvalidViewportId);
} // namespace AzToolsFramework
@@ -488,8 +488,8 @@ namespace AzToolsFramework
void SnappingCluster::TrySetVisible(const bool visible)
{
bool snapping = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled);
// show snapping viewport ui only if there are entities selected and snapping is enabled
SetViewportUiClusterVisible(m_clusterId, visible && snapping);
@@ -1377,6 +1377,7 @@ namespace AzToolsFramework
AZStd::unique_ptr<RotationManipulators> rotationManipulators =
AZStd::make_unique<RotationManipulators>(AZ::Transform::CreateIdentity());
rotationManipulators->SetCircleBoundWidth(ManipulatorCicleBoundWidth(ViewportUi::DefaultViewportId));
InitializeManipulators(*rotationManipulators);
@@ -2546,8 +2547,8 @@ namespace AzToolsFramework
if (buttonId == m_snappingCluster.m_snapToWorldButtonId)
{
float gridSize = 1.0f;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
gridSize, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
gridSize, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSize);
SnapSelectedEntitiesToWorldGrid(gridSize);
}
@@ -481,6 +481,7 @@ set(FILES
Viewport/VertexContainerDisplay.h
Viewport/VertexContainerDisplay.cpp
Viewport/ViewportMessages.h
Viewport/ViewportMessages.cpp
Viewport/ViewportTypes.h
Viewport/ViewportTypes.cpp
ViewportUi/Button.h
@@ -187,4 +187,51 @@ namespace UnitTest
EXPECT_NEAR(intersectionDistance, 10.0f, g_epsilon);
EXPECT_TRUE(intersection);
}
// replicates a scenario in the Editor using a cone and a pick ray which should have failed but passed with Intersect::IntersectRayCone
TEST(ManipulatorIntersectRayConeTest, RayConeEditorScenarioTest)
{
auto rayOrigin = AZ::Vector3(0.0f, -0.808944702f, 0.0f);
auto rayDir = AZ::Vector3(0.301363617f, 0.939044654f, 0.165454566f);
float t = 0.0f;
bool hit = AzToolsFramework::Picking::IntersectRayCone(
rayOrigin, rayDir, AZ::Vector3(0.0f, 0.0f, 0.161788940f), AZ::Vector3(0.0f, 0.0f, -1.0f), 0.0453009047, 0.0113252262, t);
EXPECT_FALSE(hit);
}
// cone lying flat, ray going towards base of cone
TEST(ManipulatorIntersectRayConeTest, RayIntersectsConeBase)
{
auto rayOrigin = AZ::Vector3::CreateZero();
auto rayDir = AZ::Vector3::CreateAxisY();
float t = 0.0f;
bool hit = AzToolsFramework::Picking::IntersectRayCone(
rayOrigin, rayDir, AZ::Vector3::CreateAxisY(10.0f), AZ::Vector3::CreateAxisY(-1.0f), 5.0f, 1.0f, t);
EXPECT_TRUE(hit);
EXPECT_THAT(t, ::testing::FloatNear(5.0f, 0.0001f));
}
// cone standing up, ray going towards mid side of cone
TEST(ManipulatorIntersectRayConeTest, RayIntersectsConeSide)
{
auto rayOrigin = AZ::Vector3::CreateZero();
auto rayDir = AZ::Vector3::CreateAxisY();
float t = 0.0f;
bool hit = AzToolsFramework::Picking::IntersectRayCone(
rayOrigin, rayDir, AZ::Vector3(0.0f, 10.0f, 5.0f), AZ::Vector3::CreateAxisZ(-1.0f), 10.0f, 5.0f, t);
EXPECT_TRUE(hit);
EXPECT_THAT(t, ::testing::FloatNear(7.5f, 0.0001f));
}
// cone standing up, ray going towards mid side of cone
TEST(ManipulatorIntersectRayConeTest, RayIntersectsConeApex)
{
auto rayOrigin = AZ::Vector3::CreateZero();
auto rayDir = AZ::Vector3::CreateAxisY();
float t = 0.0f;
bool hit = AzToolsFramework::Picking::IntersectRayCone(
rayOrigin, rayDir, AZ::Vector3::CreateAxisY(2.5f), AZ::Vector3::CreateAxisY(1.0f), 5.0f, 1.0f, t);
EXPECT_TRUE(hit);
EXPECT_THAT(t, ::testing::FloatNear(2.5f, 0.0001f));
}
} // namespace UnitTest