diff --git a/Source/Engine/Core/Math/Quaternion.cs b/Source/Engine/Core/Math/Quaternion.cs index 86a6e4e2d..b69df3969 100644 --- a/Source/Engine/Core/Math/Quaternion.cs +++ b/Source/Engine/Core/Math/Quaternion.cs @@ -1479,6 +1479,47 @@ namespace FlaxEngine return results; } + /// + /// Gets rotacion for normal in relation to transform
+ /// Funcion especially created for aligned with axis aligned faces + /// use full with + /// + /// Example code: + /// + /// GetRotacionFromNormalExample :
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// position = Hit.Collider.Position; + /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// rot = .GetRotacionFromNormal(normal,transform); + /// SomeObject.Position = point; + /// SomeObject.Orientation = rot; + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// the normal vector + /// relative to + /// normal as rotacion + public static Quaternion GetRotacionFromNormal(Vector3 InNormal, Transform InRefrenceTransform) + { + Float3 up = InRefrenceTransform.Up; + var dot = Vector3.Dot(InNormal, up); + if (Mathf.NearEqual(Math.Abs(dot), 1)) + { + up = InRefrenceTransform.Right; + } + return Quaternion.LookRotation(InNormal, up); + } + /// /// Adds two quaternions. /// diff --git a/Source/Engine/Core/Math/Quaternion.h b/Source/Engine/Core/Math/Quaternion.h index 0790dcbfb..2f2c538a6 100644 --- a/Source/Engine/Core/Math/Quaternion.h +++ b/Source/Engine/Core/Math/Quaternion.h @@ -660,6 +660,27 @@ public: // @param roll The roll of rotation (in radians) // @param result When the method completes, contains the newly created quaternion static void RotationYawPitchRoll(float yaw, float pitch, float roll, Quaternion& result); + + + /// + /// Gets rotacion for normal in relation to transform
+ /// Funcion especially created for aligned with axis aligned faces + /// use full with + ///
+ /// the normal vector + /// relative to + /// normal as rotacion + static Quaternion GetRotacionFromNormal(const Vector3& InNormal, const Transform& InRefrenceTransform) + { + Float3 up = InRefrenceTransform.GetUp(); + auto dot = Vector3::Dot(InNormal, up); + if (Math::NearEqual(Math::Abs(dot), 1)) + { + up = InRefrenceTransform.GetRight(); + } + return Quaternion::LookRotation(InNormal, up); + } + }; /// diff --git a/Source/Engine/Core/Math/Transform.cs b/Source/Engine/Core/Math/Transform.cs index e00265f6d..844625514 100644 --- a/Source/Engine/Core/Math/Transform.cs +++ b/Source/Engine/Core/Math/Transform.cs @@ -477,6 +477,187 @@ namespace FlaxEngine Quaternion.Slerp(ref start.Orientation, ref end.Orientation, amount, out result.Orientation); Float3.Lerp(ref start.Scale, ref end.Scale, amount, out result.Scale); } + /// + /// combines funcions
+ /// ,
+ /// + /// Example code: + /// + /// AlignRotacionToObjectAndSnapToGridExample :
+ /// Offset = 50.0f;
+ /// GridSize = * 20.0f;
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// SomeObject.Transform = .AlignRotacionToNormalAndSnapToGrid + /// ( + /// point, + /// normal, + /// Offset, + /// transform, + /// SomeObject.Scale, + /// GridSize + /// ); + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// The position to snap. + /// The size of the grid. + /// The local Z grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// return scale + /// InRefrenceTransform + /// rotated and snaped transform + public static Transform AlignRotacionToNormalAndSnapToGrid(Vector3 InPoint, Vector3 InNormal, float InNormalOffset, Transform InRelativeTo, Float3 InReturnScale, Vector3 InGridSize) + { + Quaternion rot = Quaternion.GetRotacionFromNormal(InNormal, InRelativeTo); + return new Transform(Vector3.SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, new Vector3(0, 0, InNormalOffset), rot, InGridSize), rot, InReturnScale); + } + /// + /// combines funcions
+ /// ,
+ /// + /// Example code: + /// + /// AlignRotacionToObjectAndSnapToGridExample :
+ /// Offset = 50.0f;
+ /// GridSize = * 20.0f;
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// SomeObject.Transform = .AlignRotacionToNormalAndSnapToGrid + /// ( + /// point, + /// normal, + /// Offset, + /// transform, + /// GridSize + /// ); + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// The position to snap. + /// The size of the grid. + /// The local Z grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// InRefrenceTransform + /// rotated and snaped transform with scale + public static Transform AlignRotacionToNormalAndSnapToGrid(Vector3 InPoint, Vector3 InNormal, float InNormalOffset, Transform InRelativeTo, Vector3 InGridSize) + { + Quaternion rot = Quaternion.GetRotacionFromNormal(InNormal, InRelativeTo); + return new Transform(Vector3.SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, new Vector3(0, 0, InNormalOffset), rot, InGridSize), rot, Float3.One); + } + /// + /// combines funcions
+ /// ,
+ /// + /// Example code: + /// + /// AlignRotacionToObjectAndSnapToGridExample :
+ /// Offset = new Vector3(0, 0, 50f);
+ /// GridSize = * 20.0f;
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// SomeObject.Transform = .AlignRotacionToNormalAndSnapToGrid + /// ( + /// point, + /// normal, + /// Offset, + /// transform, + /// SomeObject.Scale, + /// GridSize + /// ); + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// The position to snap. + /// The size of the grid. + /// The local Z grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// return scale + /// InRefrenceTransform + /// rotated and snaped transform + public static Transform AlignRotacionToNormalAndSnapToGrid(Vector3 InPoint, Vector3 InNormal, Vector3 InNormalOffset, Transform InRelativeTo, Float3 InReturnScale, Vector3 InGridSize) + { + Quaternion rot = Quaternion.GetRotacionFromNormal(InNormal, InRelativeTo); + return new Transform(Vector3.SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, InNormalOffset, rot, InGridSize), rot, InReturnScale); + } + + /// + /// combines funcions
+ /// ,
+ /// + /// Example code: + /// + /// AlignRotacionToObjectAndSnapToGridExample :
+ /// Offset = new Vector3(0, 0, 50f);
+ /// GridSize = * 20.0f;
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// SomeObject.Transform = .AlignRotacionToNormalAndSnapToGrid + /// ( + /// point, + /// normal, + /// Offset, + /// transform, + /// GridSize + /// ); + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// The position to snap. + /// The size of the grid. + /// The local grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// InRefrenceTransform + /// rotated and snaped transform with scale + public static Transform AlignRotacionToNormalAndSnapToGrid(Vector3 InPoint, Vector3 InNormal, Vector3 InNormalOffset, Transform InRelativeTo, Vector3 InGridSize) + { + Quaternion rot = Quaternion.GetRotacionFromNormal(InNormal, InRelativeTo); + return new Transform(Vector3.SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, InNormalOffset, rot, InGridSize), rot, Float3.One); + } /// /// Tests for equality between two objects. diff --git a/Source/Engine/Core/Math/Transform.h b/Source/Engine/Core/Math/Transform.h index 2c51bfa4a..a54c356db 100644 --- a/Source/Engine/Core/Math/Transform.h +++ b/Source/Engine/Core/Math/Transform.h @@ -291,6 +291,77 @@ public: return result; } + /// + /// combines funcions
+ /// ,
+ /// + ///
+ /// The position to snap. + /// The size of the grid. + /// The local Z grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// return scale + /// InRefrenceTransform + /// rotated and snaped transform + static Transform AlignRotacionToNormalAndSnapToGrid(const Vector3& InPoint, const Vector3& InNormal, float InNormalOffset, const Transform& InRelativeTo, const Float3& InReturnScale, const Vector3& InGridSize) + { + Quaternion rot = Quaternion::GetRotacionFromNormal(InNormal, InRelativeTo); + return Transform(Vector3::SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, Vector3(0, 0, InNormalOffset), rot, InGridSize), rot, InReturnScale); + } + /// + /// combines funcions
+ /// ,
+ /// + ///
+ /// The position to snap. + /// The size of the grid. + /// The local Z grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// InRefrenceTransform + /// rotated and snaped transform with scale + static Transform AlignRotacionToNormalAndSnapToGrid(const Vector3& InPoint, const Vector3& InNormal, float InNormalOffset, const Transform& InRelativeTo, const Vector3& InGridSize) + { + Quaternion rot = Quaternion::GetRotacionFromNormal(InNormal, InRelativeTo); + return Transform(Vector3::SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, Vector3(0, 0, InNormalOffset), rot, InGridSize), rot, Float3::One); + } + /// + /// combines funcions
+ /// ,
+ /// + ///
+ /// The position to snap. + /// The size of the grid. + /// The local Z grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// return scale + /// InRefrenceTransform + /// rotated and snaped transform + static Transform AlignRotacionToNormalAndSnapToGrid(const Vector3& InPoint, const Vector3& InNormal, const Vector3& InNormalOffset, const Transform& InRelativeTo,const Float3& InReturnScale,const Vector3& InGridSize) + { + Quaternion rot = Quaternion::GetRotacionFromNormal(InNormal, InRelativeTo); + return Transform(Vector3::SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, InNormalOffset, rot, InGridSize), rot, InReturnScale); + } + /// + /// combines funcions
+ /// ,
+ /// + ///
+ /// The position to snap. + /// The size of the grid. + /// The local grid offset to applay after snaping + /// Normal vector + /// Realative transform + /// InRefrenceTransform + /// rotated and snaped transform with scale + static Transform AlignRotacionToNormalAndSnapToGrid(const Vector3& InPoint,const Vector3& InNormal,const Vector3& InNormalOffset, const Transform& InRelativeTo,const Vector3& InGridSize) + { + Quaternion rot = Quaternion::GetRotacionFromNormal(InNormal, InRelativeTo); + return Transform(Vector3::SnapToRotatedGridWithOffset(InPoint, InRelativeTo.Translation, InNormalOffset, rot, InGridSize), rot, Float3::One); + } + public: FORCE_INLINE Transform operator*(const Transform& other) const { diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs index 848a3b532..9cda11544 100644 --- a/Source/Engine/Core/Math/Vector3.cs +++ b/Source/Engine/Core/Math/Vector3.cs @@ -1685,6 +1685,80 @@ namespace FlaxEngine return pos; } + /// + /// Snaps the on to rotate grid.
+ /// for world aligned grid snapping use instead + /// Example code: + /// + /// SnapToRotatedGridExample :
+ /// GridSize = * 20.0f;
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// position = Hit.Collider.Position; + /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// //Get rotation from normal relative to collider transform + /// rot = .GetRotacionFromNormal(normal,transform); + /// point = .SnapToRotatedGrid(point,position,rot,GridSize); + /// SomeObject.Position = point; + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// The position to snap. + /// The center point. + /// The rotation of the grid. + /// The size of the grid. + /// The position snapped to the grid. + public static Vector3 SnapToRotatedGrid(Vector3 InPoint, Vector3 InCenterPoint, Quaternion InOrientation, Vector3 InGridSize) + { + Vector3 p = (InPoint - InCenterPoint) * InOrientation.Conjugated(); + return (SnapToGrid(p, InGridSize) * InOrientation) + InCenterPoint; + } + /// + /// The same as but with local offset applied after point is spapend + /// Example code: + /// + /// SnapToRotatedGridWithOffsetExample :
+ /// Offset = new Vector3(0, 0, 50f);
+ /// GridSize = * 20.0f;
+ /// RayOrgin;
+ /// SomeObject;
+ ///
+ /// {
+ /// (.RayCast(RayOrgin.Position, RayOrgin.Transform.Forward, out Hit) + /// {
+ /// position = Hit.Collider.Position; + /// transform = Hit.Collider.Transform; + /// point = Hit.Point; + /// normal = Hit.Normal; + /// rot = .GetRotacionFromNormal(normal,transform); + /// point = .SnapToRotatedGridWithOffset(point,position,Offset,rot,GridSize); + /// SomeObject.Position = point; + /// } + /// } + /// } + ///
+ ///
+ ///
+ /// The position to snap. + /// The center point. + /// The rotation of the grid. + /// The size of the grid. + /// The local grid offset to applay after snaping + /// + public static Vector3 SnapToRotatedGridWithOffset(Vector3 InPoint, Vector3 InCenterPoint, Vector3 InOffset, Quaternion InOrientation, Vector3 InGridSize) + { + return ((SnapToGrid((InPoint - InCenterPoint) * InOrientation.Conjugated(), InGridSize) + InOffset) * InOrientation) + InCenterPoint; + } + /// /// Adds two vectors. /// diff --git a/Source/Engine/Core/Math/Vector3.h b/Source/Engine/Core/Math/Vector3.h index 950d730c5..b8f074b73 100644 --- a/Source/Engine/Core/Math/Vector3.h +++ b/Source/Engine/Core/Math/Vector3.h @@ -927,6 +927,47 @@ public: /// The second vector. /// The angle (in radians). static FLAXENGINE_API T Angle(const Vector3Base& from, const Vector3Base& to); + + /// + /// Snaps the input position into the grid. + /// + /// The position to snap. + /// The size of the grid. + /// The position snapped to the grid. + static Vector3 SnapToGrid(const Vector3& pos, Vector3 gridSize) + { + pos.X = Math::Ceil((pos.X - (gridSize.X * 0.5f)) / gridSize.X) * gridSize.X; + pos.Y = Math::Ceil((pos.Y - (gridSize.Y * 0.5f)) / gridSize.Y) * gridSize.Y; + pos.Z = Math::Ceil((pos.Z - (gridSize.Z * 0.5f)) / gridSize.Z) * gridSize.Z; + return pos; + } + + /// + /// Snaps the on to rotate grid.
+ /// for world aligned grid snapping use instead + ///
+ /// The position to snap. + /// The center point. + /// The rotation of the grid. + /// The size of the grid. + /// The position snapped to the grid. + static Vector3 SnapToRotatedGrid(const Vector3& InPoint, const Vector3& InCenterPoint, const Quaternion& InOrientation, const Vector3& InGridSize) + { + return (Vector3::SnapToGrid((InPoint - InCenterPoint) * InOrientation.Conjugated(), InGridSize) * InOrientation) + InCenterPoint; + } + /// + /// The same as but with local offset applied after point is spapend + /// + /// The position to snap. + /// The center point. + /// The rotation of the grid. + /// The size of the grid. + /// The local grid offset to applay after snaping + /// + static Vector3 SnapToRotatedGridWithOffset(const Vector3& InPoint, const Vector3& InCenterPoint, const Vector3& InOffset, const Quaternion& InOrientation, const Vector3& InGridSize) + { + return ((Vector3::SnapToGrid((InPoint - InCenterPoint) * InOrientation.Conjugated(), InGridSize) + InOffset) * InOrientation) + InCenterPoint; + } }; template