diff --git a/Source/Engine/CSG/Brush.h b/Source/Engine/CSG/Brush.h index 9df960e46..e3f184a9a 100644 --- a/Source/Engine/CSG/Brush.h +++ b/Source/Engine/CSG/Brush.h @@ -31,7 +31,7 @@ namespace CSG Surface() : Plane() , TexCoordScale(1) - , TexCoordOffset(0) + , TexCoordOffset(0.0f) , TexCoordRotation(0) , ScaleInLightmap(1) { @@ -41,7 +41,7 @@ namespace CSG : Plane(plane) , Material(Guid::Empty) , TexCoordScale(1) - , TexCoordOffset(0) + , TexCoordOffset(0.0f) , TexCoordRotation(0) , ScaleInLightmap(1) { @@ -51,7 +51,7 @@ namespace CSG : Plane(plane) , Material(plane.Material) , TexCoordScale(1) - , TexCoordOffset(0) + , TexCoordOffset(0.0f) , TexCoordRotation(0) , ScaleInLightmap(1) { @@ -61,7 +61,7 @@ namespace CSG : Plane(normal, d) , Material(Guid::Empty) , TexCoordScale(1) - , TexCoordOffset(0) + , TexCoordOffset(0.0f) , TexCoordRotation(0) , ScaleInLightmap(1) { @@ -71,7 +71,7 @@ namespace CSG : Plane(point1, point2, point3) , Material(Guid::Empty) , TexCoordScale(1) - , TexCoordOffset(0) + , TexCoordOffset(0.0f) , TexCoordRotation(0) , ScaleInLightmap(1) { diff --git a/Source/Engine/CSG/CSGBuilder.cpp b/Source/Engine/CSG/CSGBuilder.cpp index 0969ea1e5..a912168b7 100644 --- a/Source/Engine/CSG/CSGBuilder.cpp +++ b/Source/Engine/CSG/CSGBuilder.cpp @@ -46,7 +46,6 @@ using namespace CSGBuilderImpl; class CSGBuilderService : public EngineService { public: - CSGBuilderService() : EngineService(TEXT("CSG Builder"), 90) { @@ -336,7 +335,8 @@ bool CSGBuilderImpl::buildInner(Scene* scene, BuildData& data) for (int32 meshIndex = 0; meshIndex < lod->Meshes.Count(); meshIndex++) { const auto v = &lod->Meshes[meshIndex]->Positions; - Vector3::Transform(v->Get(), m2, v->Get(), v->Count()); + for (int32 i = 0; i < v->Count(); i++) + Vector3::Transform(v->Get()[i], m2, v->Get()[i]); } } } diff --git a/Source/Engine/Core/Math/CollisionsHelper.h b/Source/Engine/Core/Math/CollisionsHelper.h index 44c2373e7..d55513f98 100644 --- a/Source/Engine/Core/Math/CollisionsHelper.h +++ b/Source/Engine/Core/Math/CollisionsHelper.h @@ -2,15 +2,7 @@ #pragma once -struct Vector2; -struct Vector3; -struct Vector4; -struct Ray; -struct Plane; -struct Rectangle; -struct BoundingBox; -struct BoundingSphere; -struct BoundingFrustum; +#include "Engine/Core/Types/BaseTypes.h" /// /// Describes how one bounding volume contains another. diff --git a/Source/Engine/Core/Math/Color.h b/Source/Engine/Core/Math/Color.h index 937fba0e9..4024cb2ed 100644 --- a/Source/Engine/Core/Math/Color.h +++ b/Source/Engine/Core/Math/Color.h @@ -6,9 +6,6 @@ #include "Engine/Core/Math/Math.h" #include "Engine/Core/Templates.h" -class String; -struct Vector3; -struct Vector4; struct Color32; /// diff --git a/Source/Engine/Core/Math/Color32.h b/Source/Engine/Core/Math/Color32.h index 09ccfe426..e10e6d2e7 100644 --- a/Source/Engine/Core/Math/Color32.h +++ b/Source/Engine/Core/Math/Color32.h @@ -5,9 +5,6 @@ #include "Engine/Core/Formatting.h" #include "Engine/Core/Templates.h" -class String; -struct Vector3; -struct Vector4; struct Color; /// diff --git a/Source/Engine/Core/Math/Double2.cpp b/Source/Engine/Core/Math/Double2.cpp deleted file mode 100644 index bcd80084d..000000000 --- a/Source/Engine/Core/Math/Double2.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "Double2.h" -#include "Double3.h" -#include "Double4.h" -#include "Vector2.h" -#include "Vector3.h" -#include "Vector4.h" -#include "Color.h" -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" -#include "../Types/String.h" - -static_assert(sizeof(Double2) == 16, "Invalid Double2 type size."); - -const Double2 Double2::Zero(0.0); -const Double2 Double2::One(1.0); -const Double2 Double2::UnitX(1.0, 0.0); -const Double2 Double2::UnitY(0.0, 1.0); -const Double2 Double2::Minimum(MIN_double); -const Double2 Double2::Maximum(MAX_double); - -Double2::Double2(const Int2& xy) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) -{ -} - -Double2::Double2(const Int3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) -{ -} - -Double2::Double2(const Int4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) -{ -} - -Double2::Double2(const Vector2& xy) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) -{ -} - -Double2::Double2(const Vector3& xyz) - : X(xyz.X) - , Y(xyz.Y) -{ -} - -Double2::Double2(const Vector4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) -{ -} - -Double2::Double2(const Double3& xyz) - : X(xyz.X) - , Y(xyz.Y) -{ -} - -Double2::Double2(const Double4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) -{ -} - -Double2::Double2(const Color& color) - : X(color.R) - , Y(color.G) -{ -} - -String Double2::ToString() const -{ - return String::Format(TEXT("{}"), *this); -} - -Double2 Double2::Normalize(const Double2& v) -{ - Double2 result = v; - const double length = v.Length(); - if (!Math::IsZero(length)) - { - const double inv = 1. / length; - result.X *= inv; - result.Y *= inv; - } - return result; -} - -Int2 Double2::CeilToInt(const Double2& v) -{ - return Int2((int32)Math::CeilToInt(v.X), (int32)Math::CeilToInt(v.Y)); -} - -Int2 Double2::FloorToInt(const Double2& v) -{ - return Int2((int32)Math::FloorToInt(v.X), (int32)Math::FloorToInt(v.Y)); -} - -double Double2::TriangleArea(const Double2& v0, const Double2& v1, const Double2& v2) -{ - return Math::Abs((v0.X * (v1.Y - v2.Y) + v1.X * (v2.Y - v0.Y) + v2.X * (v0.Y - v1.Y)) / 2.); -} - -double Double2::Angle(const Double2& from, const Double2& to) -{ - const double dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0, 1.0); - if (Math::Abs(dot) > (1.0 - ZeroTolerance)) - return dot > 0.0 ? 0.0 : PI; - return Math::Acos(dot); -} diff --git a/Source/Engine/Core/Math/Double2.h b/Source/Engine/Core/Math/Double2.h index 3e57e332c..a814bbed4 100644 --- a/Source/Engine/Core/Math/Double2.h +++ b/Source/Engine/Core/Math/Double2.h @@ -2,625 +2,4 @@ #pragma once -#include "Math.h" -#include "Mathd.h" -#include "Engine/Core/Formatting.h" -#include "Engine/Core/Templates.h" - -struct Double3; -struct Double4; -struct Vector2; -struct Vector3; -struct Vector4; -struct Int2; -struct Int3; -struct Int4; -struct Color; -struct Matrix; - -/// -/// Represents a two dimensional mathematical vector with 64-bit precision (per-component). -/// -API_STRUCT() struct FLAXENGINE_API Double2 -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(Double2); -public: - union - { - struct - { - /// - /// The X component of the vector. - /// - API_FIELD() double X; - - /// - /// The Y component of the vector. - /// - API_FIELD() double Y; - }; - - // Raw values - double Raw[2]; - }; - -public: - // Vector with all components equal 0 - static const Double2 Zero; - - // Vector with all components equal 1 - static const Double2 One; - - // Vector X=1, Y=0 - static const Double2 UnitX; - - // Vector X=0, Y=1 - static const Double2 UnitY; - - // A minimum Double2 - static const Double2 Minimum; - - // A maximum Double2 - static const Double2 Maximum; - -public: - /// - /// Empty constructor. - /// - Double2() - { - } - - // Init - // @param xy Value to assign to the all components - Double2(double xy) - : X(xy) - , Y(xy) - { - } - - // Init - // @param x X component value - // @param y Y component value - Double2(double x, double y) - : X(x) - , Y(y) - { - } - - /// - /// Init - /// - /// X and Z components in an array - explicit Double2(double xy[2]) - : X(xy[0]) - , Y(xy[1]) - { - } - - explicit Double2(const Int2& xy); - explicit Double2(const Int3& xyz); - explicit Double2(const Int4& xyzw); - Double2(const Vector2& xy); - explicit Double2(const Vector3& xyz); - explicit Double2(const Vector4& xyzw); - explicit Double2(const Double3& xyz); - explicit Double2(const Double4& xyzw); - explicit Double2(const Color& color); - -public: - String ToString() const; - -public: - // Arithmetic operators with Double2 - Double2 operator+(const Double2& b) const - { - return Add(*this, b); - } - - Double2 operator-(const Double2& b) const - { - return Subtract(*this, b); - } - - Double2 operator*(const Double2& b) const - { - return Multiply(*this, b); - } - - Double2 operator/(const Double2& b) const - { - return Divide(*this, b); - } - - Double2 operator-() const - { - return Double2(-X, -Y); - } - - // op= operators with Double2 - Double2& operator+=(const Double2& b) - { - *this = Add(*this, b); - return *this; - } - - Double2& operator-=(const Double2& b) - { - *this = Subtract(*this, b); - return *this; - } - - Double2& operator*=(const Double2& b) - { - *this = Multiply(*this, b); - return *this; - } - - Double2& operator/=(const Double2& b) - { - *this = Divide(*this, b); - return *this; - } - - // Arithmetic operators with double - Double2 operator+(double b) const - { - return Add(*this, b); - } - - Double2 operator-(double b) const - { - return Subtract(*this, b); - } - - Double2 operator*(double b) const - { - return Multiply(*this, b); - } - - Double2 operator/(double b) const - { - return Divide(*this, b); - } - - // op= operators with double - Double2& operator+=(double b) - { - *this = Add(*this, b); - return *this; - } - - Double2& operator-=(double b) - { - *this = Subtract(*this, b); - return *this; - } - - Double2& operator*=(double b) - { - *this = Multiply(*this, b); - return *this; - } - - Double2& operator/=(double b) - { - *this = Divide(*this, b); - return *this; - } - - // Comparison operators - bool operator==(const Double2& b) const - { - return X == b.X && Y == b.Y; - } - - bool operator!=(const Double2& b) const - { - return X != b.X || Y != b.Y; - } - - bool operator>(const Double2& b) const - { - return X > b.X && Y > b.Y; - } - - bool operator>=(const Double2& b) const - { - return X >= b.X && Y >= b.Y; - } - - bool operator<(const Double2& b) const - { - return X < b.X && Y < b.Y; - } - - bool operator<=(const Double2& b) const - { - return X <= b.X && Y <= b.Y; - } - -public: - static bool NearEqual(const Double2& a, const Double2& b) - { - return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y); - } - - static bool NearEqual(const Double2& a, const Double2& b, double epsilon) - { - return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon); - } - -public: - static double Dot(const Double2& a, const Double2& b) - { - return a.X * b.X + a.Y * b.Y; - } - - static double Cross(const Double2& a, const Double2& b) - { - return a.X * b.Y - a.Y * b.X; - } - - static void Add(const Double2& a, const Double2& b, Double2& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - } - - static Double2 Add(const Double2& a, const Double2& b) - { - Double2 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Double2& a, const Double2& b, Double2& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - } - - static Double2 Subtract(const Double2& a, const Double2& b) - { - Double2 result; - Subtract(a, b, result); - return result; - } - - static Double2 Multiply(const Double2& a, const Double2& b) - { - return Double2(a.X * b.X, a.Y * b.Y); - } - - static Double2 Multiply(const Double2& a, double b) - { - return Double2(a.X * b, a.Y * b); - } - - static Double2 Divide(const Double2& a, const Double2& b) - { - return Double2(a.X / b.X, a.Y / b.Y); - } - - static Double2 Divide(const Double2& a, double b) - { - return Double2(a.X / b, a.Y / b); - } - - // Calculates distance between two points in 2D - // @param a 1st point - // @param b 2nd point - // @returns Distance - static double Distance(const Double2& a, const Double2& b) - { - const double x = a.X - b.X; - const double y = a.Y - b.Y; - return Math::Sqrt(x * x + y * y); - } - - // Calculates the squared distance between two points in 2D - // @param a 1st point - // @param b 2nd point - // @returns Distance - static double DistanceSquared(const Double2& a, const Double2& b) - { - const double x = a.X - b.X; - const double y = a.Y - b.Y; - return x * x + y * y; - } - - // Clamp vector values within given range - // @param v Vector to clamp - // @param min Minimum value - // @param max Maximum value - // @returns Clamped vector - static Double2 Clamp(const Double2& v, double min, double max) - { - return Double2(Math::Clamp(v.X, min, max), Math::Clamp(v.Y, min, max)); - } - - // Clamp vector values within given range - // @param v Vector to clamp - // @param min Minimum value - // @param max Maximum value - // @returns Clamped vector - static Double2 Clamp(const Double2& v, const Double2& min, const Double2& max) - { - return Double2(Math::Clamp(v.X, min.X, max.X), Math::Clamp(v.Y, min.Y, max.Y)); - } - - // Performs vector normalization (scales vector up to unit length) - void Normalize() - { - const double length = Length(); - if (!Math::IsZero(length)) - { - const double invLength = 1.0 / length; - X *= invLength; - Y *= invLength; - } - } - -public: - // Gets a value indicting whether this instance is normalized. - bool IsNormalized() const - { - return Math::IsOne(X * X + Y * Y); - } - - // Gets a value indicting whether this vector is zero. - bool IsZero() const - { - return Math::IsZero(X) && Math::IsZero(Y); - } - - // Gets a value indicting whether any vector component is zero. - bool IsAnyZero() const - { - return Math::IsZero(X) || Math::IsZero(Y); - } - - // Gets a value indicting whether this vector is zero. - bool IsOne() const - { - return Math::IsOne(X) && Math::IsOne(Y); - } - - // Calculates length of the vector. - double Length() const - { - return Math::Sqrt(X * X + Y * Y); - } - - // Calculates the squared length of the vector. - double LengthSquared() const - { - return X * X + Y * Y; - } - - // Calculates inverted length of the vector (1 / length). - double InvLength() const - { - return 1. / Length(); - } - - // Calculates a vector with values being absolute values of that vector. - Double2 GetAbsolute() const - { - return Double2(Math::Abs(X), Math::Abs(Y)); - } - - // Calculates a vector with values being opposite to values of that vector. - Double2 GetNegative() const - { - return Double2(-X, -Y); - } - - /// - /// Returns the average arithmetic of all the components. - /// - double AverageArithmetic() const - { - return (X + Y) * 0.5; - } - - /// - /// Gets the sum of all vector components values. - /// - double SumValues() const - { - return X + Y; - } - - /// - /// Gets the multiplication result of all vector components values. - /// - double MulValues() const - { - return X * Y; - } - - /// - /// Returns the minimum value of all the components. - /// - double MinValue() const - { - return Math::Min(X, Y); - } - - /// - /// Returns the maximum value of all the components. - /// - double MaxValue() const - { - return Math::Max(X, Y); - } - - /// - /// Returns true if vector has one or more components is not a number (NaN). - /// - bool IsNaN() const - { - return isnan(X) || isnan(Y); - } - - /// - /// Returns true if vector has one or more components equal to +/- infinity. - /// - bool IsInfinity() const - { - return isinf(X) || isinf(Y); - } - - /// - /// Returns true if vector has one or more components equal to +/- infinity or NaN. - /// - bool IsNanOrInfinity() const - { - return IsInfinity() || IsNaN(); - } - -public: - // Performs a linear interpolation between two vectors - // @param start Start vector - // @param end End vector - // @param amount Value between 0 and 1 indicating the weight of end - // @param result When the method completes, contains the linear interpolation of the two vectors - static void Lerp(const Double2& start, const Double2& end, double amount, Double2& result) - { - result.X = Math::Lerp(start.X, end.X, amount); - result.Y = Math::Lerp(start.Y, end.Y, amount); - } - - // - // Performs a linear interpolation between two vectors. - // - // @param start Start vector, - // @param end End vector, - // @param amount Value between 0 and 1 indicating the weight of @paramref end"/>, - // @returns The linear interpolation of the two vectors - static Double2 Lerp(const Double2& start, const Double2& end, double amount) - { - Double2 result; - Lerp(start, end, amount, result); - return result; - } - - static Double2 Abs(const Double2& v) - { - return Double2(Math::Abs(v.X), Math::Abs(v.Y)); - } - - // Creates vector from minimum components of two vectors - static Double2 Min(const Double2& a, const Double2& b) - { - return Double2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); - } - - // Creates vector from minimum components of two vectors - static void Min(const Double2& a, const Double2& b, Double2& result) - { - result = Double2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); - } - - // Creates vector from maximum components of two vectors - static Double2 Max(const Double2& a, const Double2& b) - { - return Double2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); - } - - // Creates vector from maximum components of two vectors - static void Max(const Double2& a, const Double2& b, Double2& result) - { - result = Double2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); - } - - // Returns normalized vector - static Double2 Normalize(const Double2& v); - - static Double2 Round(const Double2& v) - { - return Double2(Math::Round(v.X), Math::Round(v.Y)); - } - - static Double2 Ceil(const Double2& v) - { - return Double2(Math::Ceil(v.X), Math::Ceil(v.Y)); - } - - static Double2 Floor(const Double2& v) - { - return Double2(Math::Floor(v.X), Math::Floor(v.Y)); - } - - static Double2 Frac(const Double2& v) - { - return Double2(v.X - (int64)v.X, v.Y - (int64)v.Y); - } - - static Int2 CeilToInt(const Double2& v); - static Int2 FloorToInt(const Double2& v); - - static Double2 Mod(const Double2& v) - { - return Double2( - v.X - (int64)v.X, - v.Y - (int64)v.Y - ); - } - -public: - /// - /// Calculates the area of the triangle. - /// - /// The first triangle vertex. - /// The second triangle vertex. - /// The third triangle vertex. - /// The triangle area. - static double TriangleArea(const Double2& v0, const Double2& v1, const Double2& v2); - - /// - /// Calculates the angle (in radians) between from and to. This is always the smallest value. - /// - /// The first vector. - /// The second vector. - /// The angle (in radians). - static double Angle(const Double2& from, const Double2& to); -}; - -inline Double2 operator+(double a, const Double2& b) -{ - return b + a; -} - -inline Double2 operator-(double a, const Double2& b) -{ - return Double2(a) - b; -} - -inline Double2 operator*(double a, const Double2& b) -{ - return b * a; -} - -inline Double2 operator/(double a, const Double2& b) -{ - return Double2(a) / b; -} - -namespace Math -{ - FORCE_INLINE static bool NearEqual(const Double2& a, const Double2& b) - { - return Double2::NearEqual(a, b); - } -} - -template<> -struct TIsPODType -{ - enum { Value = true }; -}; - -DEFINE_DEFAULT_FORMATTING(Double2, "X:{0} Y:{1}", v.X, v.Y); +#include "Vector2.h" diff --git a/Source/Engine/Core/Math/Double3.cpp b/Source/Engine/Core/Math/Double3.cpp deleted file mode 100644 index a64c94c53..000000000 --- a/Source/Engine/Core/Math/Double3.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "Double2.h" -#include "Double3.h" -#include "Double4.h" -#include "Vector2.h" -#include "Vector3.h" -#include "Vector4.h" -#include "Quaternion.h" -#include "Matrix.h" -#include "Color.h" -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" -#include "../Types/String.h" - -static_assert(sizeof(Double3) == 24, "Invalid Double3 type size."); - -const Double3 Double3::Zero(0.0); -const Double3 Double3::One(1.0); -const Double3 Double3::Half(0.5); -const Double3 Double3::UnitX(1.0, 0.0, 0.0); -const Double3 Double3::UnitY(0.0, 1.0, 0.0); -const Double3 Double3::UnitZ(0.0, 0.0, 1.0); -const Double3 Double3::Up(0.0, 1.0, 0.0); -const Double3 Double3::Down(0.0, -1.0, 0.0); -const Double3 Double3::Left(-1.0, 0.0, 0.0); -const Double3 Double3::Right(1.0, 0.0, 0.0); -const Double3 Double3::Forward(0.0, 0.0, 1.0); -const Double3 Double3::Backward(0.0, 0.0, -1.0); -const Double3 Double3::Minimum(MIN_double); -const Double3 Double3::Maximum(MAX_double); - -Double3::Double3(const Vector2& xy, double z) - : X(xy.X) - , Y(xy.Y) - , Z(z) -{ -} - -Double3::Double3(const Vector2& xy) - : X(xy.X) - , Y(xy.Y) - , Z(0) -{ -} - -Double3::Double3(const Vector3& xyz) - : X(xyz.X) - , Y(xyz.Y) - , Z(xyz.Z) -{ -} - -Double3::Double3(const Vector4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) - , Z(xyzw.Z) -{ -} - -Double3::Double3(const Int2& xy, double z) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) - , Z(z) -{ -} - -Double3::Double3(const Int3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) -{ -} - -Double3::Double3(const Int4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.Z)) -{ -} - -Double3::Double3(const Double2& xy) - : X(xy.X) - , Y(xy.Y) - , Z(0) -{ -} - -Double3::Double3(const Double2& xy, double z) - : X(xy.X) - , Y(xy.Y) - , Z(z) -{ -} - -Double3::Double3(const Double4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) - , Z(xyzw.Z) -{ -} - -Double3::Double3(const Color& color) - : X(color.R) - , Y(color.G) - , Z(color.B) -{ -} - -String Double3::ToString() const -{ - return String::Format(TEXT("{}"), *this); -} - -void Double3::UnwindEuler() -{ - X = Math::UnwindDegrees(X); - Y = Math::UnwindDegrees(Y); - Z = Math::UnwindDegrees(Z); -} - -Double3 Double3::Floor(const Double3& v) -{ - return Double3( - Math::Floor(v.X), - Math::Floor(v.Y), - Math::Floor(v.Z) - ); -} - -Double3 Double3::Frac(const Double3& v) -{ - return Double3( - v.X - (int64)v.X, - v.Y - (int64)v.Y, - v.Z - (int64)v.Z - ); -} - -Double3 Double3::Clamp(const Double3& value, const Double3& min, const Double3& max) -{ - double x = value.X; - x = x > max.X ? max.X : x; - x = x < min.X ? min.X : x; - - double y = value.Y; - y = y > max.Y ? max.Y : y; - y = y < min.Y ? min.Y : y; - - double z = value.Z; - z = z > max.Z ? max.Z : z; - z = z < min.Z ? min.Z : z; - - return Double3(x, y, z); -} - -void Double3::Clamp(const Double3& value, const Double3& min, const Double3& max, Double3& result) -{ - double x = value.X; - x = x > max.X ? max.X : x; - x = x < min.X ? min.X : x; - - double y = value.Y; - y = y > max.Y ? max.Y : y; - y = y < min.Y ? min.Y : y; - - double z = value.Z; - z = z > max.Z ? max.Z : z; - z = z < min.Z ? min.Z : z; - - result = Double3(x, y, z); -} - -double Double3::Distance(const Double3& value1, const Double3& value2) -{ - const double x = value1.X - value2.X; - const double y = value1.Y - value2.Y; - const double z = value1.Z - value2.Z; - return Math::Sqrt(x * x + y * y + z * z); -} - -double Double3::DistanceSquared(const Double3& value1, const Double3& value2) -{ - const double x = value1.X - value2.X; - const double y = value1.Y - value2.Y; - const double z = value1.Z - value2.Z; - return x * x + y * y + z * z; -} - -Double3 Double3::Normalize(const Double3& input) -{ - Double3 output = input; - const double length = input.Length(); - if (!Math::IsZero(length)) - { - const double inv = 1.0 / length; - output.X *= inv; - output.Y *= inv; - output.Z *= inv; - } - return output; -} - -void Double3::Normalize(const Double3& input, Double3& result) -{ - result = input; - const double length = input.Length(); - if (!Math::IsZero(length)) - { - const double inv = 1.0 / length; - result.X *= inv; - result.Y *= inv; - result.Z *= inv; - } -} - -void Double3::Hermite(const Double3& value1, const Double3& tangent1, const Double3& value2, const Double3& tangent2, double amount, Double3& result) -{ - const double squared = amount * amount; - const double cubed = amount * squared; - const double part1 = 2.0 * cubed - 3.0 * squared + 1.0; - const double part2 = -2.0 * cubed + 3.0 * squared; - const double part3 = cubed - 2.0 * squared + amount; - const double part4 = cubed - squared; - - result.X = value1.X * part1 + value2.X * part2 + tangent1.X * part3 + tangent2.X * part4; - result.Y = value1.Y * part1 + value2.Y * part2 + tangent1.Y * part3 + tangent2.Y * part4; - result.Z = value1.Z * part1 + value2.Z * part2 + tangent1.Z * part3 + tangent2.Z * part4; -} - -void Double3::Reflect(const Double3& vector, const Double3& normal, Double3& result) -{ - const double dot = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z; - result.X = vector.X - 2.0 * dot * normal.X; - result.Y = vector.Y - 2.0 * dot * normal.Y; - result.Z = vector.Z - 2.0 * dot * normal.Z; -} - -void Double3::Transform(const Double3& vector, const Quaternion& rotation, Double3& result) -{ - const double x = rotation.X + rotation.X; - const double y = rotation.Y + rotation.Y; - const double z = rotation.Z + rotation.Z; - const double wx = rotation.W * x; - const double wy = rotation.W * y; - const double wz = rotation.W * z; - const double xx = rotation.X * x; - const double xy = rotation.X * y; - const double xz = rotation.X * z; - const double yy = rotation.Y * y; - const double yz = rotation.Y * z; - const double zz = rotation.Z * z; - - result = Double3( - vector.X * (1.0 - yy - zz) + vector.Y * (xy - wz) + vector.Z * (xz + wy), - vector.X * (xy + wz) + vector.Y * (1.0 - xx - zz) + vector.Z * (yz - wx), - vector.X * (xz - wy) + vector.Y * (yz + wx) + vector.Z * (1.0 - xx - yy)); -} - -Double3 Double3::Transform(const Double3& vector, const Quaternion& rotation) -{ - const double x = rotation.X + rotation.X; - const double y = rotation.Y + rotation.Y; - const double z = rotation.Z + rotation.Z; - const double wx = rotation.W * x; - const double wy = rotation.W * y; - const double wz = rotation.W * z; - const double xx = rotation.X * x; - const double xy = rotation.X * y; - const double xz = rotation.X * z; - const double yy = rotation.Y * y; - const double yz = rotation.Y * z; - const double zz = rotation.Z * z; - - return Double3( - vector.X * (1.0 - yy - zz) + vector.Y * (xy - wz) + vector.Z * (xz + wy), - vector.X * (xy + wz) + vector.Y * (1.0 - xx - zz) + vector.Z * (yz - wx), - vector.X * (xz - wy) + vector.Y * (yz + wx) + vector.Z * (1.0 - xx - yy)); -} - -void Double3::Transform(const Double3& vector, const Matrix& transform, Double4& result) -{ - result = Double4( - vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, - vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, - vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43, - vector.X * transform.M14 + vector.Y * transform.M24 + vector.Z * transform.M34 + transform.M44); -} - -void Double3::Transform(const Double3& vector, const Matrix& transform, Double3& result) -{ - result = Double3( - vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, - vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, - vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); -} - -void Double3::Transform(const Double3* vectors, const Matrix& transform, Double3* results, int32 vectorsCount) -{ - for (int32 i = 0; i < vectorsCount; i++) - { - Transform(vectors[i], transform, results[i]); - } -} - -Double3 Double3::Transform(const Double3& vector, const Matrix& transform) -{ - return Double3( - vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, - vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, - vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); -} - -void Double3::TransformCoordinate(const Double3& coordinate, const Matrix& transform, Double3& result) -{ - Double4 vector; - vector.X = coordinate.X * transform.M11 + coordinate.Y * transform.M21 + coordinate.Z * transform.M31 + transform.M41; - vector.Y = coordinate.X * transform.M12 + coordinate.Y * transform.M22 + coordinate.Z * transform.M32 + transform.M42; - vector.Z = coordinate.X * transform.M13 + coordinate.Y * transform.M23 + coordinate.Z * transform.M33 + transform.M43; - vector.W = 1.0 / (coordinate.X * transform.M14 + coordinate.Y * transform.M24 + coordinate.Z * transform.M34 + transform.M44); - result = Double3(vector.X * vector.W, vector.Y * vector.W, vector.Z * vector.W); -} - -void Double3::TransformNormal(const Double3& normal, const Matrix& transform, Double3& result) -{ - result = Double3( - normal.X * transform.M11 + normal.Y * transform.M21 + normal.Z * transform.M31, - normal.X * transform.M12 + normal.Y * transform.M22 + normal.Z * transform.M32, - normal.X * transform.M13 + normal.Y * transform.M23 + normal.Z * transform.M33); -} - -double Double3::TriangleArea(const Double3& v0, const Double3& v1, const Double3& v2) -{ - return (v2 - v0 ^ v1 - v0).Length() * 0.5; -} - -double Double3::Angle(const Double3& from, const Double3& to) -{ - const double dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0, 1.0); - if (Math::Abs(dot) > (1.0 - ZeroTolerance)) - return dot > 0.0 ? 0.0 : PI; - return Math::Acos(dot); -} diff --git a/Source/Engine/Core/Math/Double3.cs b/Source/Engine/Core/Math/Double3.cs index 24146022a..15671bbf5 100644 --- a/Source/Engine/Core/Math/Double3.cs +++ b/Source/Engine/Core/Math/Double3.cs @@ -337,16 +337,6 @@ namespace FlaxEngine } } - /// - /// Reverses the direction of the vector. - /// - public void Negate() - { - X *= -1; - Y *= -1; - Z *= -1; - } - /// /// When this vector contains Euler angles (degrees), ensure that angles are between +/-180 /// diff --git a/Source/Engine/Core/Math/Double3.h b/Source/Engine/Core/Math/Double3.h index c545cf78e..b2f09576c 100644 --- a/Source/Engine/Core/Math/Double3.h +++ b/Source/Engine/Core/Math/Double3.h @@ -2,812 +2,4 @@ #pragma once -#include "Math.h" -#include "Mathd.h" -#include "Engine/Core/Formatting.h" -#include "Engine/Core/Templates.h" - -struct Double2; -struct Double4; -struct Vector2; -struct Vector3; -struct Vector4; -struct Int2; -struct Int3; -struct Int4; -struct Color; -struct Matrix; - -/// -/// Represents a two dimensional mathematical vector with 64-bit precision (per-component). -/// -API_STRUCT() struct FLAXENGINE_API Double3 -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(Double3); -public: - union - { - struct - { - /// - /// The X component of the vector. - /// - API_FIELD() double X; - - /// - /// The Y component of the vector. - /// - API_FIELD() double Y; - - /// - /// The Z component of the vector. - /// - API_FIELD() double Z; - }; - - // Raw values - double Raw[3]; - }; - -public: - // Vector with all components equal 0. - static const Double3 Zero; - - // Vector with all components equal 1. - static const Double3 One; - - // Vector with all components equal half (0.5, 0.5, 0.5). - static const Double3 Half; - - // Vector X=1, Y=0, Z=0. - static const Double3 UnitX; - - // Vector X=0, Y=1, Z=0. - static const Double3 UnitY; - - // Vector X=0, Y=0, Z=1. - static const Double3 UnitZ; - - // A unit vector designating up (0, 1, 0). - static const Double3 Up; - - // A unit vector designating down (0, -1, 0). - static const Double3 Down; - - // A unit vector designating a (-1, 0, 0). - static const Double3 Left; - - // A unit vector designating b (1, 0, 0). - static const Double3 Right; - - // A unit vector designating forward in a a-handed coordinate system (0, 0, 1). - static const Double3 Forward; - - // A unit vector designating backward in a a-handed coordinate system (0, 0, -1). - static const Double3 Backward; - - // A minimum Double3. - static const Double3 Minimum; - - // A maximum Double3. - static const Double3 Maximum; - -public: - /// - /// Empty constructor. - /// - Double3() - { - } - - // Init - // @param xyz Value to assign to the all components - Double3(double xyz) - : X(xyz) - , Y(xyz) - , Z(xyz) - { - } - - // Init - // @param x X component value - // @param y Y component value - // @param z Z component value - Double3(double x, double y, double z) - : X(x) - , Y(y) - , Z(z) - { - } - - /// - /// Init - /// - /// X, Y and Z components in an array - explicit Double3(double xyz[3]) - : X(xyz[0]) - , Y(xyz[1]) - , Z(xyz[2]) - { - } - - explicit Double3(const Vector2& xy, double z); - explicit Double3(const Vector2& xy); - Double3(const Vector3& xyz); - explicit Double3(const Vector4& xyzw); - explicit Double3(const Int2& xy, double z); - explicit Double3(const Int3& xyz); - explicit Double3(const Int4& xyzw); - explicit Double3(const Double2& xy); - explicit Double3(const Double2& xy, double z); - explicit Double3(const Double4& xyzw); - explicit Double3(const Color& color); - -public: - String ToString() const; - -public: - // Gets a value indicting whether this instance is normalized. - bool IsNormalized() const - { - return Math::IsOne(X * X + Y * Y + Z * Z); - } - - // Gets a value indicting whether this vector is zero. - bool IsZero() const - { - return Math::IsZero(X) && Math::IsZero(Y) && Math::IsZero(Z); - } - - // Gets a value indicting whether any vector component is zero. - bool IsAnyZero() const - { - return Math::IsZero(X) || Math::IsZero(Y) || Math::IsZero(Z); - } - - // Gets a value indicting whether this vector is one. - bool IsOne() const - { - return Math::IsOne(X) && Math::IsOne(Y) && Math::IsOne(Z); - } - - // Calculates the length of the vector. - double Length() const - { - return Math::Sqrt(X * X + Y * Y + Z * Z); - } - - // Calculates the squared length of the vector. - double LengthSquared() const - { - return X * X + Y * Y + Z * Z; - } - - // Calculates inverted length of the vector (1 / length). - double InvLength() const - { - return 1.0 / Length(); - } - - /// - /// Calculates a vector with values being absolute values of that vector. - /// - Double3 GetAbsolute() const - { - return Double3(Math::Abs(X), Math::Abs(Y), Math::Abs(Z)); - } - - /// - /// Calculates a vector with values being opposite to values of that vector. - /// - Double3 GetNegative() const - { - return Double3(-X, -Y, -Z); - } - - /// - /// Calculates a normalized vector that has length equal to 1. - /// - Double3 GetNormalized() const - { - const double rcp = 1.0 / Length(); - return Double3(X * rcp, Y * rcp, Z * rcp); - } - - /// - /// Returns the average arithmetic of all the components. - /// - double AverageArithmetic() const - { - return (X + Y + Z) * 0.333333334; - } - - /// - /// Gets the sum of all vector components values. - /// - double SumValues() const - { - return X + Y + Z; - } - - /// - /// Returns the minimum value of all the components. - /// - double MinValue() const - { - return Math::Min(X, Y, Z); - } - - /// - /// Returns the maximum value of all the components. - /// - double MaxValue() const - { - return Math::Max(X, Y, Z); - } - - /// - /// Returns true if vector has one or more components is not a number (NaN). - /// - bool IsNaN() const - { - return isnan(X) || isnan(Y) || isnan(Z); - } - - /// - /// Returns true if vector has one or more components equal to +/- infinity. - /// - bool IsInfinity() const - { - return isinf(X) || isinf(Y) || isinf(Z); - } - - /// - /// Returns true if vector has one or more components equal to +/- infinity or NaN. - /// - bool IsNanOrInfinity() const - { - return IsInfinity() || IsNaN(); - } - -public: - /// - /// Performs vector normalization (scales vector up to unit length). - /// - void Normalize() - { - const double length = Math::Sqrt(X * X + Y * Y + Z * Z); - if (Math::Abs(length) >= ZeroTolerance) - { - const double inv = 1.0 / length; - X *= inv; - Y *= inv; - Z *= inv; - } - } - - /// - /// Performs fast vector normalization (scales vector up to unit length). - /// - void NormalizeFast() - { - const double inv = 1.0 / Math::Sqrt(X * X + Y * Y + Z * Z); - X *= inv; - Y *= inv; - Z *= inv; - } - - /// - /// Sets all vector components to the absolute values. - /// - void Absolute() - { - X = Math::Abs(X); - Y = Math::Abs(Y); - Z = Math::Abs(Z); - } - - /// - /// Negates all components of that vector. - /// - void Negate() - { - X = -X; - Y = -Y; - Z = -Z; - } - - /// - /// When this vector contains Euler angles (degrees), ensure that angles are between +/-180. - /// - void UnwindEuler(); - -public: - Double3 operator+(const Double3& b) const - { - return Double3(X + b.X, Y + b.Y, Z + b.Z); - } - - Double3 operator-(const Double3& b) const - { - return Double3(X - b.X, Y - b.Y, Z - b.Z); - } - - Double3 operator*(const Double3& b) const - { - return Double3(X * b.X, Y * b.Y, Z * b.Z); - } - - Double3 operator/(const Double3& b) const - { - return Double3(X / b.X, Y / b.Y, Z / b.Z); - } - - Double3 operator-() const - { - return Double3(-X, -Y, -Z); - } - - Double3 operator^(const Double3& b) const - { - return Cross(*this, b); - } - - double operator|(const Double3& b) const - { - return Dot(*this, b); - } - - Double3& operator+=(const Double3& b) - { - X += b.X; - Y += b.Y; - Z += b.Z; - return *this; - } - - Double3& operator-=(const Double3& b) - { - X -= b.X; - Y -= b.Y; - Z -= b.Z; - return *this; - } - - Double3& operator*=(const Double3& b) - { - X *= b.X; - Y *= b.Y; - Z *= b.Z; - return *this; - } - - Double3& operator/=(const Double3& b) - { - X /= b.X; - Y /= b.Y; - Z /= b.Z; - return *this; - } - - Double3 operator+(double b) const - { - return Double3(X + b, Y + b, Z + b); - } - - Double3 operator-(double b) const - { - return Double3(X - b, Y - b, Z - b); - } - - Double3 operator*(double b) const - { - return Double3(X * b, Y * b, Z * b); - } - - Double3 operator/(double b) const - { - return Double3(X / b, Y / b, Z / b); - } - - Double3& operator+=(double b) - { - *this = Add(*this, b); - return *this; - } - - Double3& operator-=(double b) - { - *this = Subtract(*this, b); - return *this; - } - - Double3& operator*=(double b) - { - *this = Multiply(*this, b); - return *this; - } - - Double3& operator/=(double b) - { - *this = Divide(*this, b); - return *this; - } - - bool operator==(const Double3& b) const - { - return X == b.X && Y == b.Y && Z == b.Z; - } - - bool operator!=(const Double3& b) const - { - return X != b.X || Y != b.Y || Z != b.Z; - } - - bool operator>(const Double3& b) const - { - return X > b.X && Y > b.Y && Z > b.Z; - } - - bool operator>=(const Double3& b) const - { - return X >= b.X && Y >= b.Y && Z >= b.Z; - } - - bool operator<(const Double3& b) const - { - return X < b.X && Y < b.Y && Z < b.Z; - } - - bool operator<=(const Double3& b) const - { - return X <= b.X && Y <= b.Y && Z <= b.Z; - } - -public: - static bool NearEqual(const Double3& a, const Double3& b) - { - return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y) && Math::NearEqual(a.Z, b.Z); - } - - static bool NearEqual(const Double3& a, const Double3& b, double epsilon) - { - return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon) && Math::NearEqual(a.Z, b.Z, epsilon); - } - -public: - static void Add(const Double3& a, const Double3& b, Double3& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - result.Z = a.Z + b.Z; - } - - static Double3 Add(const Double3& a, const Double3& b) - { - Double3 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Double3& a, const Double3& b, Double3& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - result.Z = a.Z - b.Z; - } - - static Double3 Subtract(const Double3& a, const Double3& b) - { - Double3 result; - Subtract(a, b, result); - return result; - } - - static Double3 Multiply(const Double3& a, const Double3& b) - { - return Double3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); - } - - static void Multiply(const Double3& a, const Double3& b, Double3& result) - { - result = Double3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); - } - - static Double3 Multiply(const Double3& a, double b) - { - return Double3(a.X * b, a.Y * b, a.Z * b); - } - - static Double3 Divide(const Double3& a, const Double3& b) - { - return Double3(a.X / b.X, a.Y / b.Y, a.Z / b.Z); - } - - static void Divide(const Double3& a, const Double3& b, Double3& result) - { - result = Double3(a.X / b.X, a.Y / b.Y, a.Z / b.Z); - } - - static Double3 Divide(const Double3& a, double b) - { - return Double3(a.X / b, a.Y / b, a.Z / b); - } - - static Double3 Floor(const Double3& v); - static Double3 Frac(const Double3& v); - - static double ScalarProduct(const Double3& a, const Double3& b) - { - return a.X * b.X + a.Y * b.Y + a.Z * b.Z; - } - -public: - // Restricts a value to be within a specified range. - // @param value The value to clamp. - // @param min The minimum value. - // @param max The maximum value. - // @returns Clamped value - static Double3 Clamp(const Double3& value, const Double3& min, const Double3& max); - - // Restricts a value to be within a specified range. - // @param value The value to clamp. - // @param min The minimum value. - // @param max The maximum value. - // @param result When the method completes, contains the clamped value. - static void Clamp(const Double3& value, const Double3& min, const Double3& max, Double3& result); - - // Calculates the distance between two vectors. - // @param value1 The first vector. - // @param value2 The second vector. - // @returns The distance between the two vectors. - static double Distance(const Double3& value1, const Double3& value2); - - // Calculates the squared distance between two vectors. - // @param value1 The first vector. - // @param value2 The second vector. - // @returns The squared distance between the two vectors. - static double DistanceSquared(const Double3& value1, const Double3& value2); - - // Performs vector normalization (scales vector up to unit length). - // @param inout Input vector to normalize. - // @returns Output vector that is normalized (has unit length). - static Double3 Normalize(const Double3& input); - - // Performs vector normalization (scales vector up to unit length). This is a faster version that does not performs check for length equal 0 (it assumes that input vector is not empty). - // @param inout Input vector to normalize (cannot be zero). - // @returns Output vector that is normalized (has unit length). - static Double3 NormalizeFast(const Double3& input) - { - const double inv = 1.0 / input.Length(); - return Double3(input.X * inv, input.Y * inv, input.Z * inv); - } - - // Performs vector normalization (scales vector up to unit length). - // @param inout Input vector to normalize. - // @param output Output vector that is normalized (has unit length). - static void Normalize(const Double3& input, Double3& result); - - // dot product with another vector. - static double Dot(const Double3& a, const Double3& b) - { - return a.X * b.X + a.Y * b.Y + a.Z * b.Z; - } - - // Calculates the cross product of two vectors. - // @param a First source vector. - // @param b Second source vector. - // @param result When the method completes, contains the cross product of the two vectors. - static void Cross(const Double3& a, const Double3& b, Double3& result) - { - result = Double3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); - } - - // Calculates the cross product of two vectors. - // @param a First source vector. - // @param b Second source vector. - // @returns Cross product of the two vectors. - static Double3 Cross(const Double3& a, const Double3& b) - { - return Double3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); - } - - // Performs a linear interpolation between two vectors. - // @param start Start vector. - // @param end End vector. - // @param amount Value between 0 and 1 indicating the weight of end. - // @param result When the method completes, contains the linear interpolation of the two vectors. - static void Lerp(const Double3& start, const Double3& end, double amount, Double3& result) - { - result.X = Math::Lerp(start.X, end.X, amount); - result.Y = Math::Lerp(start.Y, end.Y, amount); - result.Z = Math::Lerp(start.Z, end.Z, amount); - } - - /// - /// Performs a linear interpolation between two vectors. - /// - static Double3 Lerp(const Double3& start, const Double3& end, double amount) - { - Double3 result; - Lerp(start, end, amount, result); - return result; - } - - /// - /// Performs a cubic interpolation between two vectors - /// - static void SmoothStep(const Double3& start, const Double3& end, double amount, Double3& result) - { - amount = Math::SmoothStep(amount); - Lerp(start, end, amount, result); - } - - // Performs a Hermite spline interpolation. - // @param value1 First source position vector - // @param tangent1 First source tangent vector - // @param value2 Second source position vector - // @param tangent2 Second source tangent vector - // @param amount Weighting factor, - // @param result When the method completes, contains the result of the Hermite spline interpolation, - static void Hermite(const Double3& value1, const Double3& tangent1, const Double3& value2, const Double3& tangent2, double amount, Double3& result); - - // Returns the reflection of a vector off a surface that has the specified normal - // @param vector The source vector - // @param normal Normal of the surface - // @param result When the method completes, contains the reflected vector - static void Reflect(const Double3& vector, const Double3& normal, Double3& result); - - // Transforms a 3D vector by the given Quaternion rotation - // @param vector The vector to rotate - // @param rotation The Quaternion rotation to apply - // @param result When the method completes, contains the transformed Vector4 - static void Transform(const Double3& vector, const Quaternion& rotation, Double3& result); - - // Transforms a 3D vector by the given Quaternion rotation - // @param vector The vector to rotate - // @param rotation The Quaternion rotation to apply - // @returns The transformed Double3 - static Double3 Transform(const Double3& vector, const Quaternion& rotation); - - // Transforms a 3D vector by the given matrix - // @param vector The source vector - // @param transform The transformation matrix - // @param result When the method completes, contains the transformed Double3 - static void Transform(const Double3& vector, const Matrix& transform, Double3& result); - - // Transforms a 3D vectors by the given matrix - // @param vectors The source vectors - // @param transform The transformation matrix - // @param results When the method completes, contains the transformed Vector3s - // @param vectorsCount Amount of vectors to transform - static void Transform(const Double3* vectors, const Matrix& transform, Double3* results, int32 vectorsCount); - - // Transforms a 3D vector by the given matrix - // @param vector The source vector - // @param transform The transformation matrix - // @returns Transformed Double3 - static Double3 Transform(const Double3& vector, const Matrix& transform); - - // Transforms a 3D vector by the given matrix - // @param vector The source vector - // @param transform The transformation matrix - // @param result When the method completes, contains the transformed Double4 - static void Transform(const Double3& vector, const Matrix& transform, Double4& result); - - // Performs a coordinate transformation using the given matrix - // @param coordinate The coordinate vector to transform - // @param transform The transformation matrix - // @param result When the method completes, contains the transformed coordinates - static void TransformCoordinate(const Double3& coordinate, const Matrix& transform, Double3& result); - - // Performs a normal transformation using the given matrix - // @param normal The normal vector to transform - // @param transform The transformation matrix - // @param result When the method completes, contains the transformed normal - static void TransformNormal(const Double3& normal, const Matrix& transform, Double3& result); - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static Double3 Max(const Double3& a, const Double3& b) - { - return Double3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static Double3 Min(const Double3& a, const Double3& b) - { - return Double3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static void Max(const Double3& a, const Double3& b, Double3& result) - { - result = Double3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static void Min(const Double3& a, const Double3& b, Double3& result) - { - result = Double3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); - } - - static Double3 Round(const Double3& v) - { - return Double3(Math::Round(v.X), Math::Round(v.Y), Math::Round(v.Z)); - } - - static Double3 Ceil(const Double3& v) - { - return Double3(Math::Ceil(v.X), Math::Ceil(v.Y), Math::Ceil(v.Z)); - } - - static Double3 Abs(const Double3& v) - { - return Double3(Math::Abs(v.X), Math::Abs(v.Y), Math::Abs(v.Z)); - } - - /// - /// Calculates the area of the triangle. - /// - /// The first triangle vertex. - /// The second triangle vertex. - /// The third triangle vertex. - /// The triangle area. - static double TriangleArea(const Double3& v0, const Double3& v1, const Double3& v2); - - /// - /// Calculates the angle (in radians) between from and to. This is always the smallest value. - /// - /// The first vector. - /// The second vector. - /// The angle (in radians). - static double Angle(const Double3& from, const Double3& to); -}; - -inline Double3 operator+(double a, const Double3& b) -{ - return b + a; -} - -inline Double3 operator-(double a, const Double3& b) -{ - return Double3(a) - b; -} - -inline Double3 operator*(double a, const Double3& b) -{ - return b * a; -} - -inline Double3 operator/(double a, const Double3& b) -{ - return Double3(a) / b; -} - -namespace Math -{ - FORCE_INLINE static bool NearEqual(const Double3& a, const Double3& b) - { - return Double3::NearEqual(a, b); - } -} - -template<> -struct TIsPODType -{ - enum { Value = true }; -}; - -DEFINE_DEFAULT_FORMATTING(Double3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z); +#include "Vector3.h" diff --git a/Source/Engine/Core/Math/Double4.cpp b/Source/Engine/Core/Math/Double4.cpp deleted file mode 100644 index 31439dc6c..000000000 --- a/Source/Engine/Core/Math/Double4.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "Double2.h" -#include "Double3.h" -#include "Double4.h" -#include "Vector4.h" -#include "Vector2.h" -#include "Vector3.h" -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" -#include "Color.h" -#include "Matrix.h" -#include "Rectangle.h" -#include "../Types/String.h" - -static_assert(sizeof(Double4) == 32, "Invalid Double4 type size."); - -const Double4 Double4::Zero(0.0); -const Double4 Double4::One(1.0); -const Double4 Double4::UnitX(1, 0, 0, 0); -const Double4 Double4::UnitY(0, 1, 0, 0); -const Double4 Double4::UnitZ(0, 0, 1, 0); -const Double4 Double4::UnitW(0, 0, 0, 1); -const Double4 Double4::Minimum(MIN_double); -const Double4 Double4::Maximum(MAX_double); - -Double4::Double4(double xyzw[4]) -{ - Platform::MemoryCopy(Raw, xyzw, sizeof(double) * 4); -} - -Double4::Double4(const Vector2& xy, double z, double w) - : X(xy.X) - , Y(xy.Y) - , Z(z) - , W(w) -{ -} - -Double4::Double4(const Vector2& xy, const Vector2& zw) - : X(xy.X) - , Y(xy.Y) - , Z(zw.X) - , W(zw.Y) -{ -} - -Double4::Double4(const Vector3& xyz, double w) - : X(xyz.X) - , Y(xyz.Y) - , Z(xyz.Z) - , W(w) -{ -} - -Double4::Double4(const Vector4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) - , Z(xyzw.Z) - , W(xyzw.W) -{ -} - -Double4::Double4(const Int2& xy, double z, double w) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) - , Z(z) - , W(w) -{ -} - -Double4::Double4(const Int3& xyz, double w) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) - , W(w) -{ -} - -Double4::Double4(const Int4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.X)) - , W(static_cast(xyzw.Y)) -{ -} - -Double4::Double4(const Double2& xy, double z, double w) - : X(xy.X) - , Y(xy.Y) - , Z(z) - , W(w) -{ -} - -Double4::Double4(const Double3& xyz, double w) - : X(xyz.X) - , Y(xyz.Y) - , Z(xyz.Z) - , W(w) -{ -} - -Double4::Double4(const Color& color) - : X(color.R) - , Y(color.G) - , Z(color.B) - , W(color.A) -{ -} - -Double4::Double4(const Rectangle& rect) - : X(rect.Location.X) - , Y(rect.Location.Y) - , Z(rect.Size.X) - , W(rect.Size.Y) -{ -} - -String Double4::ToString() const -{ - return String::Format(TEXT("{}"), *this); -} - -Double4 Double4::Floor(const Double4& v) -{ - return Double4( - Math::Floor(v.X), - Math::Floor(v.Y), - Math::Floor(v.Z), - Math::Floor(v.W) - ); -} - -Double4 Double4::Frac(const Double4& v) -{ - return Double4( - v.X - (int64)v.X, - v.Y - (int64)v.Y, - v.Z - (int64)v.Z, - v.W - (int64)v.W - ); -} - -Double4 Double4::Round(const Double4& v) -{ - return Double4( - Math::Round(v.X), - Math::Round(v.Y), - Math::Round(v.Z), - Math::Round(v.W) - ); -} - -Double4 Double4::Ceil(const Double4& v) -{ - return Double4( - Math::Ceil(v.X), - Math::Ceil(v.Y), - Math::Ceil(v.Z), - Math::Ceil(v.W) - ); -} - -Double4 Double4::Clamp(const Double4& value, const Double4& min, const Double4& max) -{ - double x = value.X; - x = x > max.X ? max.X : x; - x = x < min.X ? min.X : x; - - double y = value.Y; - y = y > max.Y ? max.Y : y; - y = y < min.Y ? min.Y : y; - - double z = value.Z; - z = z > max.Z ? max.Z : z; - z = z < min.Z ? min.Z : z; - - double w = value.W; - w = w > max.W ? max.W : w; - w = w < min.W ? min.W : w; - - return Double4(x, y, z, w); -} - -void Double4::Clamp(const Double4& value, const Double4& min, const Double4& max, Double4& result) -{ - double x = value.X; - x = x > max.X ? max.X : x; - x = x < min.X ? min.X : x; - - double y = value.Y; - y = y > max.Y ? max.Y : y; - y = y < min.Y ? min.Y : y; - - double z = value.Z; - z = z > max.Z ? max.Z : z; - z = z < min.Z ? min.Z : z; - - double w = value.W; - w = w > max.W ? max.W : w; - w = w < min.W ? min.W : w; - - result = Double4(x, y, z, w); -} - -Double4 Double4::Transform(const Double4& v, const Matrix& m) -{ - return Double4( - m.Values[0][0] * v.Raw[0] + m.Values[1][0] * v.Raw[1] + m.Values[2][0] * v.Raw[2] + m.Values[3][0] * v.Raw[3], - m.Values[0][1] * v.Raw[0] + m.Values[1][1] * v.Raw[1] + m.Values[2][1] * v.Raw[2] + m.Values[3][1] * v.Raw[3], - m.Values[0][2] * v.Raw[0] + m.Values[1][2] * v.Raw[1] + m.Values[2][2] * v.Raw[2] + m.Values[3][2] * v.Raw[3], - m.Values[0][3] * v.Raw[0] + m.Values[1][3] * v.Raw[1] + m.Values[2][3] * v.Raw[2] + m.Values[3][3] * v.Raw[3] - ); -} diff --git a/Source/Engine/Core/Math/Double4.h b/Source/Engine/Core/Math/Double4.h index aeb43ca10..0ba849628 100644 --- a/Source/Engine/Core/Math/Double4.h +++ b/Source/Engine/Core/Math/Double4.h @@ -2,496 +2,4 @@ #pragma once -#include "Math.h" -#include "Mathd.h" -#include "Engine/Core/Formatting.h" -#include "Engine/Core/Templates.h" - -struct Double2; -struct Double3; -struct Vector2; -struct Vector3; -struct Vector4; -struct Color; -struct Matrix; -struct Rectangle; -class String; -struct Int2; -struct Int3; -struct Int4; - -/// -/// Represents a four dimensional mathematical vector with 64-bit precision (per-component). -/// -API_STRUCT() struct FLAXENGINE_API Double4 -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(Double4); -public: - union - { - struct - { - /// - /// The X component. - /// - API_FIELD() double X; - - /// - /// The Y component. - /// - API_FIELD() double Y; - - /// - /// The Z component. - /// - API_FIELD() double Z; - - /// - /// The W component. - /// - API_FIELD() double W; - }; - - /// - /// The raw vector values (in xyzw order). - /// - double Raw[4]; - }; - -public: - // Vector with all components equal 0 - static const Double4 Zero; - - // Vector with all components equal 1 - static const Double4 One; - - // Vector X=1, Y=0, Z=0, W=0 - static const Double4 UnitX; - - // Vector X=0, Y=1, Z=0, W=0 - static const Double4 UnitY; - - // Vector X=0, Y=0, Z=1, W=0 - static const Double4 UnitZ; - - // Vector X=0, Y=0, Z=0, W=1 - static const Double4 UnitW; - - // A minimum Double4 - static const Double4 Minimum; - - // A maximum Double4 - static const Double4 Maximum; - -public: - /// - /// Empty constructor. - /// - Double4() - { - } - - // Init - // @param xyzw Value to assign to the all components - Double4(double xyzw) - : X(xyzw) - , Y(xyzw) - , Z(xyzw) - , W(xyzw) - { - } - - // Init - // @param xyzw Values to assign - explicit Double4(double xyzw[4]); - - // Init - // @param x X component value - // @param y Y component value - // @param z Z component value - // @param w W component value - Double4(double x, double y, double z, double w) - : X(x) - , Y(y) - , Z(z) - , W(w) - { - } - - explicit Double4(const Vector2& xy, double z, double w); - explicit Double4(const Vector2& xy, const Vector2& zw); - explicit Double4(const Vector3& xyz, double w); - Double4(const Vector4& xyzw); - explicit Double4(const Int2& xy, double z, double w); - explicit Double4(const Int3& xyz, double w); - explicit Double4(const Int4& xyzw); - explicit Double4(const Double2& xy, double z, double w); - explicit Double4(const Double3& xyz, double w); - explicit Double4(const Color& color); - explicit Double4(const Rectangle& rect); - -public: - String ToString() const; - -public: - // Gets a value indicting whether this vector is zero. - bool IsZero() const - { - return Math::IsZero(X) && Math::IsZero(Y) && Math::IsZero(Z) && Math::IsZero(W); - } - - // Gets a value indicting whether any vector component is zero. - bool IsAnyZero() const - { - return Math::IsZero(X) || Math::IsZero(Y) || Math::IsZero(Z) || Math::IsZero(W); - } - - // Gets a value indicting whether this vector is one. - bool IsOne() const - { - return Math::IsOne(X) && Math::IsOne(Y) && Math::IsOne(Z) && Math::IsOne(W); - } - - /// - /// Calculates a vector with values being absolute values of that vector. - /// - Double4 GetAbsolute() const - { - return Double4(Math::Abs(X), Math::Abs(Y), Math::Abs(Z), Math::Abs(W)); - } - - /// - /// Calculates a vector with values being opposite to values of that vector. - /// - Double4 GetNegative() const - { - return Double4(-X, -Y, -Z, -W); - } - - /// - /// Returns the average arithmetic of all the components. - /// - double AverageArithmetic() const - { - return (X + Y + Z + W) * 0.25; - } - - /// - /// Gets the sum of all vector components values. - /// - double SumValues() const - { - return X + Y + Z + W; - } - - /// - /// Returns the minimum value of all the components. - /// - double MinValue() const - { - return Math::Min(X, Y, Z, W); - } - - /// - /// Returns the maximum value of all the components. - /// - double MaxValue() const - { - return Math::Max(X, Y, Z, W); - } - - /// - /// Returns true if vector has one or more components is not a number (NaN). - /// - bool IsNaN() const - { - return isnan(X) || isnan(Y) || isnan(Z) || isnan(W); - } - - /// - /// Returns true if vector has one or more components equal to +/- infinity. - /// - bool IsInfinity() const - { - return isinf(X) || isinf(Y) || isinf(Z) || isinf(W); - } - - /// - /// Returns true if vector has one or more components equal to +/- infinity or NaN. - /// - bool IsNanOrInfinity() const - { - return IsInfinity() || IsNaN(); - } - -public: - // Arithmetic operators with Double4 - inline Double4 operator+(const Double4& b) const - { - return Add(*this, b); - } - - inline Double4 operator-(const Double4& b) const - { - return Subtract(*this, b); - } - - inline Double4 operator*(const Double4& b) const - { - return Multiply(*this, b); - } - - inline Double4 operator/(const Double4& b) const - { - return Divide(*this, b); - } - - // op= operators with Double4 - inline Double4& operator+=(const Double4& b) - { - *this = Add(*this, b); - return *this; - } - - inline Double4& operator-=(const Double4& b) - { - *this = Subtract(*this, b); - return *this; - } - - inline Double4& operator*=(const Double4& b) - { - *this = Multiply(*this, b); - return *this; - } - - inline Double4& operator/=(const Double4& b) - { - *this = Divide(*this, b); - return *this; - } - - // Arithmetic operators with double - inline Double4 operator+(double b) const - { - return Add(*this, b); - } - - inline Double4 operator-(double b) const - { - return Subtract(*this, b); - } - - inline Double4 operator*(double b) const - { - return Multiply(*this, b); - } - - inline Double4 operator/(double b) const - { - return Divide(*this, b); - } - - // op= operators with double - inline Double4& operator+=(double b) - { - *this = Add(*this, b); - return *this; - } - - inline Double4& operator-=(double b) - { - *this = Subtract(*this, b); - return *this; - } - - inline Double4& operator*=(double b) - { - *this = Multiply(*this, b); - return *this; - } - - inline Double4& operator/=(double b) - { - *this = Divide(*this, b); - return *this; - } - - // Comparison - inline bool operator==(const Double4& b) const - { - return X == b.X && Y == b.Y && Z == b.Z && W == b.W; - } - - inline bool operator!=(const Double4& b) const - { - return X != b.X || Y != b.Y || Z != b.Z || W != b.W; - } - - inline bool operator>(const Double4& b) const - { - return X > b.X && Y > b.Y && Z > b.Z && W > b.W; - } - - inline bool operator>=(const Double4& b) const - { - return X >= b.X && Y >= b.Y && Z >= b.Z && W >= b.W; - } - - inline bool operator<(const Double4& b) const - { - return X < b.X && Y < b.Y && Z < b.Z && W < b.W; - } - - inline bool operator<=(const Double4& b) const - { - return X <= b.X && Y <= b.Y && Z <= b.Z && W <= b.W; - } - -public: - static bool NearEqual(const Double4& a, const Double4& b) - { - return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y) && Math::NearEqual(a.Z, b.Z) && Math::NearEqual(a.W, b.W); - } - - static bool NearEqual(const Double4& a, const Double4& b, double epsilon) - { - return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon) && Math::NearEqual(a.Z, b.Z, epsilon) && Math::NearEqual(a.W, b.W, epsilon); - } - -public: - static void Add(const Double4& a, const Double4& b, Double4& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - result.Z = a.Z + b.Z; - result.W = a.W + b.W; - } - - static Double4 Add(const Double4& a, const Double4& b) - { - Double4 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Double4& a, const Double4& b, Double4& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - result.Z = a.Z - b.Z; - result.W = a.W - b.W; - } - - static Double4 Subtract(const Double4& a, const Double4& b) - { - Double4 result; - Subtract(a, b, result); - return result; - } - - static Double4 Multiply(const Double4& a, const Double4& b) - { - return Double4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W); - } - - static Double4 Multiply(const Double4& a, double b) - { - return Double4(a.X * b, a.Y * b, a.Z * b, a.W * b); - } - - static Double4 Divide(const Double4& a, const Double4& b) - { - return Double4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W); - } - - static Double4 Divide(const Double4& a, double b) - { - return Double4(a.X / b, a.Y / b, a.Z / b, a.W / b); - } - - static Double4 Floor(const Double4& v); - static Double4 Frac(const Double4& v); - static Double4 Round(const Double4& v); - static Double4 Ceil(const Double4& v); - -public: - // Restricts a value to be within a specified range - // @param value The value to clamp - // @param min The minimum value, - // @param max The maximum value - // @returns Clamped value - static Double4 Clamp(const Double4& value, const Double4& min, const Double4& max); - - // Restricts a value to be within a specified range - // @param value The value to clamp - // @param min The minimum value, - // @param max The maximum value - // @param result When the method completes, contains the clamped value - static void Clamp(const Double4& value, const Double4& min, const Double4& max, Double4& result); - - // Performs a linear interpolation between two vectors - // @param start Start vector - // @param end End vector - // @param amount Value between 0 and 1 indicating the weight of end - // @param result When the method completes, contains the linear interpolation of the two vectors - static void Lerp(const Double4& start, const Double4& end, double amount, Double4& result) - { - result.X = Math::Lerp(start.X, end.X, amount); - result.Y = Math::Lerp(start.Y, end.Y, amount); - result.Z = Math::Lerp(start.Z, end.Z, amount); - result.W = Math::Lerp(start.W, end.W, amount); - } - - // - // Performs a linear interpolation between two vectors. - // - // @param start Start vector, - // @param end End vector, - // @param amount Value between 0 and 1 indicating the weight of @paramref end"/>, - // @returns The linear interpolation of the two vectors - static Double4 Lerp(const Double4& start, const Double4& end, double amount) - { - Double4 result; - Lerp(start, end, amount, result); - return result; - } - - static Double4 Transform(const Double4& v, const Matrix& m); -}; - -inline Double4 operator+(double a, const Double4& b) -{ - return b + a; -} - -inline Double4 operator-(double a, const Double4& b) -{ - return Double4(a) - b; -} - -inline Double4 operator*(double a, const Double4& b) -{ - return b * a; -} - -inline Double4 operator/(double a, const Double4& b) -{ - return Double4(a) / b; -} - -namespace Math -{ - FORCE_INLINE static bool NearEqual(const Double4& a, const Double4& b) - { - return Double4::NearEqual(a, b); - } -} - -template<> -struct TIsPODType -{ - enum { Value = true }; -}; - -DEFINE_DEFAULT_FORMATTING(Double4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W); +#include "Vector4.h" diff --git a/Source/Engine/Core/Math/Int2.cpp b/Source/Engine/Core/Math/Int2.cpp deleted file mode 100644 index b09519467..000000000 --- a/Source/Engine/Core/Math/Int2.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" -#include "Vector2.h" -#include "Vector3.h" -#include "Vector4.h" -#include "Engine/Core/Types/String.h" - -static_assert(sizeof(Int2) == 8, "Invalid Int2 type size."); - -const Int2 Int2::Zero(0); -const Int2 Int2::One(1); -const Int2 Int2::Minimum(MIN_int32); -const Int2 Int2::Maximum(MAX_int32); - -Int2::Int2(const Int3& xyz) - : X(xyz.X) - , Y(xyz.Y) -{ -} - -Int2::Int2(const Int4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) -{ -} - -Int2::Int2(const Vector2& xy) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) -{ -} - -Int2::Int2(const Vector3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) -{ -} - -Int2::Int2(const Vector4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) -{ -} - -String Int2::ToString() const -{ - return String::Format(TEXT("{}"), *this); -} diff --git a/Source/Engine/Core/Math/Int2.h b/Source/Engine/Core/Math/Int2.h index 836d4a38c..a814bbed4 100644 --- a/Source/Engine/Core/Math/Int2.h +++ b/Source/Engine/Core/Math/Int2.h @@ -2,389 +2,4 @@ #pragma once -#include "Math.h" -#include "Engine/Core/Formatting.h" -#include "Engine/Core/Templates.h" - -/// -/// Two-components vector (32 bit integer type). -/// -API_STRUCT() struct FLAXENGINE_API Int2 -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(Int2); -public: - union - { - struct - { - /// - /// The X component. - /// - API_FIELD() int32 X; - - /// - /// The Y component. - /// - API_FIELD() int32 Y; - }; - - // Raw values - int32 Raw[2]; - }; - -public: - // Vector with all components equal 0 - static const Int2 Zero; - - // Vector with all components equal 1 - static const Int2 One; - - // A minimum Int2 - static const Int2 Minimum; - - // A maximum Int2 - static const Int2 Maximum; - -public: - /// - /// Empty constructor. - /// - Int2() - { - } - - // Init - // @param xy Value to assign to the all components - Int2(int32 xy) - : X(xy) - , Y(xy) - { - } - - // Init - // @param x X component value - // @param y Y component value - Int2(int32 x, int32 y) - : X(x) - , Y(y) - { - } - - // Init - // @param xyz Int3 to use X and Y components - Int2(const Int3& xyz); - - // Init - // @param xyzw Int4 to use X and Y components - Int2(const Int4& xyzw); - - // Init - // @param xy Vector2 to use X and Y components - explicit Int2(const Vector2& xy); - - // Init - // @param xyz Vector3 to use X and Y components - explicit Int2(const Vector3& xyz); - - // Init - // @param xyzw Vector4 to use X and Y components - explicit Int2(const Vector4& xyzw); - -public: - String ToString() const; - -public: - // Arithmetic operators with Int2 - - Int2 operator+(const Int2& b) const - { - return Add(*this, b); - } - - Int2 operator-(const Int2& b) const - { - return Subtract(*this, b); - } - - Int2 operator*(const Int2& b) const - { - return Multiply(*this, b); - } - - Int2 operator/(const Int2& b) const - { - return Divide(*this, b); - } - - Int2 operator-() const - { - return Int2(-X, -Y); - } - - // op= operators with Int2 - - Int2& operator+=(const Int2& b) - { - *this = Add(*this, b); - return *this; - } - - Int2& operator-=(const Int2& b) - { - *this = Subtract(*this, b); - return *this; - } - - Int2& operator*=(const Int2& b) - { - *this = Multiply(*this, b); - return *this; - } - - Int2& operator/=(const Int2& b) - { - *this = Divide(*this, b); - return *this; - } - - // Arithmetic operators with int32 - - Int2 operator+(int32 b) const - { - return Add(*this, b); - } - - Int2 operator-(int32 b) const - { - return Subtract(*this, b); - } - - Int2 operator*(int32 b) const - { - return Multiply(*this, b); - } - - Int2 operator/(int32 b) const - { - return Divide(*this, b); - } - - // op= operators with int32 - - Int2& operator+=(int32 b) - { - *this = Add(*this, b); - return *this; - } - - Int2& operator-=(int32 b) - { - *this = Subtract(*this, b); - return *this; - } - - Int2& operator*=(int32 b) - { - *this = Multiply(*this, b); - return *this; - } - - Int2& operator/=(int32 b) - { - *this = Divide(*this, b); - return *this; - } - - // Comparison operators - - bool operator==(const Int2& b) const - { - return X == b.X && Y == b.Y; - } - - bool operator!=(const Int2& b) const - { - return X != b.X || Y != b.Y; - } - - bool operator>(const Int2& b) const - { - return X > b.X && Y > b.Y; - } - - bool operator>=(const Int2& b) const - { - return X >= b.X && Y >= b.Y; - } - - bool operator<(const Int2& b) const - { - return X < b.X && Y < b.Y; - } - - bool operator<=(const Int2& b) const - { - return X <= b.X && Y <= b.Y; - } - -public: - static void Add(const Int2& a, const Int2& b, Int2& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - } - - static Int2 Add(const Int2& a, const Int2& b) - { - Int2 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Int2& a, const Int2& b, Int2& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - } - - static Int2 Subtract(const Int2& a, const Int2& b) - { - Int2 result; - Subtract(a, b, result); - return result; - } - - static Int2 Multiply(const Int2& a, const Int2& b) - { - return Int2(a.X * b.X, a.Y * b.Y); - } - - static Int2 Multiply(const Int2& a, int32 b) - { - return Int2(a.X * b, a.Y * b); - } - - static Int2 Divide(const Int2& a, const Int2& b) - { - return Int2(a.X / b.X, a.Y / b.Y); - } - - static Int2 Divide(const Int2& a, int32 b) - { - return Int2(a.X / b, a.Y / b); - } - - /// - /// Gets a value indicting whether this vector is zero. - /// - /// True if the vector is zero, otherwise false. - bool IsZero() const - { - return X == 0 && Y == 0; - } - - /// - /// Gets a value indicting whether any vector component is zero. - /// - /// True if a component is zero, otherwise false. - bool IsAnyZero() const - { - return X == 0 || Y == 0; - } - - /// - /// Gets a value indicting whether this vector is one. - /// - /// True if the vector is one, otherwise false. - bool IsOne() const - { - return X == 1 && Y == 1; - } - - /// - /// Calculates a vector with values being opposite to values of that vector - /// - /// Negative vector - Int2 GetNegative() const - { - return Int2(-X, -Y); - } - - /// - /// Returns average arithmetic of all the components - /// - /// Average arithmetic of all the components - float AverageArithmetic() const - { - return (X + Y) * 0.5f; - } - - /// - /// Gets sum of all vector components values - /// - /// Sum of X, Y, Z and W - int32 SumValues() const - { - return X + Y; - } - - /// - /// Returns minimum value of all the components - /// - /// Minimum value - int32 MinValue() const - { - return Math::Min(X, Y); - } - - /// - /// Returns maximum value of all the components - /// - /// Maximum value - int32 MaxValue() const - { - return Math::Max(X, Y); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - static Int2 Min(const Int2& a, const Int2& b) - { - return Int2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - static Int2 Max(const Int2& a, const Int2& b) - { - return Int2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static void Min(const Int2& a, const Int2& b, Int2& result) - { - result = Int2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static void Max(const Int2& a, const Int2& b, Int2& result) - { - result = Int2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); - } -}; - -template<> -struct TIsPODType -{ - enum { Value = true }; -}; - -DEFINE_DEFAULT_FORMATTING(Int2, "X:{0} Y:{1}", v.X, v.Y); +#include "Vector2.h" diff --git a/Source/Engine/Core/Math/Int3.cpp b/Source/Engine/Core/Math/Int3.cpp deleted file mode 100644 index 106b3346c..000000000 --- a/Source/Engine/Core/Math/Int3.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" -#include "Vector2.h" -#include "Vector3.h" -#include "Vector4.h" -#include "Engine/Core/Types/String.h" - -static_assert(sizeof(Int3) == 12, "Invalid Int3 type size."); - -const Int3 Int3::Zero(0); -const Int3 Int3::One(1); -const Int3 Int3::Minimum(MIN_int32); -const Int3 Int3::Maximum(MAX_int32); - -Int3::Int3(const Int2& xy, int32 z) - : X(xy.X) - , Y(xy.Y) - , Z(z) -{ -} - -Int3::Int3(const Int4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) - , Z(xyzw.Z) -{ -} - -Int3::Int3(const Vector2& xy, int32 z) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) - , Z(z) -{ -} - -Int3::Int3(const Vector3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) -{ -} - -Int3::Int3(const Vector4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.Z)) -{ -} - -String Int3::ToString() const -{ - return String::Format(TEXT("{}"), *this); -} diff --git a/Source/Engine/Core/Math/Int3.h b/Source/Engine/Core/Math/Int3.h index 989d4aeca..b2f09576c 100644 --- a/Source/Engine/Core/Math/Int3.h +++ b/Source/Engine/Core/Math/Int3.h @@ -2,402 +2,4 @@ #pragma once -#include "Math.h" -#include "Engine/Core/Formatting.h" -#include "Engine/Core/Templates.h" - -/// -/// Three-components vector (32 bit integer type). -/// -API_STRUCT() struct FLAXENGINE_API Int3 -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(Int3); -public: - union - { - struct - { - /// - /// The X component. - /// - API_FIELD() int32 X; - - /// - /// The Y component. - /// - API_FIELD() int32 Y; - - /// - /// The Z component. - /// - API_FIELD() int32 Z; - }; - - // Raw values - int32 Raw[3]; - }; - -public: - // Vector with all components equal 0 - static const Int3 Zero; - - // Vector with all components equal 1 - static const Int3 One; - - // A minimum Int3 - static const Int3 Minimum; - - // A maximum Int3 - static const Int3 Maximum; - -public: - /// - /// Empty constructor. - /// - Int3() - { - } - - // Init - // @param xy Value to assign to the all components - Int3(int32 xyz) - : X(xyz) - , Y(xyz) - , Z(xyz) - { - } - - // Init - // @param x X component value - // @param y Y component value - // @param z Z component value - Int3(int32 x, int32 y, int32 z) - : X(x) - , Y(y) - , Z(z) - { - } - - // Init - // @param v Int2 to use X and Y components - // @param z Z component value - Int3(const Int2& xy, int32 z); - - // Init - // @param v Int4 to use X and Y components - Int3(const Int4& xyzw); - - // Init - // @param v Vector2 to use X and Y components - // @param z Z component value - explicit Int3(const Vector2& xy, int32 z); - - // Init - // @param v Vector3 to use X, Y and Z components - explicit Int3(const Vector3& xyz); - - // Init - // @param v Vector4 to use X and Y components - explicit Int3(const Vector4& xyzw); - -public: - String ToString() const; - -public: - // Arithmetic operators with Int2 - - Int3 operator+(const Int3& b) const - { - return Add(*this, b); - } - - Int3 operator-(const Int3& b) const - { - return Subtract(*this, b); - } - - Int3 operator*(const Int3& b) const - { - return Multiply(*this, b); - } - - Int3 operator/(const Int3& b) const - { - return Divide(*this, b); - } - - Int3 operator-() const - { - return Int3(-X, -Y, -Z); - } - - // op= operators with Int2 - - Int3& operator+=(const Int3& b) - { - *this = Add(*this, b); - return *this; - } - - Int3& operator-=(const Int3& b) - { - *this = Subtract(*this, b); - return *this; - } - - Int3& operator*=(const Int3& b) - { - *this = Multiply(*this, b); - return *this; - } - - Int3& operator/=(const Int3& b) - { - *this = Divide(*this, b); - return *this; - } - - // Arithmetic operators with int32 - - Int3 operator+(int32 b) const - { - return Add(*this, b); - } - - Int3 operator-(int32 b) const - { - return Subtract(*this, b); - } - - Int3 operator*(int32 b) const - { - return Multiply(*this, b); - } - - Int3 operator/(int32 b) const - { - return Divide(*this, b); - } - - // op= operators with int32 - - Int3& operator+=(int32 b) - { - *this = Add(*this, b); - return *this; - } - - Int3& operator-=(int32 b) - { - *this = Subtract(*this, b); - return *this; - } - - Int3& operator*=(int32 b) - { - *this = Multiply(*this, b); - return *this; - } - - Int3& operator/=(int32 b) - { - *this = Divide(*this, b); - return *this; - } - - // Comparison operators - - bool operator==(const Int3& b) const - { - return X == b.X && Y == b.Y; - } - - bool operator!=(const Int3& b) const - { - return X != b.X || Y != b.Y; - } - - bool operator>(const Int3& b) const - { - return X > b.X && Y > b.Y; - } - - bool operator>=(const Int3& b) const - { - return X >= b.X && Y >= b.Y; - } - - bool operator<(const Int3& b) const - { - return X < b.X && Y < b.Y; - } - - bool operator<=(const Int3& b) const - { - return X <= b.X && Y <= b.Y; - } - -public: - static void Add(const Int3& a, const Int3& b, Int3& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - result.Z = a.Z + b.Z; - } - - static Int3 Add(const Int3& a, const Int3& b) - { - Int3 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Int3& a, const Int3& b, Int3& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - result.Z = a.Z - b.Z; - } - - static Int3 Subtract(const Int3& a, const Int3& b) - { - Int3 result; - Subtract(a, b, result); - return result; - } - - static Int3 Multiply(const Int3& a, const Int3& b) - { - return Int3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); - } - - static Int3 Multiply(const Int3& a, int32 b) - { - return Int3(a.X * b, a.Y * b, a.Z * b); - } - - static Int3 Divide(const Int3& a, const Int3& b) - { - return Int3(a.X / b.X, a.Y / b.Y, a.Z / b.Z); - } - - static Int3 Divide(const Int3& a, int32 b) - { - return Int3(a.X / b, a.Y / b, a.Z / b); - } - -public: - /// - /// Gets a value indicting whether this vector is zero. - /// - /// True if the vector is zero, otherwise false. - bool IsZero() const - { - return X == 0 && Y == 0 && Z == 0; - } - - /// - /// Gets a value indicting whether any vector component is zero. - /// - /// True if a component is zero, otherwise false. - bool IsAnyZero() const - { - return X == 0 || Y == 0 || Z == 0; - } - - /// - /// Gets a value indicting whether this vector is one. - /// - /// True if the vector is one, otherwise false. - bool IsOne() const - { - return X == 1 && Y == 1 && Z == 1; - } - - /// - /// Calculates a vector with values being opposite to values of that vector - /// - /// Negative vector - Int3 GetNegative() const - { - return Int3(-X, -Y, -Z); - } - - /// - /// Returns average arithmetic of all the components - /// - /// Average arithmetic of all the components - float AverageArithmetic() const - { - return (X + Y + Z) / 3.0f; - } - - /// - /// Gets sum of all vector components values - /// - /// Sum of X, Y, Z and W - int32 SumValues() const - { - return X + Y + Z; - } - - /// - /// Returns minimum value of all the components - /// - /// Minimum value - int32 MinValue() const - { - return Math::Min(X, Y, Z); - } - - /// - /// Returns maximum value of all the components - /// - /// Maximum value - int32 MaxValue() const - { - return Math::Max(X, Y, Z); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - static Int3 Max(const Int3& a, const Int3& b) - { - return Int3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - static Int3 Min(const Int3& a, const Int3& b) - { - return Int3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static void Max(const Int3& a, const Int3& b, Int3& result) - { - result = Int3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static void Min(const Int3& a, const Int3& b, Int3 result) - { - result = Int3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); - } -}; - -template<> -struct TIsPODType -{ - enum { Value = true }; -}; - -DEFINE_DEFAULT_FORMATTING(Int3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z); +#include "Vector3.h" diff --git a/Source/Engine/Core/Math/Int4.cpp b/Source/Engine/Core/Math/Int4.cpp deleted file mode 100644 index 918bf16d9..000000000 --- a/Source/Engine/Core/Math/Int4.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" -#include "Vector2.h" -#include "Vector3.h" -#include "Vector4.h" -#include "Engine/Core/Types/String.h" - -static_assert(sizeof(Int4) == 16, "Invalid Int4 type size."); - -const Int4 Int4::Zero(0); -const Int4 Int4::One(1); -const Int4 Int4::Minimum(MIN_int32); -const Int4 Int4::Maximum(MAX_int32); - -Int4::Int4(const Int2& xy, int32 z, int32 w) - : X(xy.X) - , Y(xy.Y) - , Z(z) - , W(w) -{ -} - -Int4::Int4(const Int3& xyz, int32 w) - : X(xyz.X) - , Y(xyz.Y) - , Z(xyz.Z) - , W(w) -{ -} - -Int4::Int4(const Vector2& v, int32 z, int32 w) - : X(static_cast(v.X)) - , Y(static_cast(v.Y)) - , Z(z) - , W(w) -{ -} - -Int4::Int4(const Vector3& v, int32 w) - : X(static_cast(v.X)) - , Y(static_cast(v.Y)) - , Z(static_cast(v.Z)) - , W(w) -{ -} - -Int4::Int4(const Vector4& v) - : X(static_cast(v.X)) - , Y(static_cast(v.Y)) - , Z(static_cast(v.Z)) - , W(static_cast(v.W)) -{ -} - -String Int4::ToString() const -{ - return String::Format(TEXT("{}"), *this); -} diff --git a/Source/Engine/Core/Math/Int4.h b/Source/Engine/Core/Math/Int4.h index 0896cc05a..0ba849628 100644 --- a/Source/Engine/Core/Math/Int4.h +++ b/Source/Engine/Core/Math/Int4.h @@ -2,416 +2,4 @@ #pragma once -#include "Math.h" -#include "Engine/Core/Formatting.h" -#include "Engine/Core/Templates.h" - -/// -/// Four-components vector (32 bit integer type). -/// -API_STRUCT() struct FLAXENGINE_API Int4 -{ - DECLARE_SCRIPTING_TYPE_MINIMAL(Int4); -public: - union - { - struct - { - /// - /// The X component. - /// - API_FIELD() int32 X; - - /// - /// The Y component. - /// - API_FIELD() int32 Y; - - /// - /// The Z component. - /// - API_FIELD() int32 Z; - - /// - /// The W component. - /// - API_FIELD() int32 W; - }; - - // Raw values - int32 Raw[4]; - }; - -public: - // Vector with all components equal 0 - static const Int4 Zero; - - // Vector with all components equal 1 - static const Int4 One; - - // A minimum Int4 - static const Int4 Minimum; - - // A maximum Int4 - static const Int4 Maximum; - -public: - /// - /// Empty constructor. - /// - Int4() - { - } - - // Init - // @param xy Value to assign to the all components - Int4(int32 xyzw) - : X(xyzw) - , Y(xyzw) - , Z(xyzw) - , W(xyzw) - { - } - - // Init - // @param x X component value - // @param y Y component value - // @param z Z component value - // @param w W component value - Int4(int32 x, int32 y, int32 z, int32 w) - : X(x) - , Y(y) - , Z(z) - , W(w) - { - } - - // Init - // @param v Int2 to use X and Y components - // @param z Z component value - // @param w W component value - Int4(const Int2& xy, int32 z, int32 w); - - // Init - // @param v Int3 to use X , Y and Z components - // @param w W component value - Int4(const Int3& xyz, int32 w); - - // Init - // @param v Vector2 to use X and Y components - // @param z Z component value - // @param w W component value - explicit Int4(const Vector2& xy, int32 z, int32 w); - - // Init - // @param v Vector3 to use X , Y and Z components - // @param w W component value - explicit Int4(const Vector3& xyz, int32 w); - - // Init - // @param v Vector to use X, Y, Z and W components - explicit Int4(const Vector4& xyzw); - -public: - String ToString() const; - -public: - // Arithmetic operators with Int2 - - Int4 operator+(const Int4& b) const - { - return Add(*this, b); - } - - Int4 operator-(const Int4& b) const - { - return Subtract(*this, b); - } - - Int4 operator*(const Int4& b) const - { - return Multiply(*this, b); - } - - Int4 operator/(const Int4& b) const - { - return Divide(*this, b); - } - - Int4 operator-() const - { - return Int4(-X, -Y, -Z, -W); - } - - // op= operators with Int2 - - Int4& operator+=(const Int4& b) - { - *this = Add(*this, b); - return *this; - } - - Int4& operator-=(const Int4& b) - { - *this = Subtract(*this, b); - return *this; - } - - Int4& operator*=(const Int4& b) - { - *this = Multiply(*this, b); - return *this; - } - - Int4& operator/=(const Int4& b) - { - *this = Divide(*this, b); - return *this; - } - - // Arithmetic operators with int32 - - Int4 operator+(int32 b) const - { - return Add(*this, b); - } - - Int4 operator-(int32 b) const - { - return Subtract(*this, b); - } - - Int4 operator*(int32 b) const - { - return Multiply(*this, b); - } - - Int4 operator/(int32 b) const - { - return Divide(*this, b); - } - - // op= operators with int32 - - Int4& operator+=(int32 b) - { - *this = Add(*this, b); - return *this; - } - - Int4& operator-=(int32 b) - { - *this = Subtract(*this, b); - return *this; - } - - Int4& operator*=(int32 b) - { - *this = Multiply(*this, b); - return *this; - } - - Int4& operator/=(int32 b) - { - *this = Divide(*this, b); - return *this; - } - - // Comparison operators - - bool operator==(const Int4& b) const - { - return X == b.X && Y == b.Y; - } - - bool operator!=(const Int4& b) const - { - return X != b.X || Y != b.Y; - } - - bool operator>(const Int4& b) const - { - return X > b.X && Y > b.Y; - } - - bool operator>=(const Int4& b) const - { - return X >= b.X && Y >= b.Y; - } - - bool operator<(const Int4& b) const - { - return X < b.X && Y < b.Y; - } - - bool operator<=(const Int4& b) const - { - return X <= b.X && Y <= b.Y; - } - -public: - static void Add(const Int4& a, const Int4& b, Int4& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - result.Z = a.Z + b.Z; - result.W = a.W + b.W; - } - - static Int4 Add(const Int4& a, const Int4& b) - { - Int4 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Int4& a, const Int4& b, Int4& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - result.Z = a.Z - b.Z; - result.W = a.W - b.W; - } - - static Int4 Subtract(const Int4& a, const Int4& b) - { - Int4 result; - Subtract(a, b, result); - return result; - } - - static Int4 Multiply(const Int4& a, const Int4& b) - { - return Int4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W); - } - - static Int4 Multiply(const Int4& a, int32 b) - { - return Int4(a.X * b, a.Y * b, a.Z * b, a.W * b); - } - - static Int4 Divide(const Int4& a, const Int4& b) - { - return Int4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W); - } - - static Int4 Divide(const Int4& a, int32 b) - { - return Int4(a.X / b, a.Y / b, a.Z / b, a.Y / b); - } - -public: - /// - /// Gets a value indicting whether this vector is zero. - /// - /// True if the vector is zero, otherwise false. - bool IsZero() const - { - return X == 0 && Y == 0 && Z == 0 && W == 0; - } - - /// - /// Gets a value indicting whether any vector component is zero. - /// - /// True if a component is zero, otherwise false. - bool IsAnyZero() const - { - return X == 0 || Y == 0 || Z == 0 || W == 0; - } - - /// - /// Gets a value indicting whether this vector is one. - /// - /// True if the vector is one, otherwise false. - bool IsOne() const - { - return X == 1 && Y == 1 && Z == 1 && W == 1; - } - - /// - /// Calculates a vector with values being opposite to values of that vector - /// - /// Negative vector - Int4 GetNegative() const - { - return Int4(-X, -Y, -Z, -W); - } - - /// - /// Returns average arithmetic of all the components - /// - /// Average arithmetic of all the components - float AverageArithmetic() const - { - return (X + Y + Z + W) * 0.25f; - } - - /// - /// Gets sum of all vector components values - /// - /// Sum of X, Y, Z and W - int32 SumValues() const - { - return X + Y + Z + W; - } - - /// - /// Returns minimum value of all the components - /// - /// Minimum value - int32 MinValue() const - { - return Math::Min(X, Y, Z, W); - } - - /// - /// Returns maximum value of all the components - /// - /// Maximum value - int32 MaxValue() const - { - return Math::Max(X, Y, Z, W); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - static Int4 Max(const Int4& a, const Int4& b) - { - return Int4(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z, a.W > b.W ? a.W : b.W); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - static Int4 Min(const Int4& a, const Int4& b) - { - return Int4(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z, a.W < b.W ? a.W : b.W); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static void Max(const Int4& a, const Int4& b, Int4& result) - { - result = Int4(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z, a.W > b.W ? a.W : b.W); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static void Min(const Int4& a, const Int4& b, Int4& result) - { - result = Int4(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z, a.W < b.W ? a.W : b.W); - } -}; - -template<> -struct TIsPODType -{ - enum { Value = true }; -}; - -DEFINE_DEFAULT_FORMATTING(Int4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W); +#include "Vector4.h" diff --git a/Source/Engine/Core/Math/Math.h b/Source/Engine/Core/Math/Math.h index f5baa53ee..40a1fa835 100644 --- a/Source/Engine/Core/Math/Math.h +++ b/Source/Engine/Core/Math/Math.h @@ -631,7 +631,8 @@ namespace Math } // Given a heading which may be outside the +/- PI range, 'unwind' it back into that range - static float UnwindRadians(float a) + template + static T UnwindRadians(T a) { while (a > PI) a -= TWO_PI; @@ -641,12 +642,13 @@ namespace Math } // Utility to ensure angle is between +/- 180 degrees by unwinding - static float UnwindDegrees(float a) + template + static T UnwindDegrees(T a) { - while (a > 180.f) - a -= 360.f; - while (a < -180.f) - a += 360.f; + while (a > 180) + a -= 360; + while (a < -180) + a += 360; return a; } diff --git a/Source/Engine/Core/Math/Mathd.h b/Source/Engine/Core/Math/Mathd.h index 79be4cf65..8d8504a55 100644 --- a/Source/Engine/Core/Math/Mathd.h +++ b/Source/Engine/Core/Math/Mathd.h @@ -294,26 +294,6 @@ namespace Math return delta; } - // Given a heading which may be outside the +/- PI range, 'unwind' it back into that range - static double UnwindRadians(double a) - { - while (a > PI) - a -= TWO_PI; - while (a < -PI) - a += TWO_PI; - return a; - } - - // Utility to ensure angle is between +/- 180 degrees by unwinding - static double UnwindDegrees(double a) - { - while (a > 180.) - a -= 360.; - while (a < -180.) - a += 360.; - return a; - } - /// /// Returns value based on comparand. The main purpose of this function is to avoid branching based on floating point comparison which can be avoided via compiler intrinsics. /// diff --git a/Source/Engine/Core/Math/Matrix.cpp b/Source/Engine/Core/Math/Matrix.cpp index 039ab201b..cc5de58fb 100644 --- a/Source/Engine/Core/Math/Matrix.cpp +++ b/Source/Engine/Core/Math/Matrix.cpp @@ -611,7 +611,7 @@ void Matrix::CreateWorld(const Vector3& position, const Vector3& forward, const Vector3 vector3, vector31, vector32; Vector3::Normalize(forward, vector3); - vector3.Negate(); + vector3 = vector3.GetNegative(); Vector3::Normalize(Vector3::Cross(up, vector3), vector31); Vector3::Cross(vector3, vector31, vector32); diff --git a/Source/Engine/Core/Math/Matrix.cs b/Source/Engine/Core/Math/Matrix.cs index b00e8e619..ae4b18630 100644 --- a/Source/Engine/Core/Math/Matrix.cs +++ b/Source/Engine/Core/Math/Matrix.cs @@ -2899,7 +2899,7 @@ namespace FlaxEngine public static void CreateWorld(ref Vector3 position, ref Vector3 forward, ref Vector3 up, out Matrix result) { Vector3.Normalize(ref forward, out var vector3); - vector3.Negate(); + vector3 = vector3.Negative; Vector3 vector31 = Vector3.Cross(up, vector3); vector31.Normalize(); Vector3.Cross(ref vector3, ref vector31, out var vector32); diff --git a/Source/Engine/Core/Math/OrientedBoundingBox.cpp b/Source/Engine/Core/Math/OrientedBoundingBox.cpp index 593c8cb46..913fb921b 100644 --- a/Source/Engine/Core/Math/OrientedBoundingBox.cpp +++ b/Source/Engine/Core/Math/OrientedBoundingBox.cpp @@ -135,8 +135,7 @@ ContainmentType OrientedBoundingBox::Contains(const Vector3& point, float* dista // Get minimum distance to edge in local space Vector3 tmp; Vector3::Subtract(Extents, locPoint, tmp); - tmp.Absolute(); - const float minDstToEdgeLocal = tmp.MinValue(); + const float minDstToEdgeLocal = tmp.GetAbsolute().MinValue(); // Transform distance to world space Vector3 dstVec = Vector3::UnitX * minDstToEdgeLocal; diff --git a/Source/Engine/Core/Math/Quaternion.cpp b/Source/Engine/Core/Math/Quaternion.cpp index b03ab8133..0dc12bc20 100644 --- a/Source/Engine/Core/Math/Quaternion.cpp +++ b/Source/Engine/Core/Math/Quaternion.cpp @@ -71,9 +71,7 @@ Vector3 Quaternion::GetEuler() const result.Z = Math::Atan2(2.0f * q.X * q.Y + 2.0f * q.Z * q.W, 1 - 2.0f * (q.Y * q.Y + q.Z * q.Z)); } - result *= RadiansToDegrees; - result.UnwindEuler(); - return result; + return Math::UnwindDegrees(result * RadiansToDegrees); } void Quaternion::Multiply(const Quaternion& other) diff --git a/Source/Engine/Core/Math/Quaternion.cs b/Source/Engine/Core/Math/Quaternion.cs index 75e0b892c..ffeb795b6 100644 --- a/Source/Engine/Core/Math/Quaternion.cs +++ b/Source/Engine/Core/Math/Quaternion.cs @@ -221,8 +221,7 @@ namespace FlaxEngine } result *= Mathf.RadiansToDegrees; - result.UnwindEuler(); - return result; + return new Vector3(Mathf.UnwindDegrees(result.X), Mathf.UnwindDegrees(result.Y), Mathf.UnwindDegrees(result.Z)); } } diff --git a/Source/Engine/Core/Math/Quaternion.h b/Source/Engine/Core/Math/Quaternion.h index 53ac31e28..cbc6c787d 100644 --- a/Source/Engine/Core/Math/Quaternion.h +++ b/Source/Engine/Core/Math/Quaternion.h @@ -6,9 +6,6 @@ #include "Engine/Core/Formatting.h" #include "Engine/Core/Templates.h" -struct Vector2; -struct Vector3; -struct Vector4; struct Matrix; struct Matrix3x3; @@ -232,17 +229,6 @@ public: } } - /// - /// Reverses the direction of the quaternion. - /// - void Negate() - { - X = -X; - Y = -Y; - Z = -Z; - W = -W; - } - /// /// Converts the quaternion into a unit quaternion. /// diff --git a/Source/Engine/Core/Math/Transform.cpp b/Source/Engine/Core/Math/Transform.cpp index 45934bf48..c2a28b63c 100644 --- a/Source/Engine/Core/Math/Transform.cpp +++ b/Source/Engine/Core/Math/Transform.cpp @@ -2,6 +2,7 @@ #include "Transform.h" #include "Matrix.h" +#include "Vector2.h" #include "../Types/String.h" Transform Transform::Identity(Vector3(0, 0, 0)); @@ -70,13 +71,6 @@ Transform Transform::Subtract(const Transform& other) const return result; } -Transform Transform::LocalToWorld(const Transform& other) const -{ - Transform result; - LocalToWorld(other, result); - return result; -} - void Transform::LocalToWorld(const Transform& other, Transform& result) const { //Quaternion::Multiply(Orientation, other.Orientation, result.Orientation); @@ -128,13 +122,6 @@ void Transform::LocalToWorld(const Transform& other, Transform& result) const result.Translation = Vector3(tmp.X + Translation.X, tmp.Y + Translation.Y, tmp.Z + Translation.Z); } -Vector3 Transform::LocalToWorld(const Vector3& point) const -{ - Vector3 result = point * Scale; - Vector3::Transform(result, Orientation, result); - return result + Translation; -} - Vector3 Transform::LocalToWorldVector(const Vector3& vector) const { Vector3 result = vector * Scale; @@ -149,38 +136,6 @@ void Transform::LocalToWorld(const Vector3& point, Vector3& result) const Vector3::Add(tmp, Translation, result); } -void Transform::LocalToWorld(const Vector3* points, int32 pointsCount, Vector3* result) const -{ - for (int32 i = 0; i < pointsCount; i++) - { - result[i] = Vector3::Transform(points[i] * Scale, Orientation) + Translation; - } -} - -Transform Transform::WorldToLocal(const Transform& other) const -{ - Transform result; - - Vector3 invScale = Scale; - if (invScale.X != 0.0f) - invScale.X = 1.0f / invScale.X; - if (invScale.Y != 0.0f) - invScale.Y = 1.0f / invScale.Y; - if (invScale.Z != 0.0f) - invScale.Z = 1.0f / invScale.Z; - - const Quaternion invRotation = Orientation.Conjugated(); - - Quaternion::Multiply(invRotation, other.Orientation, result.Orientation); - result.Orientation.Normalize(); - Vector3::Multiply(other.Scale, invScale, result.Scale); - const Vector3 tmp = other.Translation - Translation; - Vector3::Transform(tmp, invRotation, result.Translation); - Vector3::Multiply(result.Translation, invScale, result.Translation); - - return result; -} - void Transform::WorldToLocal(const Transform& other, Transform& result) const { Vector3 invScale = Scale; @@ -201,7 +156,7 @@ void Transform::WorldToLocal(const Transform& other, Transform& result) const Vector3::Multiply(result.Translation, invScale, result.Translation); } -Vector3 Transform::WorldToLocal(const Vector3& point) const +void Transform::WorldToLocal(const Vector3& point, Vector3& result) const { Vector3 invScale = Scale; if (invScale.X != 0.0f) @@ -210,13 +165,10 @@ Vector3 Transform::WorldToLocal(const Vector3& point) const invScale.Y = 1.0f / invScale.Y; if (invScale.Z != 0.0f) invScale.Z = 1.0f / invScale.Z; - const Quaternion invRotation = Orientation.Conjugated(); - - Vector3 result = point - Translation; + result = point - Translation; Vector3::Transform(result, invRotation, result); - - return result * invScale; + result *= invScale; } Vector3 Transform::WorldToLocalVector(const Vector3& vector) const @@ -237,26 +189,6 @@ Vector3 Transform::WorldToLocalVector(const Vector3& vector) const return result * invScale; } -void Transform::WorldToLocal(const Vector3* points, int32 pointsCount, Vector3* result) const -{ - Vector3 invScale = Scale; - if (invScale.X != 0.0f) - invScale.X = 1.0f / invScale.X; - if (invScale.Y != 0.0f) - invScale.Y = 1.0f / invScale.Y; - if (invScale.Z != 0.0f) - invScale.Z = 1.0f / invScale.Z; - - const Quaternion invRotation = Orientation.Conjugated(); - - for (int32 i = 0; i < pointsCount; i++) - { - result[i] = points[i] - Translation; - Vector3::Transform(result[i], invRotation, result[i]); - result[i] *= invScale; - } -} - Transform Transform::Lerp(const Transform& t1, const Transform& t2, float amount) { Transform result; diff --git a/Source/Engine/Core/Math/Transform.h b/Source/Engine/Core/Math/Transform.h index bcfd57ea4..8caa6ef2c 100644 --- a/Source/Engine/Core/Math/Transform.h +++ b/Source/Engine/Core/Math/Transform.h @@ -85,18 +85,16 @@ public: public: /// - /// Checks if transform is an identity transformation + /// Checks if transform is an identity transformation. /// - /// True if is identity, otherwise false bool IsIdentity() const { return Translation.IsZero() && Orientation.IsIdentity() && Scale.IsOne(); } /// - /// Returns true if transform has one or more components equal to +/- infinity or NaN + /// Returns true if transform has one or more components equal to +/- infinity or NaN. /// - /// True if one or more components equal to +/- infinity or NaN bool IsNanOrInfinity() const { return Translation.IsNanOrInfinity() || Orientation.IsNanOrInfinity() || Scale.IsNanOrInfinity(); @@ -105,7 +103,6 @@ public: /// /// Calculates the determinant of this transformation. /// - /// The determinant. FORCE_INLINE float GetDeterminant() const { return Scale.X * Scale.Y * Scale.Z; @@ -113,31 +110,31 @@ public: public: /// - /// Gets rotation matrix (from Orientation) + /// Gets rotation matrix (from Orientation). /// /// Rotation matrix Matrix GetRotation() const; /// - /// Gets rotation matrix (from Orientation) + /// Gets rotation matrix (from Orientation). /// /// Matrix to set void GetRotation(Matrix& result) const; /// - /// Sets rotation matrix (from Orientation) + /// Sets rotation matrix (from Orientation). /// /// Rotation matrix void SetRotation(const Matrix& value); /// - /// Gets world matrix that describes transformation as a 4 by 4 matrix + /// Gets world matrix that describes transformation as a 4 by 4 matrix. /// /// World matrix Matrix GetWorld() const; /// - /// Gets world matrix that describes transformation as a 4 by 4 matrix + /// Gets world matrix that describes transformation as a 4 by 4 matrix. /// /// World matrix void GetWorld(Matrix& result) const; @@ -169,7 +166,12 @@ public: /// /// The local space transformation. /// The world space transformation. - Transform LocalToWorld(const Transform& other) const; + Transform LocalToWorld(const Transform& other) const + { + Transform result; + LocalToWorld(other, result); + return result; + } /// /// Performs transformation of the given transform in local space to the world space of this transform. @@ -183,7 +185,12 @@ public: /// /// The local space point. /// The world space point. - Vector3 LocalToWorld(const Vector3& point) const; + Vector3 LocalToWorld(const Vector3& point) const + { + Vector3 result; + LocalToWorld(point, result); + return result; + } /// /// Performs transformation of the given vector in local space to the world space of this transform. @@ -199,20 +206,17 @@ public: /// The world space point. void LocalToWorld(const Vector3& point, Vector3& result) const; - /// - /// Performs transformation of the given points in local space to the world space of this transform. - /// - /// The local space points. - /// The amount of the points. - /// The world space points. - void LocalToWorld(const Vector3* points, int32 pointsCount, Vector3* result) const; - /// /// Performs transformation of the given transform in local space to the world space of this transform. /// /// The world space transformation. /// The local space transformation. - Transform WorldToLocal(const Transform& other) const; + Transform WorldToLocal(const Transform& other) const + { + Transform result; + WorldToLocal(other, result); + return result; + } /// /// Performs transformation of the given transform in world space to the local space of this transform. @@ -221,12 +225,24 @@ public: /// The local space transformation. void WorldToLocal(const Transform& other, Transform& result) const; + /// + /// Performs transformation of the given point in world space to the local space of this transform. + /// + /// The world space point. + /// The local space point. + void WorldToLocal(const Vector3& point, Vector3& result) const; + /// /// Performs transformation of the given point in world space to the local space of this transform. /// /// The world space point. /// The local space point. - Vector3 WorldToLocal(const Vector3& point) const; + Vector3 WorldToLocal(const Vector3& point) const + { + Vector3 result; + WorldToLocal(point, result); + return result; + } /// /// Performs transformation of the given vector in world space to the local space of this transform. @@ -235,14 +251,6 @@ public: /// The local space vector. Vector3 WorldToLocalVector(const Vector3& vector) const; - /// - /// Performs transformation of the given points in world space to the local space of this transform. - /// - /// The world space points. - /// The amount of the points. - /// The local space points. - void WorldToLocal(const Vector3* points, int32 pointsCount, Vector3* result) const; - public: FORCE_INLINE Transform operator*(const Transform& other) const { diff --git a/Source/Engine/Core/Math/Vector2.cpp b/Source/Engine/Core/Math/Vector2.cpp index 480ffa54f..16695388c 100644 --- a/Source/Engine/Core/Math/Vector2.cpp +++ b/Source/Engine/Core/Math/Vector2.cpp @@ -1,117 +1,265 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. -#include "Double2.h" -#include "Double3.h" -#include "Double4.h" #include "Vector2.h" #include "Vector3.h" #include "Vector4.h" #include "Color.h" -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" #include "../Types/String.h" -static_assert(sizeof(Vector2) == 8, "Invalid Vector2 type size."); +// Float -const Vector2 Vector2::Zero(0); -const Vector2 Vector2::One(1); -const Vector2 Vector2::UnitX(1, 0); -const Vector2 Vector2::UnitY(0, 1); -const Vector2 Vector2::Minimum(MIN_float); -const Vector2 Vector2::Maximum(MAX_float); +static_assert(sizeof(Float2) == 8, "Invalid Float2 type size."); -Vector2::Vector2(const Int2& xy) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) +template<> +const Float2 Float2::Zero(0.0f); +template<> +const Float2 Float2::One(1.0f); +template<> +const Float2 Float2::UnitX(1.0f, 0.0f); +template<> +const Float2 Float2::UnitY(0.0f, 1.0f); +template<> +const Float2 Float2::Minimum(MIN_float); +template<> +const Float2 Float2::Maximum(MAX_float); + +template<> +Float2::Vector2Base(const Int3& xy) + : X((float)xy.X) + , Y((float)xy.Y) { } -Vector2::Vector2(const Int3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) +template<> +Float2::Vector2Base(const Int4& xy) + : X((float)xy.X) + , Y((float)xy.Y) { } -Vector2::Vector2(const Int4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) +template<> +Float2::Vector2Base(const Float3& xy) + : X(xy.X) + , Y(xy.Y) { } -Vector2::Vector2(const Vector3& xyz) - : X(xyz.X) - , Y(xyz.Y) +template<> +Float2::Vector2Base(const Float4& xy) + : X(xy.X) + , Y(xy.Y) { } -Vector2::Vector2(const Vector4& xyzw) - : X(xyzw.X) - , Y(xyzw.Y) +template<> +Float2::Vector2Base(const Double3& xy) + : X((float)xy.X) + , Y((float)xy.Y) { } -Vector2::Vector2(const Double2& xy) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) +template<> +Float2::Vector2Base(const Double4& xy) + : X((float)xy.X) + , Y((float)xy.Y) { } -Vector2::Vector2(const Double3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) -{ -} - -Vector2::Vector2(const Double4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) -{ -} - -Vector2::Vector2(const Color& color) +template<> +Float2::Vector2Base(const Color& color) : X(color.R) , Y(color.G) { } -String Vector2::ToString() const +template<> +String Float2::ToString() const { return String::Format(TEXT("{}"), *this); } -Vector2 Vector2::Normalize(const Vector2& v) -{ - Vector2 result = v; - const float length = v.Length(); - if (!Math::IsZero(length)) - { - const float inv = 1.0f / length; - result.X *= inv; - result.Y *= inv; - } - return result; -} - -Int2 Vector2::CeilToInt(const Vector2& v) -{ - return Int2(Math::CeilToInt(v.X), Math::CeilToInt(v.Y)); -} - -Int2 Vector2::FloorToInt(const Vector2& v) -{ - return Int2(Math::FloorToInt(v.X), Math::FloorToInt(v.Y)); -} - -float Vector2::TriangleArea(const Vector2& v0, const Vector2& v1, const Vector2& v2) +template<> +float Float2::TriangleArea(const Float2& v0, const Float2& v1, const Float2& v2) { return Math::Abs((v0.X * (v1.Y - v2.Y) + v1.X * (v2.Y - v0.Y) + v2.X * (v0.Y - v1.Y)) / 2); } -float Vector2::Angle(const Vector2& from, const Vector2& to) +template<> +float Float2::Angle(const Float2& from, const Float2& to) { const float dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0f, 1.0f); - if (Math::Abs(dot) > (1.0f - ZeroTolerance)) + if (Math::Abs(dot) > 1.0f - ZeroTolerance) return dot > 0.0f ? 0.0f : PI; return Math::Acos(dot); } + +// Double + +static_assert(sizeof(Double2) == 16, "Invalid Double2 type size."); + +template<> +const Double2 Double2::Zero(0.0); +template<> +const Double2 Double2::One(1.0); +template<> +const Double2 Double2::UnitX(1.0, 0.0); +template<> +const Double2 Double2::UnitY(0.0, 1.0); +template<> +const Double2 Double2::Minimum(MIN_double); +template<> +const Double2 Double2::Maximum(MAX_double); + +template<> +Double2::Vector2Base(const Int3& xy) + : X((double)xy.X) + , Y((double)xy.Y) +{ +} + +template<> +Double2::Vector2Base(const Int4& xy) + : X((double)xy.X) + , Y((double)xy.Y) +{ +} + +template<> +Double2::Vector2Base(const Float3& xy) + : X((double)xy.X) + , Y((double)xy.Y) +{ +} + +template<> +Double2::Vector2Base(const Float4& xy) + : X((int32)xy.X) + , Y((double)xy.Y) +{ +} + +template<> +Double2::Vector2Base(const Double3& xy) + : X(xy.X) + , Y(xy.Y) +{ +} + +template<> +Double2::Vector2Base(const Double4& xy) + : X(xy.X) + , Y(xy.Y) +{ +} + +template<> +Double2::Vector2Base(const Color& color) + : X((double)color.R) + , Y((double)color.G) +{ +} + +template<> +String Double2::ToString() const +{ + return String::Format(TEXT("{}"), *this); +} + +template<> +double Double2::TriangleArea(const Double2& v0, const Double2& v1, const Double2& v2) +{ + return Math::Abs((v0.X * (v1.Y - v2.Y) + v1.X * (v2.Y - v0.Y) + v2.X * (v0.Y - v1.Y)) / 2); +} + +template<> +double Double2::Angle(const Double2& from, const Double2& to) +{ + const double dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0, 1.0); + if (Math::Abs(dot) > 1.0 - ZeroTolerance) + return dot > 0.0 ? 0.0 : PI; + return Math::Acos(dot); +} + +// Int + +static_assert(sizeof(Int2) == 8, "Invalid Int2 type size."); + +template<> +const Int2 Int2::Zero(0); +template<> +const Int2 Int2::One(1); +template<> +const Int2 Int2::UnitX(1, 0); +template<> +const Int2 Int2::UnitY(0, 1); +template<> +const Int2 Int2::Minimum(MIN_int32); +template<> +const Int2 Int2::Maximum(MAX_int32); + +template<> +Int2::Vector2Base(const Int3& xy) + : X(xy.X) + , Y(xy.Y) +{ +} + +template<> +Int2::Vector2Base(const Int4& xy) + : X(xy.X) + , Y(xy.Y) +{ +} + +template<> +Int2::Vector2Base(const Float3& xy) + : X((int32)xy.X) + , Y((int32)xy.Y) +{ +} + +template<> +Int2::Vector2Base(const Float4& xy) + : X((int32)xy.X) + , Y((int32)xy.Y) +{ +} + +template<> +Int2::Vector2Base(const Double3& xy) + : X((int32)xy.X) + , Y((int32)xy.Y) +{ +} + +template<> +Int2::Vector2Base(const Double4& xy) + : X((int32)xy.X) + , Y((int32)xy.Y) +{ +} + +template<> +Int2::Vector2Base(const Color& color) + : X((int32)color.R) + , Y((int32)color.G) +{ +} + +template<> +String Int2::ToString() const +{ + return String::Format(TEXT("{}"), *this); +} + +template<> +int32 Int2::TriangleArea(const Int2& v0, const Int2& v1, const Int2& v2) +{ + return Math::Abs((v0.X * (v1.Y - v2.Y) + v1.X * (v2.Y - v0.Y) + v2.X * (v0.Y - v1.Y)) / 2); +} + +template<> +int32 Int2::Angle(const Int2& from, const Int2& to) +{ + return 0; +} diff --git a/Source/Engine/Core/Math/Vector2.cs b/Source/Engine/Core/Math/Vector2.cs index 09839c052..ecc3d9f91 100644 --- a/Source/Engine/Core/Math/Vector2.cs +++ b/Source/Engine/Core/Math/Vector2.cs @@ -57,6 +57,24 @@ using System.Runtime.InteropServices; namespace FlaxEngine { + /// + /// Represents a two dimensional mathematical vector. + /// + [Unmanaged] + [StructLayout(LayoutKind.Sequential)] + public unsafe partial struct Vector2 + { + /// + /// The X component. + /// + public float X; + + /// + /// The Y component. + /// + public float Y; + } + [Serializable] [TypeConverter(typeof(TypeConverters.Vector2Converter))] partial struct Vector2 : IEquatable, IFormattable diff --git a/Source/Engine/Core/Math/Vector2.h b/Source/Engine/Core/Math/Vector2.h index 0bf004124..809f63191 100644 --- a/Source/Engine/Core/Math/Vector2.h +++ b/Source/Engine/Core/Math/Vector2.h @@ -3,27 +3,21 @@ #pragma once #include "Math.h" +#include "Mathd.h" #include "Engine/Core/Formatting.h" #include "Engine/Core/Templates.h" -struct Double2; -struct Double3; -struct Double4; -struct Vector3; -struct Vector4; -struct Int2; -struct Int3; -struct Int4; -struct Color; -struct Matrix; +#include /// -/// Represents a two dimensional mathematical vector with 32-bit precision (per-component). +/// Represents a two dimensional mathematical vector. /// -API_STRUCT() struct FLAXENGINE_API Vector2 +template +API_STRUCT(Template) struct Vector2Base { - DECLARE_SCRIPTING_TYPE_MINIMAL(Vector2); -public: + typedef T Real; + static struct ScriptingTypeInitializer TypeInitializer; + union { struct @@ -31,325 +25,82 @@ public: /// /// The X component of the vector. /// - API_FIELD() float X; + API_FIELD() T X; /// /// The Y component of the vector. /// - API_FIELD() float Y; + API_FIELD() T Y; }; - // Raw values - float Raw[2]; + /// + /// The raw vector values (in XY order). + /// + T Raw[2]; }; public: // Vector with all components equal 0 - static const Vector2 Zero; + static FLAXENGINE_API const Vector2Base Zero; // Vector with all components equal 1 - static const Vector2 One; + static FLAXENGINE_API const Vector2Base One; // Vector X=1, Y=0 - static const Vector2 UnitX; + static FLAXENGINE_API const Vector2Base UnitX; // Vector X=0, Y=1 - static const Vector2 UnitY; + static FLAXENGINE_API const Vector2Base UnitY; - // A minimum Vector2 - static const Vector2 Minimum; + // Vector with all components equal maximum value. + static FLAXENGINE_API const Vector2Base Minimum; - // A maximum Vector2 - static const Vector2 Maximum; + // Vector with all components equal minimum value. + static FLAXENGINE_API const Vector2Base Maximum; public: /// /// Empty constructor. /// - Vector2() + Vector2Base() { } - // Init - // @param xy Value to assign to the all components - Vector2(float xy) + FORCE_INLINE Vector2Base(T xy) : X(xy) , Y(xy) { } - // Init - // @param x X component value - // @param y Y component value - Vector2(float x, float y) + FORCE_INLINE explicit Vector2Base(const T* xy) + : X(xy[0]) + , Y(xy[1]) + { + } + + FORCE_INLINE Vector2Base(T x, T y) : X(x) , Y(y) { } - explicit Vector2(const Int2& xy); - explicit Vector2(const Int3& xyz); - explicit Vector2(const Int4& xyzw); - explicit Vector2(const Vector3& xyz); - explicit Vector2(const Vector4& xyzw); - Vector2(const Double2& xy); - explicit Vector2(const Double3& xyz); - explicit Vector2(const Double4& xyzw); - explicit Vector2(const Color& color); + template>::Value>::Type...> + FORCE_INLINE explicit Vector2Base(const Vector2Base& xy) + : X((T)xy.X) + , Y((T)xy.Y) + { + } + + FLAXENGINE_API explicit Vector2Base(const Int3& xy); + FLAXENGINE_API explicit Vector2Base(const Int4& xy); + FLAXENGINE_API explicit Vector2Base(const Float3& xy); + FLAXENGINE_API explicit Vector2Base(const Float4& xy); + FLAXENGINE_API explicit Vector2Base(const Double3& xy); + FLAXENGINE_API explicit Vector2Base(const Double4& xy); + FLAXENGINE_API explicit Vector2Base(const Color& color); public: - String ToString() const; - -public: - // Arithmetic operators with Vector2 - Vector2 operator+(const Vector2& b) const - { - return Add(*this, b); - } - - Vector2 operator-(const Vector2& b) const - { - return Subtract(*this, b); - } - - Vector2 operator*(const Vector2& b) const - { - return Multiply(*this, b); - } - - Vector2 operator/(const Vector2& b) const - { - return Divide(*this, b); - } - - Vector2 operator-() const - { - return Vector2(-X, -Y); - } - - // op= operators with Vector2 - Vector2& operator+=(const Vector2& b) - { - *this = Add(*this, b); - return *this; - } - - Vector2& operator-=(const Vector2& b) - { - *this = Subtract(*this, b); - return *this; - } - - Vector2& operator*=(const Vector2& b) - { - *this = Multiply(*this, b); - return *this; - } - - Vector2& operator/=(const Vector2& b) - { - *this = Divide(*this, b); - return *this; - } - - // Arithmetic operators with float - Vector2 operator+(float b) const - { - return Add(*this, b); - } - - Vector2 operator-(float b) const - { - return Subtract(*this, b); - } - - Vector2 operator*(float b) const - { - return Multiply(*this, b); - } - - Vector2 operator/(float b) const - { - return Divide(*this, b); - } - - // op= operators with float - Vector2& operator+=(float b) - { - *this = Add(*this, b); - return *this; - } - - Vector2& operator-=(float b) - { - *this = Subtract(*this, b); - return *this; - } - - Vector2& operator*=(float b) - { - *this = Multiply(*this, b); - return *this; - } - - Vector2& operator/=(float b) - { - *this = Divide(*this, b); - return *this; - } - - // Comparison operators - bool operator==(const Vector2& b) const - { - return X == b.X && Y == b.Y; - } - - bool operator!=(const Vector2& b) const - { - return X != b.X || Y != b.Y; - } - - bool operator>(const Vector2& b) const - { - return X > b.X && Y > b.Y; - } - - bool operator>=(const Vector2& b) const - { - return X >= b.X && Y >= b.Y; - } - - bool operator<(const Vector2& b) const - { - return X < b.X && Y < b.Y; - } - - bool operator<=(const Vector2& b) const - { - return X <= b.X && Y <= b.Y; - } - -public: - static bool NearEqual(const Vector2& a, const Vector2& b) - { - return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y); - } - - static bool NearEqual(const Vector2& a, const Vector2& b, float epsilon) - { - return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon); - } - -public: - static float Dot(const Vector2& a, const Vector2& b) - { - return a.X * b.X + a.Y * b.Y; - } - - static float Cross(const Vector2& a, const Vector2& b) - { - return a.X * b.Y - a.Y * b.X; - } - - static void Add(const Vector2& a, const Vector2& b, Vector2& result) - { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - } - - static Vector2 Add(const Vector2& a, const Vector2& b) - { - Vector2 result; - Add(a, b, result); - return result; - } - - static void Subtract(const Vector2& a, const Vector2& b, Vector2& result) - { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - } - - static Vector2 Subtract(const Vector2& a, const Vector2& b) - { - Vector2 result; - Subtract(a, b, result); - return result; - } - - static Vector2 Multiply(const Vector2& a, const Vector2& b) - { - return Vector2(a.X * b.X, a.Y * b.Y); - } - - static Vector2 Multiply(const Vector2& a, float b) - { - return Vector2(a.X * b, a.Y * b); - } - - static Vector2 Divide(const Vector2& a, const Vector2& b) - { - return Vector2(a.X / b.X, a.Y / b.Y); - } - - static Vector2 Divide(const Vector2& a, float b) - { - return Vector2(a.X / b, a.Y / b); - } - - // Calculates distance between two points in 2D - // @param a 1st point - // @param b 2nd point - // @returns Distance - static float Distance(const Vector2& a, const Vector2& b) - { - const float x = a.X - b.X; - const float y = a.Y - b.Y; - return Math::Sqrt(x * x + y * y); - } - - // Calculates the squared distance between two points in 2D - // @param a 1st point - // @param b 2nd point - // @returns Distance - static float DistanceSquared(const Vector2& a, const Vector2& b) - { - const float x = a.X - b.X; - const float y = a.Y - b.Y; - return x * x + y * y; - } - - // Clamp vector values within given range - // @param v Vector to clamp - // @param min Minimum value - // @param max Maximum value - // @returns Clamped vector - static Vector2 Clamp(const Vector2& v, float min, float max) - { - return Vector2(Math::Clamp(v.X, min, max), Math::Clamp(v.Y, min, max)); - } - - // Clamp vector values within given range - // @param v Vector to clamp - // @param min Minimum value - // @param max Maximum value - // @returns Clamped vector - static Vector2 Clamp(const Vector2& v, const Vector2& min, const Vector2& max) - { - return Vector2(Math::Clamp(v.X, min.X, max.X), Math::Clamp(v.Y, min.Y, max.Y)); - } - - // Performs vector normalization (scales vector up to unit length) - void Normalize() - { - const float length = Length(); - if (!Math::IsZero(length)) - { - const float invLength = 1.0f / length; - X *= invLength; - Y *= invLength; - } - } + FLAXENGINE_API String ToString() const; public: // Gets a value indicting whether this instance is normalized. @@ -377,39 +128,27 @@ public: } // Calculates the length of the vector. - float Length() const + T Length() const { return Math::Sqrt(X * X + Y * Y); } // Calculates the squared length of the vector. - float LengthSquared() const + T LengthSquared() const { return X * X + Y * Y; } // Calculates inverted length of the vector (1 / length). - float InvLength() const + T InvLength() const { return 1.0f / Length(); } - // Calculates a vector with values being absolute values of that vector. - Vector2 GetAbsolute() const - { - return Vector2(Math::Abs(X), Math::Abs(Y)); - } - - // Calculates a vector with values being opposite to values of that vector. - Vector2 GetNegative() const - { - return Vector2(-X, -Y); - } - /// /// Returns the average arithmetic of all the components. /// - float AverageArithmetic() const + T AverageArithmetic() const { return (X + Y) * 0.5f; } @@ -417,7 +156,7 @@ public: /// /// Gets the sum of all vector components values. /// - float SumValues() const + T SumValues() const { return X + Y; } @@ -425,7 +164,7 @@ public: /// /// Gets the multiplication result of all vector components values. /// - float MulValues() const + T MulValues() const { return X * Y; } @@ -433,7 +172,7 @@ public: /// /// Returns the minimum value of all the components. /// - float MinValue() const + T MinValue() const { return Math::Min(X, Y); } @@ -441,7 +180,7 @@ public: /// /// Returns the maximum value of all the components. /// - float MaxValue() const + T MaxValue() const { return Math::Max(X, Y); } @@ -470,13 +209,322 @@ public: return IsInfinity() || IsNaN(); } + /// + /// Calculates a vector with values being absolute values of that vector. + /// + Vector2Base GetAbsolute() const + { + return Vector2Base(Math::Abs(X), Math::Abs(Y)); + } + + /// + /// Calculates a vector with values being opposite to values of that vector. + /// + Vector2Base GetNegative() const + { + return Vector2Base(-X, -Y); + } + public: + /// + /// Performs vector normalization (scales vector up to unit length). + /// + void Normalize() + { + const T length = Math::Sqrt(X * X + Y * Y); + if (!Math::IsZero(length)) + { + const T invLength = 1.0f / length; + X *= invLength; + Y *= invLength; + } + } + +public: + Vector2Base operator+(const Vector2Base& b) const + { + return Vector2Base(X + b.X, Y + b.Y); + } + + Vector2Base operator-(const Vector2Base& b) const + { + return Vector2Base(X - b.X, Y - b.Y); + } + + Vector2Base operator*(const Vector2Base& b) const + { + return Vector2Base(X * b.X, Y * b.Y); + } + + Vector2Base operator/(const Vector2Base& b) const + { + return Vector2Base(X / b.X, Y / b.Y); + } + + Vector2Base operator-() const + { + return Vector2Base(-X, -Y); + } + + Vector2Base operator+(T b) const + { + return Vector2Base(X + b, Y + b); + } + + Vector2Base operator-(T b) const + { + return Vector2Base(X - b, Y - b); + } + + Vector2Base operator*(T b) const + { + return Vector2Base(X * b, Y * b); + } + + Vector2Base operator/(T b) const + { + return Vector2Base(X / b, Y / b); + } + + Vector2Base& operator+=(const Vector2Base& b) + { + X += b.X; + Y += b.Y; + return *this; + } + + Vector2Base& operator-=(const Vector2Base& b) + { + X -= b.X; + Y -= b.Y; + return *this; + } + + Vector2Base& operator*=(const Vector2Base& b) + { + X *= b.X; + Y *= b.Y; + return *this; + } + + Vector2Base& operator/=(const Vector2Base& b) + { + X /= b.X; + Y /= b.Y; + return *this; + } + + Vector2Base& operator+=(T b) + { + X += b; + Y += b; + return *this; + } + + Vector2Base& operator-=(T b) + { + X -= b; + Y -= b; + return *this; + } + + Vector2Base& operator*=(T b) + { + X *= b; + Y *= b; + return *this; + } + + Vector2Base& operator/=(T b) + { + X /= b; + Y /= b; + return *this; + } + + bool operator==(const Vector2Base& b) const + { + return X == b.X && Y == b.Y; + } + + bool operator!=(const Vector2Base& b) const + { + return X != b.X || Y != b.Y; + } + + bool operator>(const Vector2Base& b) const + { + return X > b.X && Y > b.Y; + } + + bool operator>=(const Vector2Base& b) const + { + return X >= b.X && Y >= b.Y; + } + + bool operator<(const Vector2Base& b) const + { + return X < b.X && Y < b.Y; + } + + bool operator<=(const Vector2Base& b) const + { + return X <= b.X && Y <= b.Y; + } + +public: + static bool NearEqual(const Vector2Base& a, const Vector2Base& b) + { + return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y); + } + + static bool NearEqual(const Vector2Base& a, const Vector2Base& b, T epsilon) + { + return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon); + } + +public: + static T Dot(const Vector2Base& a, const Vector2Base& b) + { + return a.X * b.X + a.Y * b.Y; + } + + static T Cross(const Vector2Base& a, const Vector2Base& b) + { + return a.X * b.Y - a.Y * b.X; + } + + static void Add(const Vector2Base& a, const Vector2Base& b, Vector2Base& result) + { + result = Vector2Base(a.X + b.X, a.Y + b.Y); + } + + static void Subtract(const Vector2Base& a, const Vector2Base& b, Vector2Base& result) + { + result = Vector2Base(a.X - b.X, a.Y - b.Y); + } + + static void Multiply(const Vector2Base& a, const Vector2Base& b, Vector2Base& result) + { + result = Vector2Base(a.X * b.X, a.Y * b.Y); + } + + static void Divide(const Vector2Base& a, const Vector2Base& b, Vector2Base& result) + { + result = Vector2Base(a.X / b.X, a.Y / b.Y); + } + + static void Min(const Vector2Base& a, const Vector2Base& b, Vector2Base& result) + { + result = Vector2Base(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); + } + + static void Max(const Vector2Base& a, const Vector2Base& b, Vector2Base& result) + { + result = Vector2Base(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); + } + +public: + static Vector2Base Min(const Vector2Base& a, const Vector2Base& b) + { + return Vector2Base(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); + } + + static Vector2Base Max(const Vector2Base& a, const Vector2Base& b) + { + return Vector2Base(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); + } + + static Vector2Base Floor(const Vector2Base& v) + { + return Vector2Base(Math::Floor(v.X), Math::Floor(v.Y)); + } + + static Vector2Base Frac(const Vector2Base& v) + { + return Vector3(v.X - (int32)v.X, v.Y - (int32)v.Y); + } + + static Vector2Base Round(const Vector2Base& v) + { + return Vector2Base(Math::Round(v.X), Math::Round(v.Y)); + } + + static Vector2Base Ceil(const Vector2Base& v) + { + return Vector2Base(Math::Ceil(v.X), Math::Ceil(v.Y)); + } + + static Vector2Base Abs(const Vector2Base& v) + { + return Vector2Base(Math::Abs(v.X), Math::Abs(v.Y)); + } + +public: + // Clamp vector values within given range + // @param v Vector to clamp + // @param min Minimum value + // @param max Maximum value + // @returns Clamped vector + static Vector2Base Clamp(const Vector2Base& v, const Vector2Base& min, const Vector2Base& max) + { + Vector2Base result; + Clamp(v, min, max, result); + return result; + } + + // Restricts a value to be within a specified range + // @param v The value to clamp + // @param min The minimum value, + // @param max The maximum value + // @param result When the method completes, contains the clamped value + static void Clamp(const Vector2Base& v, const Vector2Base& min, const Vector2Base& max, Vector2Base& result) + { + result = Vector2Base(Math::Clamp(v.X, min.X, max.X), Math::Clamp(v.Y, min.Y, max.Y)); + } + + // Calculates distance between two points in 2D + // @param a 1st point + // @param b 2nd point + // @returns Distance + static T Distance(const Vector2Base& a, const Vector2Base& b) + { + const T x = a.X - b.X; + const T y = a.Y - b.Y; + return Math::Sqrt(x * x + y * y); + } + + // Calculates the squared distance between two points in 2D + // @param a 1st point + // @param b 2nd point + // @returns Distance + static T DistanceSquared(const Vector2Base& a, const Vector2Base& b) + { + const T x = a.X - b.X; + const T y = a.Y - b.Y; + return x * x + y * y; + } + + // Performs vector normalization (scales vector up to unit length). + static Vector2Base Normalize(const Vector2Base& v) + { + Vector2Base r = v; + const T length = Math::Sqrt(r.X * r.X + r.Y * r.Y); + if (Math::Abs(length) >= ZeroTolerance) + { + const T inv = 1.0f / length; + r.X *= inv; + r.Y *= inv; + } + return r; + } + // Performs a linear interpolation between two vectors // @param start Start vector // @param end End vector // @param amount Value between 0 and 1 indicating the weight of end // @param result When the method completes, contains the linear interpolation of the two vectors - static void Lerp(const Vector2& start, const Vector2& end, float amount, Vector2& result) + static void Lerp(const Vector2Base& start, const Vector2Base& end, T amount, Vector2Base& result) { result.X = Math::Lerp(start.X, end.X, amount); result.Y = Math::Lerp(start.Y, end.Y, amount); @@ -489,76 +537,13 @@ public: // @param end End vector, // @param amount Value between 0 and 1 indicating the weight of @paramref end"/>, // @returns The linear interpolation of the two vectors - static Vector2 Lerp(const Vector2& start, const Vector2& end, float amount) + static Vector2Base Lerp(const Vector2Base& start, const Vector2Base& end, T amount) { - Vector2 result; + Vector2Base result; Lerp(start, end, amount, result); return result; } - static Vector2 Abs(const Vector2& v) - { - return Vector2(Math::Abs(v.X), Math::Abs(v.Y)); - } - - // Creates vector from minimum components of two vectors - static Vector2 Min(const Vector2& a, const Vector2& b) - { - return Vector2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); - } - - // Creates vector from minimum components of two vectors - static void Min(const Vector2& a, const Vector2& b, Vector2& result) - { - result = Vector2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y); - } - - // Creates vector from maximum components of two vectors - static Vector2 Max(const Vector2& a, const Vector2& b) - { - return Vector2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); - } - - // Creates vector from maximum components of two vectors - static void Max(const Vector2& a, const Vector2& b, Vector2& result) - { - result = Vector2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y); - } - - // Returns normalized vector - static Vector2 Normalize(const Vector2& v); - - static Vector2 Round(const Vector2& v) - { - return Vector2(Math::Round(v.X), Math::Round(v.Y)); - } - - static Vector2 Ceil(const Vector2& v) - { - return Vector2(Math::Ceil(v.X), Math::Ceil(v.Y)); - } - - static Vector2 Floor(const Vector2& v) - { - return Vector2(Math::Floor(v.X), Math::Floor(v.Y)); - } - - static Vector2 Frac(const Vector2& v) - { - return Vector2(v.X - (int32)v.X, v.Y - (int32)v.Y); - } - - static Int2 CeilToInt(const Vector2& v); - static Int2 FloorToInt(const Vector2& v); - - static Vector2 Mod(const Vector2& v) - { - return Vector2( - (float)(v.X - (int32)v.X), - (float)(v.Y - (int32)v.Y) - ); - } - public: /// /// Calculates the area of the triangle. @@ -567,7 +552,7 @@ public: /// The second triangle vertex. /// The third triangle vertex. /// The triangle area. - static float TriangleArea(const Vector2& v0, const Vector2& v1, const Vector2& v2); + FLAXENGINE_API static T TriangleArea(const Vector2Base& v0, const Vector2Base& v1, const Vector2Base& v2); /// /// Calculates the angle (in radians) between from and to. This is always the smallest value. @@ -575,41 +560,62 @@ public: /// The first vector. /// The second vector. /// The angle (in radians). - static float Angle(const Vector2& from, const Vector2& to); + FLAXENGINE_API static T Angle(const Vector2Base& from, const Vector2Base& to); }; -inline Vector2 operator+(float a, const Vector2& b) +template +inline Vector2Base operator+(T a, const Vector2Base& b) { return b + a; } -inline Vector2 operator-(float a, const Vector2& b) +template +inline Vector2Base operator-(T a, const Vector2Base& b) { - return Vector2(a) - b; + return Vector2Base(a) - b; } -inline Vector2 operator*(float a, const Vector2& b) +template +inline Vector2Base operator*(T a, const Vector2Base& b) { return b * a; } -inline Vector2 operator/(float a, const Vector2& b) +template +inline Vector2Base operator/(T a, const Vector2Base& b) { - return Vector2(a) / b; + return Vector2Base(a) / b; } namespace Math { - FORCE_INLINE static bool NearEqual(const Vector2& a, const Vector2& b) + template + FORCE_INLINE static bool NearEqual(const Vector2Base& a, const Vector2Base& b) { - return Vector2::NearEqual(a, b); + return Vector2Base::NearEqual(a, b); } } template<> -struct TIsPODType +struct TIsPODType { enum { Value = true }; }; -DEFINE_DEFAULT_FORMATTING(Vector2, "X:{0} Y:{1}", v.X, v.Y); +DEFINE_DEFAULT_FORMATTING(Float2, "X:{0} Y:{1}", v.X, v.Y); + +template<> +struct TIsPODType +{ + enum { Value = true }; +}; + +DEFINE_DEFAULT_FORMATTING(Double2, "X:{0} Y:{1}", v.X, v.Y); + +template<> +struct TIsPODType +{ + enum { Value = true }; +}; + +DEFINE_DEFAULT_FORMATTING(Int2, "X:{0} Y:{1}", v.X, v.Y); diff --git a/Source/Engine/Core/Math/Vector3.cpp b/Source/Engine/Core/Math/Vector3.cpp index 567e107f6..3dc500a83 100644 --- a/Source/Engine/Core/Math/Vector3.cpp +++ b/Source/Engine/Core/Math/Vector3.cpp @@ -1,138 +1,119 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. -#include "Double2.h" -#include "Double3.h" -#include "Double4.h" -#include "Vector2.h" #include "Vector3.h" +#include "Vector2.h" #include "Vector4.h" #include "Color.h" #include "Quaternion.h" #include "Matrix.h" #include "Matrix3x3.h" -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" #include "../Types/String.h" -static_assert(sizeof(Vector3) == 12, "Invalid Vector3 type size."); +// Float -const Vector3 Vector3::Zero(0.0f); -const Vector3 Vector3::One(1.0f); -const Vector3 Vector3::Half(0.5f); -const Vector3 Vector3::UnitX(1.0f, 0.0f, 0.0f); -const Vector3 Vector3::UnitY(0.0f, 1.0f, 0.0f); -const Vector3 Vector3::UnitZ(0.0f, 0.0f, 1.0f); -const Vector3 Vector3::Up(0.0f, 1.0f, 0.0f); -const Vector3 Vector3::Down(0.0f, -1.0f, 0.0f); -const Vector3 Vector3::Left(-1.0f, 0.0f, 0.0f); -const Vector3 Vector3::Right(1.0f, 0.0f, 0.0f); -const Vector3 Vector3::Forward(0.0f, 0.0f, 1.0f); -const Vector3 Vector3::Backward(0.0f, 0.0f, -1.0f); -const Vector3 Vector3::Minimum(MIN_float); -const Vector3 Vector3::Maximum(MAX_float); +static_assert(sizeof(Float3) == 12, "Invalid Float3 type size."); -Vector3::Vector3(const Vector2& xy, float z) +template<> +const Float3 Float3::Zero(0.0f); +template<> +const Float3 Float3::One(1.0f); +template<> +const Float3 Float3::Half(0.5f); +template<> +const Float3 Float3::UnitX(1.0f, 0.0f, 0.0f); +template<> +const Float3 Float3::UnitY(0.0f, 1.0f, 0.0f); +template<> +const Float3 Float3::UnitZ(0.0f, 0.0f, 1.0f); +template<> +const Float3 Float3::Up(0.0f, 1.0f, 0.0f); +template<> +const Float3 Float3::Down(0.0f, -1.0f, 0.0f); +template<> +const Float3 Float3::Left(-1.0f, 0.0f, 0.0f); +template<> +const Float3 Float3::Right(1.0f, 0.0f, 0.0f); +template<> +const Float3 Float3::Forward(0.0f, 0.0f, 1.0f); +template<> +const Float3 Float3::Backward(0.0f, 0.0f, -1.0f); +template<> +const Float3 Float3::Minimum(MIN_float); +template<> +const Float3 Float3::Maximum(MAX_float); + +template<> +Float3::Vector3Base(const Float2& xy, float z) : X(xy.X) , Y(xy.Y) , Z(z) { } -Vector3::Vector3(const Vector2& xy) - : X(xy.X) - , Y(xy.Y) +template<> +Float3::Vector3Base(const Double2& xy, float z) + : X((float)xy.X) + , Y((float)xy.Y) , Z(0) { } -Vector3::Vector3(const Int2& xy, float z) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) - , Z(static_cast(z)) +template<> +Float3::Vector3Base(const Int2& xy, float z) + : X((float)xy.X) + , Y((float)xy.Y) + , Z(z) { } -Vector3::Vector3(const Int3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) +template<> +Float3::Vector3Base(const Int3& xyz) + : X((float)xyz.X) + , Y((float)xyz.Y) + , Z((float)xyz.Z) { } -Vector3::Vector3(const Int4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.Z)) +template<> +Float3::Vector3Base(const Int4& xyz) + : X((float)xyz.X) + , Y((float)xyz.Y) + , Z((float)xyz.Z) { } -Vector3::Vector3(const Vector4& xyz) +template<> +Float3::Vector3Base(const Vector4& xyz) : X(xyz.X) , Y(xyz.Y) , Z(xyz.Z) { } -Vector3::Vector3(const Double2& xy, float z) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) - , Z(z) +template<> +Float3::Vector3Base(const Double4& xyz) + : X((float)xyz.X) + , Y((float)xyz.Y) + , Z((float)xyz.Z) { } -Vector3::Vector3(const Double3& xyz) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) -{ -} - -Vector3::Vector3(const Double4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.Z)) -{ -} - -Vector3::Vector3(const Color& color) +template<> +Float3::Vector3Base(const Color& color) : X(color.R) , Y(color.G) , Z(color.B) { } -String Vector3::ToString() const +template<> +String Float3::ToString() const { return String::Format(TEXT("{}"), *this); } -void Vector3::UnwindEuler() -{ - X = Math::UnwindDegrees(X); - Y = Math::UnwindDegrees(Y); - Z = Math::UnwindDegrees(Z); -} - -Vector3 Vector3::Floor(const Vector3& v) -{ - return Vector3( - Math::Floor(v.X), - Math::Floor(v.Y), - Math::Floor(v.Z) - ); -} - -Vector3 Vector3::Frac(const Vector3& v) -{ - return Vector3( - v.X - (int32)v.X, - v.Y - (int32)v.Y, - v.Z - (int32)v.Z - ); -} - -void Vector3::Hermite(const Vector3& value1, const Vector3& tangent1, const Vector3& value2, const Vector3& tangent2, float amount, Vector3& result) +template<> +void Float3::Hermite(const Float3& value1, const Float3& tangent1, const Float3& value2, const Float3& tangent2, float amount, Float3& result) { const float squared = amount * amount; const float cubed = amount * squared; @@ -140,21 +121,22 @@ void Vector3::Hermite(const Vector3& value1, const Vector3& tangent1, const Vect const float part2 = -2.0f * cubed + 3.0f * squared; const float part3 = cubed - 2.0f * squared + amount; const float part4 = cubed - squared; - result.X = value1.X * part1 + value2.X * part2 + tangent1.X * part3 + tangent2.X * part4; result.Y = value1.Y * part1 + value2.Y * part2 + tangent1.Y * part3 + tangent2.Y * part4; result.Z = value1.Z * part1 + value2.Z * part2 + tangent1.Z * part3 + tangent2.Z * part4; } -void Vector3::Reflect(const Vector3& vector, const Vector3& normal, Vector3& result) +template<> +void Float3::Reflect(const Float3& vector, const Float3& normal, Float3& result) { - const float dot = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z; + const Real dot = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z; result.X = vector.X - 2.0f * dot * normal.X; result.Y = vector.Y - 2.0f * dot * normal.Y; result.Z = vector.Z - 2.0f * dot * normal.Z; } -void Vector3::Transform(const Vector3& vector, const Quaternion& rotation, Vector3& result) +template<> +void Float3::Transform(const Float3& vector, const Quaternion& rotation, Float3& result) { const float x = rotation.X + rotation.X; const float y = rotation.Y + rotation.Y; @@ -168,14 +150,14 @@ void Vector3::Transform(const Vector3& vector, const Quaternion& rotation, Vecto const float yy = rotation.Y * y; const float yz = rotation.Y * z; const float zz = rotation.Z * z; - - result = Vector3( + result = Float3( vector.X * (1.0f - yy - zz) + vector.Y * (xy - wz) + vector.Z * (xz + wy), vector.X * (xy + wz) + vector.Y * (1.0f - xx - zz) + vector.Z * (yz - wx), vector.X * (xz - wy) + vector.Y * (yz + wx) + vector.Z * (1.0f - xx - yy)); } -Vector3 Vector3::Transform(const Vector3& vector, const Quaternion& rotation) +template<> +Float3 Float3::Transform(const Float3& vector, const Quaternion& rotation) { const float x = rotation.X + rotation.X; const float y = rotation.Y + rotation.Y; @@ -189,71 +171,71 @@ Vector3 Vector3::Transform(const Vector3& vector, const Quaternion& rotation) const float yy = rotation.Y * y; const float yz = rotation.Y * z; const float zz = rotation.Z * z; - - return Vector3( + return Float3( vector.X * (1.0f - yy - zz) + vector.Y * (xy - wz) + vector.Z * (xz + wy), vector.X * (xy + wz) + vector.Y * (1.0f - xx - zz) + vector.Z * (yz - wx), vector.X * (xz - wy) + vector.Y * (yz + wx) + vector.Z * (1.0f - xx - yy)); } -void Vector3::Transform(const Vector3& vector, const Matrix& transform, Vector4& result) +template<> +void Float3::Transform(const Float3& vector, const Matrix& transform, Float4& result) { - result = Vector4( + result = Float4( vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43, vector.X * transform.M14 + vector.Y * transform.M24 + vector.Z * transform.M34 + transform.M44); } -void Vector3::Transform(const Vector3& vector, const Matrix& transform, Vector3& result) +template<> +void Float3::Transform(const Float3& vector, const Matrix& transform, Float3& result) { - result = Vector3( + result = Float3( vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); } -void Vector3::Transform(const Vector3* vectors, const Matrix& transform, Vector3* results, int32 vectorsCount) +template<> +void Float3::Transform(const Float3& vector, const Matrix3x3& transform, Float3& result) { - for (int32 i = 0; i < vectorsCount; i++) - Transform(vectors[i], transform, results[i]); -} - -void Vector3::Transform(const Vector3& vector, const Matrix3x3& transform, Vector3& result) -{ - result = Vector3( + result = Float3( vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31, vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32, vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33); } -Vector3 Vector3::Transform(const Vector3& vector, const Matrix& transform) +template<> +Float3 Float3::Transform(const Float3& vector, const Matrix& transform) { - return Vector3( + return Float3( vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); } -void Vector3::TransformCoordinate(const Vector3& coordinate, const Matrix& transform, Vector3& result) +template<> +void Float3::TransformCoordinate(const Float3& coordinate, const Matrix& transform, Float3& result) { - Vector4 vector; - vector.X = coordinate.X * transform.M11 + coordinate.Y * transform.M21 + coordinate.Z * transform.M31 + transform.M41; - vector.Y = coordinate.X * transform.M12 + coordinate.Y * transform.M22 + coordinate.Z * transform.M32 + transform.M42; - vector.Z = coordinate.X * transform.M13 + coordinate.Y * transform.M23 + coordinate.Z * transform.M33 + transform.M43; - vector.W = 1.0f / (coordinate.X * transform.M14 + coordinate.Y * transform.M24 + coordinate.Z * transform.M34 + transform.M44); - result = Vector3(vector.X * vector.W, vector.Y * vector.W, vector.Z * vector.W); + Float4 v; + v.X = coordinate.X * transform.M11 + coordinate.Y * transform.M21 + coordinate.Z * transform.M31 + transform.M41; + v.Y = coordinate.X * transform.M12 + coordinate.Y * transform.M22 + coordinate.Z * transform.M32 + transform.M42; + v.Z = coordinate.X * transform.M13 + coordinate.Y * transform.M23 + coordinate.Z * transform.M33 + transform.M43; + v.W = 1.0f / (coordinate.X * transform.M14 + coordinate.Y * transform.M24 + coordinate.Z * transform.M34 + transform.M44); + result = Float3(v.X * v.W, v.Y * v.W, v.Z * v.W); } -void Vector3::TransformNormal(const Vector3& normal, const Matrix& transform, Vector3& result) +template<> +void Float3::TransformNormal(const Float3& normal, const Matrix& transform, Float3& result) { - result = Vector3( + result = Float3( normal.X * transform.M11 + normal.Y * transform.M21 + normal.Z * transform.M31, normal.X * transform.M12 + normal.Y * transform.M22 + normal.Z * transform.M32, normal.X * transform.M13 + normal.Y * transform.M23 + normal.Z * transform.M33); } -Vector3 Vector3::Project(const Vector3& vector, const Vector3& onNormal) +template<> +Float3 Float3::Project(const Float3& vector, const Float3& onNormal) { const float sqrMag = Dot(onNormal, onNormal); if (sqrMag < ZeroTolerance) @@ -261,63 +243,559 @@ Vector3 Vector3::Project(const Vector3& vector, const Vector3& onNormal) return onNormal * Dot(vector, onNormal) / sqrMag; } -void Vector3::Project(const Vector3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Vector3& result) +template<> +void Float3::Project(const Float3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Float3& result) { - Vector3 v; + Float3 v; TransformCoordinate(vector, worldViewProjection, v); - - result = Vector3((1.0f + v.X) * 0.5f * width + x, (1.0f - v.Y) * 0.5f * height + y, v.Z * (maxZ - minZ) + minZ); + result = Float3((1.0f + v.X) * 0.5f * width + x, (1.0f - v.Y) * 0.5f * height + y, v.Z * (maxZ - minZ) + minZ); } -void Vector3::Unproject(const Vector3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Vector3& result) +template<> +void Float3::Unproject(const Float3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Float3& result) { Matrix matrix; Matrix::Invert(worldViewProjection, matrix); - - const Vector3 v = Vector3((vector.X - x) / width * 2.0f - 1.0f, -((vector.Y - y) / height * 2.0f - 1.0f), (vector.Z - minZ) / (maxZ - minZ)); - + const Float3 v((vector.X - x) / width * 2.0f - 1.0f, -((vector.Y - y) / height * 2.0f - 1.0f), (vector.Z - minZ) / (maxZ - minZ)); TransformCoordinate(v, matrix, result); } -void Vector3::CreateOrthonormalBasis(Vector3& xAxis, Vector3& yAxis, Vector3& zAxis) +template<> +void Float3::CreateOrthonormalBasis(Float3& xAxis, Float3& yAxis, Float3& zAxis) { xAxis -= (xAxis | zAxis) / (zAxis | zAxis) * zAxis; yAxis -= (yAxis | zAxis) / (zAxis | zAxis) * zAxis; - if (xAxis.LengthSquared() < ZeroTolerance) xAxis = yAxis ^ zAxis; if (yAxis.LengthSquared() < ZeroTolerance) yAxis = xAxis ^ zAxis; - xAxis.Normalize(); yAxis.Normalize(); zAxis.Normalize(); } -void Vector3::FindBestAxisVectors(Vector3& firstAxis, Vector3& secondAxis) const +template<> +void Float3::FindBestAxisVectors(Float3& firstAxis, Float3& secondAxis) const { const float absX = Math::Abs(X); const float absY = Math::Abs(Y); const float absZ = Math::Abs(Z); - if (absZ > absX && absZ > absY) - firstAxis = Vector3(1, 0, 0); + firstAxis = Float3(1, 0, 0); else - firstAxis = Vector3(0, 0, 1); - + firstAxis = Float3(0, 0, 1); firstAxis = (firstAxis - *this * (firstAxis | *this)).GetNormalized(); secondAxis = firstAxis ^ *this; } -float Vector3::TriangleArea(const Vector3& v0, const Vector3& v1, const Vector3& v2) +template<> +float Float3::TriangleArea(const Float3& v0, const Float3& v1, const Float3& v2) { return (v2 - v0 ^ v1 - v0).Length() * 0.5f; } -float Vector3::Angle(const Vector3& from, const Vector3& to) +template<> +float Float3::Angle(const Float3& from, const Float3& to) { const float dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0f, 1.0f); - if (Math::Abs(dot) > (1.0f - ZeroTolerance)) + if (Math::Abs(dot) > 1.0f - ZeroTolerance) return dot > 0.0f ? 0.0f : PI; return Math::Acos(dot); } + +// Double + +static_assert(sizeof(Double3) == 24, "Invalid Double3 type size."); + +template<> +const Double3 Double3::Zero(0.0); +template<> +const Double3 Double3::One(1.0); +template<> +const Double3 Double3::Half(0.5); +template<> +const Double3 Double3::UnitX(1.0, 0.0, 0.0); +template<> +const Double3 Double3::UnitY(0.0, 1.0, 0.0); +template<> +const Double3 Double3::UnitZ(0.0, 0.0, 1.0); +template<> +const Double3 Double3::Up(0.0, 1.0, 0.0); +template<> +const Double3 Double3::Down(0.0, -1.0, 0.0); +template<> +const Double3 Double3::Left(-1.0, 0.0, 0.0); +template<> +const Double3 Double3::Right(1.0, 0.0, 0.0); +template<> +const Double3 Double3::Forward(0.0, 0.0, 1.0); +template<> +const Double3 Double3::Backward(0.0, 0.0, -1.0); +template<> +const Double3 Double3::Minimum(MIN_double); +template<> +const Double3 Double3::Maximum(MAX_double); + +template<> +Double3::Vector3Base(const Float2& xy, double z) + : X((double)xy.X) + , Y((double)xy.Y) + , Z(z) +{ +} + +template<> +Double3::Vector3Base(const Double2& xy, double z) + : X(xy.X) + , Y(xy.Y) + , Z(0) +{ +} + +template<> +Double3::Vector3Base(const Int2& xy, double z) + : X((double)xy.X) + , Y((double)xy.Y) + , Z(z) +{ +} + +template<> +Double3::Vector3Base(const Int3& xyz) + : X((double)xyz.X) + , Y((double)xyz.Y) + , Z((double)xyz.Z) +{ +} + +template<> +Double3::Vector3Base(const Int4& xyz) + : X((double)xyz.X) + , Y((double)xyz.Y) + , Z((double)xyz.Z) +{ +} + +template<> +Double3::Vector3Base(const Float4& xyz) + : X((double)xyz.X) + , Y((double)xyz.Y) + , Z((double)xyz.Z) +{ +} + +template<> +Double3::Vector3Base(const Double4& xyz) + : X(xyz.X) + , Y(xyz.Y) + , Z(xyz.Z) +{ +} + +template<> +Double3::Vector3Base(const Color& color) + : X((double)color.R) + , Y((double)color.G) + , Z((double)color.B) +{ +} + +template<> +String Double3::ToString() const +{ + return String::Format(TEXT("{}"), *this); +} + +template<> +void Double3::Hermite(const Double3& value1, const Double3& tangent1, const Double3& value2, const Double3& tangent2, double amount, Double3& result) +{ + const double squared = amount * amount; + const double cubed = amount * squared; + const double part1 = 2.0 * cubed - 3.0 * squared + 1.0; + const double part2 = -2.0 * cubed + 3.0 * squared; + const double part3 = cubed - 2.0 * squared + amount; + const double part4 = cubed - squared; + result.X = value1.X * part1 + value2.X * part2 + tangent1.X * part3 + tangent2.X * part4; + result.Y = value1.Y * part1 + value2.Y * part2 + tangent1.Y * part3 + tangent2.Y * part4; + result.Z = value1.Z * part1 + value2.Z * part2 + tangent1.Z * part3 + tangent2.Z * part4; +} + +template<> +void Double3::Reflect(const Double3& vector, const Double3& normal, Double3& result) +{ + const double dot = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z; + result.X = vector.X - 2.0 * dot * normal.X; + result.Y = vector.Y - 2.0 * dot * normal.Y; + result.Z = vector.Z - 2.0 * dot * normal.Z; +} + +template<> +void Double3::Transform(const Double3& vector, const Quaternion& rotation, Double3& result) +{ + const float x = rotation.X + rotation.X; + const float y = rotation.Y + rotation.Y; + const float z = rotation.Z + rotation.Z; + const float wx = rotation.W * x; + const float wy = rotation.W * y; + const float wz = rotation.W * z; + const float xx = rotation.X * x; + const float xy = rotation.X * y; + const float xz = rotation.X * z; + const float yy = rotation.Y * y; + const float yz = rotation.Y * z; + const float zz = rotation.Z * z; + result = Double3( + vector.X * (1.0f - yy - zz) + vector.Y * (xy - wz) + vector.Z * (xz + wy), + vector.X * (xy + wz) + vector.Y * (1.0f - xx - zz) + vector.Z * (yz - wx), + vector.X * (xz - wy) + vector.Y * (yz + wx) + vector.Z * (1.0f - xx - yy)); +} + +template<> +Double3 Double3::Transform(const Double3& vector, const Quaternion& rotation) +{ + const float x = rotation.X + rotation.X; + const float y = rotation.Y + rotation.Y; + const float z = rotation.Z + rotation.Z; + const float wx = rotation.W * x; + const float wy = rotation.W * y; + const float wz = rotation.W * z; + const float xx = rotation.X * x; + const float xy = rotation.X * y; + const float xz = rotation.X * z; + const float yy = rotation.Y * y; + const float yz = rotation.Y * z; + const float zz = rotation.Z * z; + return Double3( + vector.X * double(1.0f - yy - zz) + vector.Y * double(xy - wz) + vector.Z * double(xz + wy), + vector.X * double(xy + wz) + vector.Y * double(1.0f - xx - zz) + vector.Z * double(yz - wx), + vector.X * double(xz - wy) + vector.Y * double(yz + wx) + vector.Z * double(1.0f - xx - yy)); +} + +template<> +void Double3::Transform(const Double3& vector, const Matrix& transform, Double4& result) +{ + result = Double4( + vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, + vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, + vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43, + vector.X * transform.M14 + vector.Y * transform.M24 + vector.Z * transform.M34 + transform.M44); +} + +template<> +void Double3::Transform(const Double3& vector, const Matrix& transform, Double3& result) +{ + result = Double3( + vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, + vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, + vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); +} + +template<> +void Double3::Transform(const Double3& vector, const Matrix3x3& transform, Double3& result) +{ + result = Double3( + vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31, + vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32, + vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33); +} + +template<> +Double3 Double3::Transform(const Double3& vector, const Matrix& transform) +{ + return Double3( + vector.X * transform.M11 + vector.Y * transform.M21 + vector.Z * transform.M31 + transform.M41, + vector.X * transform.M12 + vector.Y * transform.M22 + vector.Z * transform.M32 + transform.M42, + vector.X * transform.M13 + vector.Y * transform.M23 + vector.Z * transform.M33 + transform.M43); +} + +template<> +void Double3::TransformCoordinate(const Double3& coordinate, const Matrix& transform, Double3& result) +{ + Double4 v; + v.X = coordinate.X * transform.M11 + coordinate.Y * transform.M21 + coordinate.Z * transform.M31 + transform.M41; + v.Y = coordinate.X * transform.M12 + coordinate.Y * transform.M22 + coordinate.Z * transform.M32 + transform.M42; + v.Z = coordinate.X * transform.M13 + coordinate.Y * transform.M23 + coordinate.Z * transform.M33 + transform.M43; + v.W = 1.0 / (coordinate.X * transform.M14 + coordinate.Y * transform.M24 + coordinate.Z * transform.M34 + transform.M44); + result = Double3(v.X * v.W, v.Y * v.W, v.Z * v.W); +} + +template<> +void Double3::TransformNormal(const Double3& normal, const Matrix& transform, Double3& result) +{ + result = Double3( + normal.X * transform.M11 + normal.Y * transform.M21 + normal.Z * transform.M31, + normal.X * transform.M12 + normal.Y * transform.M22 + normal.Z * transform.M32, + normal.X * transform.M13 + normal.Y * transform.M23 + normal.Z * transform.M33); +} + +template<> +Double3 Double3::Project(const Double3& vector, const Double3& onNormal) +{ + const Real sqrMag = Dot(onNormal, onNormal); + if (sqrMag < ZeroTolerance) + return Zero; + return onNormal * Dot(vector, onNormal) / sqrMag; +} + +template<> +void Double3::Project(const Double3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Double3& result) +{ + Double3 v; + TransformCoordinate(vector, worldViewProjection, v); + result = Double3((1.0f + v.X) * 0.5f * width + x, (1.0f - v.Y) * 0.5f * height + y, v.Z * (maxZ - minZ) + minZ); +} + +template<> +void Double3::Unproject(const Double3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Double3& result) +{ + Matrix matrix; + Matrix::Invert(worldViewProjection, matrix); + const Double3 v((vector.X - x) / width * 2.0f - 1.0f, -((vector.Y - y) / height * 2.0f - 1.0f), (vector.Z - minZ) / (maxZ - minZ)); + TransformCoordinate(v, matrix, result); +} + +template<> +void Double3::CreateOrthonormalBasis(Double3& xAxis, Double3& yAxis, Double3& zAxis) +{ + xAxis -= (xAxis | zAxis) / (zAxis | zAxis) * zAxis; + yAxis -= (yAxis | zAxis) / (zAxis | zAxis) * zAxis; + if (xAxis.LengthSquared() < ZeroTolerance) + xAxis = yAxis ^ zAxis; + if (yAxis.LengthSquared() < ZeroTolerance) + yAxis = xAxis ^ zAxis; + xAxis.Normalize(); + yAxis.Normalize(); + zAxis.Normalize(); +} + +template<> +void Double3::FindBestAxisVectors(Double3& firstAxis, Double3& secondAxis) const +{ + const double absX = Math::Abs(X); + const double absY = Math::Abs(Y); + const double absZ = Math::Abs(Z); + if (absZ > absX && absZ > absY) + firstAxis = Double3(1, 0, 0); + else + firstAxis = Double3(0, 0, 1); + firstAxis = (firstAxis - *this * (firstAxis | *this)).GetNormalized(); + secondAxis = firstAxis ^ *this; +} + +template<> +double Double3::TriangleArea(const Double3& v0, const Double3& v1, const Double3& v2) +{ + return (v2 - v0 ^ v1 - v0).Length() * 0.5; +} + +template<> +double Double3::Angle(const Double3& from, const Double3& to) +{ + const double dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0, 1.0); + if (Math::Abs(dot) > 1.0 - ZeroTolerance) + return dot > 0.0 ? 0.0 : PI; + return Math::Acos(dot); +} + +// Int + +static_assert(sizeof(Int3) == 12, "Invalid Int3 type size."); + +template<> +const Int3 Int3::Zero(0); +template<> +const Int3 Int3::One(1); +template<> +const Int3 Int3::Half(1); +template<> +const Int3 Int3::UnitX(1, 0, 0); +template<> +const Int3 Int3::UnitY(0, 1, 0); +template<> +const Int3 Int3::UnitZ(0, 0, 1); +template<> +const Int3 Int3::Up(0, 1, 0); +template<> +const Int3 Int3::Down(0, -1, 0); +template<> +const Int3 Int3::Left(-1, 0, 0); +template<> +const Int3 Int3::Right(1, 0, 0); +template<> +const Int3 Int3::Forward(0, 0, 1); +template<> +const Int3 Int3::Backward(0, 0, -1); +template<> +const Int3 Int3::Minimum(MIN_int32); +template<> +const Int3 Int3::Maximum(MAX_int32); + +template<> +Int3::Vector3Base(const Float2& xy, int32 z) + : X((int32)xy.X) + , Y((int32)xy.Y) + , Z(z) +{ +} + +template<> +Int3::Vector3Base(const Double2& xy, int32 z) + : X((int32)xy.X) + , Y((int32)xy.Y) + , Z(0) +{ +} + +template<> +Int3::Vector3Base(const Int2& xy, int32 z) + : X(xy.X) + , Y(xy.Y) + , Z(z) +{ +} + +template<> +Int3::Vector3Base(const Int3& xyz) + : X(xyz.X) + , Y(xyz.Y) + , Z(xyz.Z) +{ +} + +template<> +Int3::Vector3Base(const Int4& xyz) + : X(xyz.X) + , Y(xyz.Y) + , Z(xyz.Z) +{ +} + +template<> +Int3::Vector3Base(const Float4& xyz) + : X((int32)xyz.X) + , Y((int32)xyz.Y) + , Z((int32)xyz.Z) +{ +} + +template<> +Int3::Vector3Base(const Double4& xyz) + : X((int32)xyz.X) + , Y((int32)xyz.Y) + , Z((int32)xyz.Z) +{ +} + +template<> +Int3::Vector3Base(const Color& color) + : X((int32)color.R) + , Y((int32)color.G) + , Z((int32)color.B) +{ +} + +template<> +String Int3::ToString() const +{ + return String::Format(TEXT("{}"), *this); +} + +template<> +void Int3::Hermite(const Int3& value1, const Int3& tangent1, const Int3& value2, const Int3& tangent2, int32 amount, Int3& result) +{ + result = value1; +} + +template<> +void Int3::Reflect(const Int3& vector, const Int3& normal, Int3& result) +{ + result = vector; +} + +template<> +void Int3::Transform(const Int3& vector, const Quaternion& rotation, Int3& result) +{ + result = vector; +} + +template<> +Int3 Int3::Transform(const Int3& vector, const Quaternion& rotation) +{ + return vector; +} + +template<> +void Int3::Transform(const Int3& vector, const Matrix& transform, Int4& result) +{ + result = Int4(vector); +} + +template<> +void Int3::Transform(const Int3& vector, const Matrix& transform, Int3& result) +{ + result = vector; +} + +template<> +void Int3::Transform(const Int3& vector, const Matrix3x3& transform, Int3& result) +{ + result = vector; +} + +template<> +Int3 Int3::Transform(const Int3& vector, const Matrix& transform) +{ + return vector; +} + +template<> +void Int3::TransformCoordinate(const Int3& coordinate, const Matrix& transform, Int3& result) +{ + result = coordinate; +} + +template<> +void Int3::TransformNormal(const Int3& normal, const Matrix& transform, Int3& result) +{ + result = normal; +} + +template<> +Int3 Int3::Project(const Int3& vector, const Int3& onNormal) +{ + return Zero; +} + +template<> +void Int3::Project(const Int3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Int3& result) +{ + result = vector; +} + +template<> +void Int3::Unproject(const Int3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Int3& result) +{ + result = vector; +} + +template<> +void Int3::CreateOrthonormalBasis(Int3& xAxis, Int3& yAxis, Int3& zAxis) +{ +} + +template<> +void Int3::FindBestAxisVectors(Int3& firstAxis, Int3& secondAxis) const +{ +} + +template<> +int32 Int3::TriangleArea(const Int3& v0, const Int3& v1, const Int3& v2) +{ + return 0; +} + +template<> +int32 Int3::Angle(const Int3& from, const Int3& to) +{ + return 0; +} diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs index 4868a2d4f..233ca7578 100644 --- a/Source/Engine/Core/Math/Vector3.cs +++ b/Source/Engine/Core/Math/Vector3.cs @@ -57,6 +57,29 @@ using System.Runtime.InteropServices; namespace FlaxEngine { + /// + /// Represents a three dimensional mathematical vector. + /// + [Unmanaged] + [StructLayout(LayoutKind.Sequential)] + public unsafe partial struct Vector3 + { + /// + /// The X component. + /// + public float X; + + /// + /// The Y component. + /// + public float Y; + + /// + /// The Z component. + /// + public float Z; + } + [Serializable] [TypeConverter(typeof(TypeConverters.Vector3Converter))] partial struct Vector3 : IEquatable, IFormattable @@ -326,26 +349,6 @@ namespace FlaxEngine } } - /// - /// Reverses the direction of the vector. - /// - public void Negate() - { - X *= -1; - Y *= -1; - Z *= -1; - } - - /// - /// When this vector contains Euler angles (degrees), ensure that angles are between +/-180 - /// - public void UnwindEuler() - { - X = Mathf.UnwindDegrees(X); - Y = Mathf.UnwindDegrees(Y); - Z = Mathf.UnwindDegrees(Z); - } - /// /// Creates an array containing the elements of the vector. /// diff --git a/Source/Engine/Core/Math/Vector3.h b/Source/Engine/Core/Math/Vector3.h index 82d7b6ea5..b320c2104 100644 --- a/Source/Engine/Core/Math/Vector3.h +++ b/Source/Engine/Core/Math/Vector3.h @@ -3,29 +3,19 @@ #pragma once #include "Math.h" +#include "Mathd.h" #include "Engine/Core/Formatting.h" #include "Engine/Core/Templates.h" -struct Double2; -struct Double3; -struct Double4; -struct Quaternion; -struct Matrix; -struct Matrix3x3; -struct Vector2; -struct Vector4; -struct Color; -class String; -struct Int3; -struct Int4; - /// -/// Represents a three dimensional mathematical vector with 32-bit precision (per-component). +/// Represents a three dimensional mathematical vector. /// -API_STRUCT() struct FLAXENGINE_API Vector3 +template +API_STRUCT(Template) struct Vector3Base { - DECLARE_SCRIPTING_TYPE_MINIMAL(Vector3); -public: + typedef T Real; + static struct ScriptingTypeInitializer TypeInitializer; + union { struct @@ -33,118 +23,116 @@ public: /// /// The X component. /// - API_FIELD() float X; + API_FIELD() T X; /// /// The Y component. /// - API_FIELD() float Y; + API_FIELD() T Y; /// /// The Z component. /// - API_FIELD() float Z; + API_FIELD() T Z; }; - // Raw values - float Raw[3]; + /// + /// The raw vector values (in XYZ order). + /// + T Raw[3]; }; public: // Vector with all components equal zero (0, 0, 0). - static const Vector3 Zero; + static FLAXENGINE_API const Vector3Base Zero; // Vector with all components equal one (1, 1, 1). - static const Vector3 One; + static FLAXENGINE_API const Vector3Base One; // Vector with all components equal half (0.5, 0.5, 0.5). - static const Vector3 Half; + static FLAXENGINE_API const Vector3Base Half; // The X unit vector (1, 0, 0). - static const Vector3 UnitX; + static FLAXENGINE_API const Vector3Base UnitX; // The Y unit vector (0, 1, 0). - static const Vector3 UnitY; + static FLAXENGINE_API const Vector3Base UnitY; // The Z unit vector (0, 0, 1). - static const Vector3 UnitZ; + static FLAXENGINE_API const Vector3Base UnitZ; // A unit vector designating up (0, 1, 0). - static const Vector3 Up; + static FLAXENGINE_API const Vector3Base Up; // A unit vector designating down (0, -1, 0). - static const Vector3 Down; + static FLAXENGINE_API const Vector3Base Down; // A unit vector designating a (-1, 0, 0). - static const Vector3 Left; + static FLAXENGINE_API const Vector3Base Left; // A unit vector designating b (1, 0, 0). - static const Vector3 Right; + static FLAXENGINE_API const Vector3Base Right; // A unit vector designating forward in a a-handed coordinate system (0, 0, 1). - static const Vector3 Forward; + static FLAXENGINE_API const Vector3Base Forward; // A unit vector designating backward in a a-handed coordinate system (0, 0, -1). - static const Vector3 Backward; + static FLAXENGINE_API const Vector3Base Backward; - // A minimum Vector3. - static const Vector3 Minimum; + // Vector with all components equal maximum value. + static FLAXENGINE_API const Vector3Base Minimum; - // A maximum Vector3. - static const Vector3 Maximum; + // Vector with all components equal minimum value. + static FLAXENGINE_API const Vector3Base Maximum; public: /// /// Empty constructor. /// - Vector3() + Vector3Base() { } - // Init - // @param xyz Value to assign to the all components - Vector3(float xyz) + FORCE_INLINE Vector3Base(T xyz) : X(xyz) , Y(xyz) , Z(xyz) { } - // Init - // @param x X component value - // @param y Y component value - // @param z Z component value - Vector3(float x, float y, float z) - : X(x) - , Y(y) - , Z(z) - { - } - - /// - /// Init - /// - /// X, Y and Z components in an array - explicit Vector3(const float* xyz) + FORCE_INLINE explicit Vector3Base(const T* xyz) : X(xyz[0]) , Y(xyz[1]) , Z(xyz[2]) { } - explicit Vector3(const Vector2& xy, float z); - explicit Vector3(const Vector2& xy); - explicit Vector3(const Int2& xy, float z); - explicit Vector3(const Int3& xyz); - explicit Vector3(const Int4& xyzw); - explicit Vector3(const Vector4& xyz); - explicit Vector3(const Double2& xy, float z); - Vector3(const Double3& xyz); - explicit Vector3(const Double4& xyzw); - explicit Vector3(const Color& color); + FORCE_INLINE Vector3Base(T x, T y, T z) + : X(x) + , Y(y) + , Z(z) + { + } + + template>::Value>::Type...> + FORCE_INLINE explicit Vector3Base(const Vector3Base& xyz) + : X((T)xyz.X) + , Y((T)xyz.Y) + , Z((T)xyz.Z) + { + } + + FLAXENGINE_API Vector3Base(const Float2& xy, T z = 0); + FLAXENGINE_API Vector3Base(const Double2& xy, T z = 0); + FLAXENGINE_API Vector3Base(const Int2& xy, T z = 0); + FLAXENGINE_API Vector3Base(const Int3& xyz); + FLAXENGINE_API explicit Vector3Base(const Float4& xyz); + FLAXENGINE_API explicit Vector3Base(const Double4& xyz); + FLAXENGINE_API explicit Vector3Base(const Int4& xyz); + FLAXENGINE_API explicit Vector3Base(const Color& color); public: - String ToString() const; + FLAXENGINE_API String ToString() const; public: // Gets a value indicting whether this instance is normalized. @@ -172,52 +160,27 @@ public: } // Calculates the length of the vector. - float Length() const + T Length() const { return Math::Sqrt(X * X + Y * Y + Z * Z); } // Calculates the squared length of the vector. - float LengthSquared() const + T LengthSquared() const { return X * X + Y * Y + Z * Z; } // Calculates inverted length of the vector (1 / length). - float InvLength() const + T InvLength() const { return 1.0f / Length(); } - /// - /// Calculates a vector with values being absolute values of that vector. - /// - Vector3 GetAbsolute() const - { - return Vector3(Math::Abs(X), Math::Abs(Y), Math::Abs(Z)); - } - - /// - /// Calculates a vector with values being opposite to values of that vector. - /// - Vector3 GetNegative() const - { - return Vector3(-X, -Y, -Z); - } - - /// - /// Calculates a normalized vector that has length equal to 1. - /// - Vector3 GetNormalized() const - { - const float rcp = 1.0f / Length(); - return Vector3(X * rcp, Y * rcp, Z * rcp); - } - /// /// Returns the average arithmetic of all the components. /// - float AverageArithmetic() const + T AverageArithmetic() const { return (X + Y + Z) * 0.333333334f; } @@ -225,7 +188,7 @@ public: /// /// Gets the sum of all vector components values. /// - float SumValues() const + T SumValues() const { return X + Y + Z; } @@ -233,7 +196,7 @@ public: /// /// Returns the minimum value of all the components. /// - float MinValue() const + T MinValue() const { return Math::Min(X, Y, Z); } @@ -241,7 +204,7 @@ public: /// /// Returns the maximum value of all the components. /// - float MaxValue() const + T MaxValue() const { return Math::Max(X, Y, Z); } @@ -270,16 +233,41 @@ public: return IsInfinity() || IsNaN(); } + /// + /// Calculates a vector with values being absolute values of that vector. + /// + Vector3Base GetAbsolute() const + { + return Vector3Base(Math::Abs(X), Math::Abs(Y), Math::Abs(Z)); + } + + /// + /// Calculates a vector with values being opposite to values of that vector. + /// + Vector3Base GetNegative() const + { + return Vector3Base(-X, -Y, -Z); + } + + /// + /// Calculates a normalized vector that has length equal to 1. + /// + Vector3Base GetNormalized() const + { + const T rcp = 1.0f / Length(); + return Vector3Base(X * rcp, Y * rcp, Z * rcp); + } + public: /// /// Performs vector normalization (scales vector up to unit length). /// void Normalize() { - const float length = Math::Sqrt(X * X + Y * Y + Z * Z); + const T length = Math::Sqrt(X * X + Y * Y + Z * Z); if (Math::Abs(length) >= ZeroTolerance) { - const float inv = 1.0f / length; + const T inv = 1.0f / length; X *= inv; Y *= inv; Z *= inv; @@ -291,74 +279,69 @@ public: /// void NormalizeFast() { - const float inv = 1.0f / Math::Sqrt(X * X + Y * Y + Z * Z); + const T inv = 1.0f / Math::Sqrt(X * X + Y * Y + Z * Z); X *= inv; Y *= inv; Z *= inv; } - /// - /// Sets all vector components to the absolute values. - /// - void Absolute() - { - X = Math::Abs(X); - Y = Math::Abs(Y); - Z = Math::Abs(Z); - } - - /// - /// Negates all components of that vector. - /// - void Negate() - { - X = -X; - Y = -Y; - Z = -Z; - } - - /// - /// When this vector contains Euler angles (degrees), ensure that angles are between +/-180. - /// - void UnwindEuler(); - public: - Vector3 operator+(const Vector3& b) const + Vector3Base operator+(const Vector3Base& b) const { - return Vector3(X + b.X, Y + b.Y, Z + b.Z); + return Vector3Base(X + b.X, Y + b.Y, Z + b.Z); } - Vector3 operator-(const Vector3& b) const + Vector3Base operator-(const Vector3Base& b) const { - return Vector3(X - b.X, Y - b.Y, Z - b.Z); + return Vector3Base(X - b.X, Y - b.Y, Z - b.Z); } - Vector3 operator*(const Vector3& b) const + Vector3Base operator*(const Vector3Base& b) const { - return Vector3(X * b.X, Y * b.Y, Z * b.Z); + return Vector3Base(X * b.X, Y * b.Y, Z * b.Z); } - Vector3 operator/(const Vector3& b) const + Vector3Base operator/(const Vector3Base& b) const { - return Vector3(X / b.X, Y / b.Y, Z / b.Z); + return Vector3Base(X / b.X, Y / b.Y, Z / b.Z); } - Vector3 operator-() const + Vector3Base operator-() const { - return Vector3(-X, -Y, -Z); + return Vector3Base(-X, -Y, -Z); } - Vector3 operator^(const Vector3& b) const + Vector3Base operator+(T b) const + { + return Vector3Base(X + b, Y + b, Z + b); + } + + Vector3Base operator-(T b) const + { + return Vector3Base(X - b, Y - b, Z - b); + } + + Vector3Base operator*(T b) const + { + return Vector3Base(X * b, Y * b, Z * b); + } + + Vector3Base operator/(T b) const + { + return Vector3Base(X / b, Y / b, Z / b); + } + + Vector3Base operator^(const Vector3Base& b) const { return Cross(*this, b); } - float operator|(const Vector3& b) const + T operator|(const Vector3Base& b) const { return Dot(*this, b); } - Vector3& operator+=(const Vector3& b) + Vector3Base& operator+=(const Vector3Base& b) { X += b.X; Y += b.Y; @@ -366,7 +349,7 @@ public: return *this; } - Vector3& operator-=(const Vector3& b) + Vector3Base& operator-=(const Vector3Base& b) { X -= b.X; Y -= b.Y; @@ -374,7 +357,7 @@ public: return *this; } - Vector3& operator*=(const Vector3& b) + Vector3Base& operator*=(const Vector3Base& b) { X *= b.X; Y *= b.Y; @@ -382,7 +365,7 @@ public: return *this; } - Vector3& operator/=(const Vector3& b) + Vector3Base& operator/=(const Vector3Base& b) { X /= b.X; Y /= b.Y; @@ -390,234 +373,227 @@ public: return *this; } - Vector3 operator+(float b) const + Vector3Base& operator+=(T b) { - return Vector3(X + b, Y + b, Z + b); - } - - Vector3 operator-(float b) const - { - return Vector3(X - b, Y - b, Z - b); - } - - Vector3 operator*(float b) const - { - return Vector3(X * b, Y * b, Z * b); - } - - Vector3 operator/(float b) const - { - return Vector3(X / b, Y / b, Z / b); - } - - Vector3& operator+=(float b) - { - *this = Add(*this, b); + X += b; + Y += b; + Z += b; return *this; } - Vector3& operator-=(float b) + Vector3Base& operator-=(T b) { - *this = Subtract(*this, b); + X -= b; + Y -= b; + Z -= b; return *this; } - Vector3& operator*=(float b) + Vector3Base& operator*=(T b) { - *this = Multiply(*this, b); + X *= b; + Y *= b; + Z *= b; return *this; } - Vector3& operator/=(float b) + Vector3Base& operator/=(T b) { - *this = Divide(*this, b); + X /= b; + Y /= b; + Z /= b; return *this; } - bool operator==(const Vector3& b) const + bool operator==(const Vector3Base& b) const { return X == b.X && Y == b.Y && Z == b.Z; } - bool operator!=(const Vector3& b) const + bool operator!=(const Vector3Base& b) const { return X != b.X || Y != b.Y || Z != b.Z; } - bool operator>(const Vector3& b) const + bool operator>(const Vector3Base& b) const { return X > b.X && Y > b.Y && Z > b.Z; } - bool operator>=(const Vector3& b) const + bool operator>=(const Vector3Base& b) const { return X >= b.X && Y >= b.Y && Z >= b.Z; } - bool operator<(const Vector3& b) const + bool operator<(const Vector3Base& b) const { return X < b.X && Y < b.Y && Z < b.Z; } - bool operator<=(const Vector3& b) const + bool operator<=(const Vector3Base& b) const { return X <= b.X && Y <= b.Y && Z <= b.Z; } public: - static bool NearEqual(const Vector3& a, const Vector3& b) + static bool NearEqual(const Vector3Base& a, const Vector3Base& b) { return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y) && Math::NearEqual(a.Z, b.Z); } - static bool NearEqual(const Vector3& a, const Vector3& b, float epsilon) + static bool NearEqual(const Vector3Base& a, const Vector3Base& b, T epsilon) { return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon) && Math::NearEqual(a.Z, b.Z, epsilon); } public: - static void Add(const Vector3& a, const Vector3& b, Vector3& result) + static void Add(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - result.Z = a.Z + b.Z; + result = Vector3Base(a.X + b.X, a.Y + b.Y, a.Z + b.Z); } - static Vector3 Add(const Vector3& a, const Vector3& b) + static void Subtract(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - Vector3 result; - Add(a, b, result); - return result; + result = Vector3Base(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } - static void Subtract(const Vector3& a, const Vector3& b, Vector3& result) + static void Multiply(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - result.Z = a.Z - b.Z; + result = Vector3Base(a.X * b.X, a.Y * b.Y, a.Z * b.Z); } - static Vector3 Subtract(const Vector3& a, const Vector3& b) + static void Divide(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - Vector3 result; - Subtract(a, b, result); - return result; + result = Vector3Base(a.X / b.X, a.Y / b.Y, a.Z / b.Z); } - static Vector3 Multiply(const Vector3& a, const Vector3& b) + static void Min(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - return Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); + result = Vector3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); } - static void Multiply(const Vector3& a, const Vector3& b, Vector3& result) + static void Max(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - result = Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z); + result = Vector3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); } - static Vector3 Multiply(const Vector3& a, float b) +public: + static Vector3Base Min(const Vector3Base& a, const Vector3Base& b) { - return Vector3(a.X * b, a.Y * b, a.Z * b); + return Vector3Base(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); } - static Vector3 Divide(const Vector3& a, const Vector3& b) + static Vector3Base Max(const Vector3Base& a, const Vector3Base& b) { - return Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z); + return Vector3Base(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); } - static void Divide(const Vector3& a, const Vector3& b, Vector3& result) + static Vector3Base Floor(const Vector3Base& v) { - result = Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z); + return Vector3Base(Math::Floor(v.X), Math::Floor(v.Y), Math::Floor(v.Z)); } - static Vector3 Divide(const Vector3& a, float b) + static Vector3Base Frac(const Vector3Base& v) { - return Vector3(a.X / b, a.Y / b, a.Z / b); + return Vector3(v.X - (int32)v.X, v.Y - (int32)v.Y, v.Z - (int32)v.Z); } - static Vector3 Floor(const Vector3& v); - static Vector3 Frac(const Vector3& v); + static Vector3Base Round(const Vector3Base& v) + { + return Vector3Base(Math::Round(v.X), Math::Round(v.Y), Math::Round(v.Z)); + } + + static Vector3Base Ceil(const Vector3Base& v) + { + return Vector3Base(Math::Ceil(v.X), Math::Ceil(v.Y), Math::Ceil(v.Z)); + } + + static Vector3Base Abs(const Vector3Base& v) + { + return Vector3Base(Math::Abs(v.X), Math::Abs(v.Y), Math::Abs(v.Z)); + } public: // Restricts a value to be within a specified range - // @param value The value to clamp + // @param v The value to clamp // @param min The minimum value, // @param max The maximum value // @returns Clamped value - static Vector3 Clamp(const Vector3& value, const Vector3& min, const Vector3& max) + static Vector3Base Clamp(const Vector3Base& v, const Vector3Base& min, const Vector3Base& max) { - return Vector3(Math::Clamp(value.X, min.X, max.X), Math::Clamp(value.Y, min.Y, max.Y), Math::Clamp(value.Z, min.Z, max.Z)); + Vector3Base result; + Clamp(v, min, max, result); + return result; } // Restricts a value to be within a specified range - // @param value The value to clamp + // @param v The value to clamp // @param min The minimum value, // @param max The maximum value // @param result When the method completes, contains the clamped value - static void Clamp(const Vector3& value, const Vector3& min, const Vector3& max, Vector3& result) + static void Clamp(const Vector3Base& v, const Vector3Base& min, const Vector3Base& max, Vector3Base& result) { - result = Vector3(Math::Clamp(value.X, min.X, max.X), Math::Clamp(value.Y, min.Y, max.Y), Math::Clamp(value.Z, min.Z, max.Z)); + result = Vector3Base(Math::Clamp(v.X, min.X, max.X), Math::Clamp(v.Y, min.Y, max.Y), Math::Clamp(v.Z, min.Z, max.Z)); } // Calculates the distance between two vectors - // @param value1 The first vector - // @param value2 The second vector + // @param a The first vector + // @param b The second vector // @returns The distance between the two vectors - static float Distance(const Vector3& value1, const Vector3& value2) + static T Distance(const Vector3Base& a, const Vector3Base& b) { - const float x = value1.X - value2.X; - const float y = value1.Y - value2.Y; - const float z = value1.Z - value2.Z; + const T x = a.X - b.X; + const T y = a.Y - b.Y; + const T z = a.Z - b.Z; return Math::Sqrt(x * x + y * y + z * z); } // Calculates the squared distance between two vectors - // @param value1 The first vector - // @param value2 The second vector + // @param a The first vector + // @param b The second vector // @returns The squared distance between the two vectors - static float DistanceSquared(const Vector3& value1, const Vector3& value2) + static T DistanceSquared(const Vector3Base& a, const Vector3Base& b) { - const float x = value1.X - value2.X; - const float y = value1.Y - value2.Y; - const float z = value1.Z - value2.Z; + const T x = a.X - b.X; + const T y = a.Y - b.Y; + const T z = a.Z - b.Z; return x * x + y * y + z * z; } - // Performs vector normalization (scales vector up to unit length) - // @param inout Input vector to normalize - // @returns Output vector that is normalized (has unit length) - static Vector3 Normalize(const Vector3& input) + // Performs vector normalization (scales vector up to unit length). + static Vector3Base Normalize(const Vector3Base& v) { - Vector3 output = input; - const float length = input.Length(); + Vector3Base r = v; + const T length = Math::Sqrt(r.X * r.X + r.Y * r.Y + r.Z * r.Z); if (Math::Abs(length) >= ZeroTolerance) { - const float inv = 1.0f / length; - output.X *= inv; - output.Y *= inv; - output.Z *= inv; + const T inv = 1.0f / length; + r.X *= inv; + r.Y *= inv; + r.Z *= inv; } - return output; + return r; } // Performs vector normalization (scales vector up to unit length). This is a faster version that does not performs check for length equal 0 (it assumes that input vector is not empty). // @param inout Input vector to normalize (cannot be zero). // @returns Output vector that is normalized (has unit length) - static Vector3 NormalizeFast(const Vector3& input) + static Vector3Base NormalizeFast(const Vector3Base& v) { - const float inv = 1.0f / input.Length(); - return Vector3(input.X * inv, input.Y * inv, input.Z * inv); + const T inv = 1.0f / v.Length(); + return Vector3Base(v.X * inv, v.Y * inv, v.Z * inv); } // Performs vector normalization (scales vector up to unit length) // @param inout Input vector to normalize // @param output Output vector that is normalized (has unit length) - static FORCE_INLINE void Normalize(const Vector3& input, Vector3& result) + static FORCE_INLINE void Normalize(const Vector3Base& input, Vector3Base& result) { result = Normalize(input); } // dot product with another vector - static float Dot(const Vector3& a, const Vector3& b) + static T Dot(const Vector3Base& a, const Vector3Base& b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; } @@ -626,18 +602,18 @@ public: // @param a First source vector // @param b Second source vector // @param result When the method completes, contains the cross product of the two vectors - static void Cross(const Vector3& a, const Vector3& b, Vector3& result) + static void Cross(const Vector3Base& a, const Vector3Base& b, Vector3Base& result) { - result = Vector3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); + result = Vector3Base(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); } // Calculates the cross product of two vectors // @param a First source vector // @param b Second source vector // @returns Cross product of the two vectors - static Vector3 Cross(const Vector3& a, const Vector3& b) + static Vector3Base Cross(const Vector3Base& a, const Vector3Base& b) { - return Vector3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); + return Vector3Base(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); } // Performs a linear interpolation between two vectors @@ -645,7 +621,7 @@ public: // @param end End vector // @param amount Value between 0 and 1 indicating the weight of end // @param result When the method completes, contains the linear interpolation of the two vectors - static void Lerp(const Vector3& start, const Vector3& end, float amount, Vector3& result) + static void Lerp(const Vector3Base& start, const Vector3Base& end, T amount, Vector3Base& result) { result.X = Math::Lerp(start.X, end.X, amount); result.Y = Math::Lerp(start.Y, end.Y, amount); @@ -655,9 +631,9 @@ public: // // Performs a linear interpolation between two vectors. // - static Vector3 Lerp(const Vector3& start, const Vector3& end, float amount) + static Vector3Base Lerp(const Vector3Base& start, const Vector3Base& end, T amount) { - Vector3 result; + Vector3Base result; Lerp(start, end, amount, result); return result; } @@ -667,7 +643,7 @@ public: // @param end End vector // @param amount Value between 0 and 1 indicating the weight of end // @param result When the method completes, contains the cubic interpolation of the two vectors - static void SmoothStep(const Vector3& start, const Vector3& end, float amount, Vector3& result) + static void SmoothStep(const Vector3Base& start, const Vector3Base& end, T amount, Vector3Base& result) { amount = Math::SmoothStep(amount); Lerp(start, end, amount, result); @@ -680,104 +656,61 @@ public: // @param tangent2 Second source tangent vector // @param amount Weighting factor, // @param result When the method completes, contains the result of the Hermite spline interpolation, - static void Hermite(const Vector3& value1, const Vector3& tangent1, const Vector3& value2, const Vector3& tangent2, float amount, Vector3& result); + static FLAXENGINE_API void Hermite(const Vector3Base& value1, const Vector3Base& tangent1, const Vector3Base& value2, const Vector3Base& tangent2, T amount, Vector3Base& result); // Returns the reflection of a vector off a surface that has the specified normal // @param vector The source vector // @param normal Normal of the surface // @param result When the method completes, contains the reflected vector - static void Reflect(const Vector3& vector, const Vector3& normal, Vector3& result); + static FLAXENGINE_API void Reflect(const Vector3Base& vector, const Vector3Base& normal, Vector3Base& result); // Transforms a 3D vector by the given Quaternion rotation // @param vector The vector to rotate // @param rotation The Quaternion rotation to apply - // @param result When the method completes, contains the transformed Vector4 - static void Transform(const Vector3& vector, const Quaternion& rotation, Vector3& result); + // @param result When the method completes, contains the transformed Vector3 + static FLAXENGINE_API void Transform(const Vector3Base& vector, const Quaternion& rotation, Vector3Base& result); // Transforms a 3D vector by the given Quaternion rotation // @param vector The vector to rotate // @param rotation The Quaternion rotation to apply - // @returns The transformed Vector4 - static Vector3 Transform(const Vector3& vector, const Quaternion& rotation); + // @returns The transformed Vector3 + static FLAXENGINE_API Vector3Base Transform(const Vector3Base& vector, const Quaternion& rotation); // Transforms a 3D vector by the given matrix // @param vector The source vector // @param transform The transformation matrix // @param result When the method completes, contains the transformed Vector3 - static void Transform(const Vector3& vector, const Matrix& transform, Vector3& result); - - // Transforms a 3D vectors by the given matrix - // @param vectors The source vectors - // @param transform The transformation matrix - // @param results When the method completes, contains the transformed Vector3s - // @param vectorsCount Amount of vectors to transform - static void Transform(const Vector3* vectors, const Matrix& transform, Vector3* results, int32 vectorsCount); + static FLAXENGINE_API void Transform(const Vector3Base& vector, const Matrix& transform, Vector3Base& result); // Transforms a 3D vector by the given matrix // @param vector The source vector // @param transform The transformation matrix // @param result When the method completes, contains the transformed Vector3 - static void Transform(const Vector3& vector, const Matrix3x3& transform, Vector3& result); + static FLAXENGINE_API void Transform(const Vector3Base& vector, const Matrix3x3& transform, Vector3Base& result); // Transforms a 3D vector by the given matrix // @param vector The source vector // @param transform The transformation matrix // @returns Transformed Vector3 - static Vector3 Transform(const Vector3& vector, const Matrix& transform); + static FLAXENGINE_API Vector3Base Transform(const Vector3Base& vector, const Matrix& transform); // Transforms a 3D vector by the given matrix // @param vector The source vector // @param transform The transformation matrix // @param result When the method completes, contains the transformed Vector4 - static void Transform(const Vector3& vector, const Matrix& transform, Vector4& result); + static FLAXENGINE_API void Transform(const Vector3Base& vector, const Matrix& transform, Vector4Base& result); // Performs a coordinate transformation using the given matrix // @param coordinate The coordinate vector to transform // @param transform The transformation matrix // @param result When the method completes, contains the transformed coordinates - static void TransformCoordinate(const Vector3& coordinate, const Matrix& transform, Vector3& result); + static FLAXENGINE_API void TransformCoordinate(const Vector3Base& coordinate, const Matrix& transform, Vector3Base& result); // Performs a normal transformation using the given matrix // @param normal The normal vector to transform // @param transform The transformation matrix // @param result When the method completes, contains the transformed normal - static void TransformNormal(const Vector3& normal, const Matrix& transform, Vector3& result); - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static Vector3 Max(const Vector3& a, const Vector3& b) - { - return Vector3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static Vector3 Min(const Vector3& a, const Vector3& b) - { - return Vector3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the largest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the largest components of the source vectors - static void Max(const Vector3& a, const Vector3& b, Vector3& result) - { - result = Vector3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z); - } - - // Returns a vector containing the smallest components of the specified vectors - // @param a The first source vector - // @param b The second source vector - // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors - static void Min(const Vector3& a, const Vector3& b, Vector3& result) - { - result = Vector3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z); - } + static FLAXENGINE_API void TransformNormal(const Vector3Base& normal, const Matrix& transform, Vector3Base& result); /// /// Projects a vector onto another vector. @@ -785,7 +718,7 @@ public: /// The vector to project. /// The projection normal vector. /// The projected vector. - static Vector3 Project(const Vector3& vector, const Vector3& onNormal); + static FLAXENGINE_API Vector3Base Project(const Vector3Base& vector, const Vector3Base& onNormal); /// /// Projects a vector onto a plane defined by a normal orthogonal to the plane. @@ -793,7 +726,7 @@ public: /// The vector to project. /// The plane normal vector. /// The projected vector. - static Vector3 ProjectOnPlane(const Vector3& vector, const Vector3& planeNormal) + static Vector3Base ProjectOnPlane(const Vector3Base& vector, const Vector3Base& planeNormal) { return vector - Project(vector, planeNormal); } @@ -808,7 +741,7 @@ public: // @param maxZ The maximum depth of the viewport // @param worldViewProjection The combined world-view-projection matrix // @param result When the method completes, contains the vector in screen space - static void Project(const Vector3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Vector3& result); + static FLAXENGINE_API void Project(const Vector3Base& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Vector3Base& result); // Projects a 3D vector from object space into screen space // @param vector The vector to project @@ -820,9 +753,9 @@ public: // @param maxZ The maximum depth of the viewport // @param worldViewProjection The combined world-view-projection matrix // @returns The vector in screen space - static Vector3 Project(const Vector3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection) + static Vector3Base Project(const Vector3Base& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection) { - Vector3 result; + Vector3Base result; Project(vector, x, y, width, height, minZ, maxZ, worldViewProjection, result); return result; } @@ -837,7 +770,7 @@ public: // @param maxZ The maximum depth of the viewport // @param worldViewProjection The combined world-view-projection matrix // @param result When the method completes, contains the vector in object space - static void Unproject(const Vector3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Vector3& result); + static FLAXENGINE_API void Unproject(const Vector3Base& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection, Vector3Base& result); // Projects a 3D vector from screen space into object space // @param vector The vector to project @@ -849,9 +782,9 @@ public: // @param maxZ The maximum depth of the viewport // @param worldViewProjection The combined world-view-projection matrix // @returns The vector in object space - static Vector3 Unproject(const Vector3& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection) + static Vector3Base Unproject(const Vector3Base& vector, float x, float y, float width, float height, float minZ, float maxZ, const Matrix& worldViewProjection) { - Vector3 result; + Vector3Base result; Unproject(vector, x, y, width, height, minZ, maxZ, worldViewProjection, result); return result; } @@ -862,29 +795,14 @@ public: /// The X axis. /// The y axis. /// The z axis. - static void CreateOrthonormalBasis(Vector3& xAxis, Vector3& yAxis, Vector3& zAxis); + static FLAXENGINE_API void CreateOrthonormalBasis(Vector3Base& xAxis, Vector3Base& yAxis, Vector3Base& zAxis); /// /// Finds the best arbitrary axis vectors to represent U and V axes of a plane, by using this vector as the normal of the plane. /// /// The reference to first axis. /// The reference to second axis. - void FindBestAxisVectors(Vector3& firstAxis, Vector3& secondAxis) const; - - static Vector3 Round(const Vector3& v) - { - return Vector3(Math::Round(v.X), Math::Round(v.Y), Math::Round(v.Z)); - } - - static Vector3 Ceil(const Vector3& v) - { - return Vector3(Math::Ceil(v.X), Math::Ceil(v.Y), Math::Ceil(v.Z)); - } - - static Vector3 Abs(const Vector3& v) - { - return Vector3(Math::Abs(v.X), Math::Abs(v.Y), Math::Abs(v.Z)); - } + FLAXENGINE_API void FindBestAxisVectors(Vector3Base& firstAxis, Vector3Base& secondAxis) const; /// /// Calculates the area of the triangle. @@ -893,7 +811,7 @@ public: /// The second triangle vertex. /// The third triangle vertex. /// The triangle area. - static float TriangleArea(const Vector3& v0, const Vector3& v1, const Vector3& v2); + static FLAXENGINE_API T TriangleArea(const Vector3Base& v0, const Vector3Base& v1, const Vector3Base& v2); /// /// Calculates the angle (in radians) between from and to. This is always the smallest value. @@ -901,41 +819,68 @@ public: /// The first vector. /// The second vector. /// The angle (in radians). - static float Angle(const Vector3& from, const Vector3& to); + static FLAXENGINE_API T Angle(const Vector3Base& from, const Vector3Base& to); }; -inline Vector3 operator+(float a, const Vector3& b) +template +inline Vector3Base operator+(T a, const Vector3Base& b) { return b + a; } -inline Vector3 operator-(float a, const Vector3& b) +template +inline Vector3Base operator-(T a, const Vector3Base& b) { - return Vector3(a) - b; + return Vector3Base(a) - b; } -inline Vector3 operator*(float a, const Vector3& b) +template +inline Vector3Base operator*(T a, const Vector3Base& b) { return b * a; } -inline Vector3 operator/(float a, const Vector3& b) +template +inline Vector3Base operator/(T a, const Vector3Base& b) { - return Vector3(a) / b; + return Vector3Base(a) / b; } namespace Math { - FORCE_INLINE static bool NearEqual(const Vector3& a, const Vector3& b) + template + FORCE_INLINE static bool NearEqual(const Vector3Base& a, const Vector3Base& b) { - return Vector3::NearEqual(a, b); + return Vector3Base::NearEqual(a, b); + } + + template + FORCE_INLINE static Vector3Base UnwindDegrees(const Vector3Base& v) + { + return Vector3Base(UnwindDegrees(v.X), UnwindDegrees(v.Y), UnwindDegrees(v.Z)); } } template<> -struct TIsPODType +struct TIsPODType { enum { Value = true }; }; -DEFINE_DEFAULT_FORMATTING(Vector3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z); +DEFINE_DEFAULT_FORMATTING(Float3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z); + +template<> +struct TIsPODType +{ + enum { Value = true }; +}; + +DEFINE_DEFAULT_FORMATTING(Double3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z); + +template<> +struct TIsPODType +{ + enum { Value = true }; +}; + +DEFINE_DEFAULT_FORMATTING(Int3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z); diff --git a/Source/Engine/Core/Math/Vector4.cpp b/Source/Engine/Core/Math/Vector4.cpp index 879177c5a..bb805f0a7 100644 --- a/Source/Engine/Core/Math/Vector4.cpp +++ b/Source/Engine/Core/Math/Vector4.cpp @@ -1,36 +1,36 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. -#include "Double4.h" -#include "Double3.h" -#include "Double2.h" #include "Vector4.h" #include "Vector2.h" #include "Vector3.h" -#include "Int2.h" -#include "Int3.h" -#include "Int4.h" #include "Color.h" #include "Matrix.h" #include "Rectangle.h" #include "../Types/String.h" -static_assert(sizeof(Vector4) == 16, "Invalid Vector4 type size."); +// Float -const Vector4 Vector4::Zero(0.0f); -const Vector4 Vector4::One(1.0f); -const Vector4 Vector4::UnitX(1, 0, 0, 0); -const Vector4 Vector4::UnitY(0, 1, 0, 0); -const Vector4 Vector4::UnitZ(0, 0, 1, 0); -const Vector4 Vector4::UnitW(0, 0, 0, 1); -const Vector4 Vector4::Minimum(MIN_float); -const Vector4 Vector4::Maximum(MAX_float); +static_assert(sizeof(Float4) == 16, "Invalid Float4 type size."); -Vector4::Vector4(float xyzw[4]) -{ - Platform::MemoryCopy(Raw, xyzw, sizeof(float) * 4); -} +template<> +const Float4 Float4::Zero(0.0f); +template<> +const Float4 Float4::One(1.0f); +template<> +const Float4 Float4::UnitX(1.0f, 0.0f, 0.0f, 0.0f); +template<> +const Float4 Float4::UnitY(0.0f, 1.0f, 0.0f, 0.0f); +template<> +const Float4 Float4::UnitZ(0.0f, 0.0f, 1.0f, 0.0f); +template<> +const Float4 Float4::UnitW(0.0f, 0.0f, 0.0f, 1.0f); +template<> +const Float4 Float4::Minimum(MIN_float); +template<> +const Float4 Float4::Maximum(MAX_float); -Vector4::Vector4(const Vector2& xy, float z, float w) +template<> +Float4::Vector4Base(const Float2& xy, float z, float w) : X(xy.X) , Y(xy.Y) , Z(z) @@ -38,7 +38,8 @@ Vector4::Vector4(const Vector2& xy, float z, float w) { } -Vector4::Vector4(const Vector2& xy, const Vector2& zw) +template<> +Float4::Vector4Base(const Float2& xy, const Float2& zw) : X(xy.X) , Y(xy.Y) , Z(zw.X) @@ -46,7 +47,8 @@ Vector4::Vector4(const Vector2& xy, const Vector2& zw) { } -Vector4::Vector4(const Vector3& xyz, float w) +template<> +Float4::Vector4Base(const Float3& xyz, float w) : X(xyz.X) , Y(xyz.Y) , Z(xyz.Z) @@ -54,55 +56,53 @@ Vector4::Vector4(const Vector3& xyz, float w) { } -Vector4::Vector4(const Int2& xy, float z, float w) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) +template<> +Float4::Vector4Base(const Int2& xy, float z, float w) + : X((float)xy.X) + , Y((float)xy.Y) , Z(z) , W(w) { } -Vector4::Vector4(const Int3& xyz, float w) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) +template<> +Float4::Vector4Base(const Int3& xyz, float w) + : X((float)xyz.X) + , Y((float)xyz.Y) + , Z((float)xyz.Z) , W(w) { } -Vector4::Vector4(const Int4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.Z)) - , W(static_cast(xyzw.W)) -{ -} - -Vector4::Vector4(const Double2& xy, float z, float w) - : X(static_cast(xy.X)) - , Y(static_cast(xy.Y)) +template<> +Float4::Vector4Base(const Double2& xy, float z, float w) + : X((float)xy.X) + , Y((float)xy.Y) , Z(z) , W(w) { } -Vector4::Vector4(const Double3& xyz, float w) - : X(static_cast(xyz.X)) - , Y(static_cast(xyz.Y)) - , Z(static_cast(xyz.Z)) +template<> +Float4::Vector4Base(const Double2& xy, const Double2& zw) + : X((float)xy.X) + , Y((float)xy.Y) + , Z((float)zw.X) + , W((float)zw.Y) +{ +} + +template<> +Float4::Vector4Base(const Double3& xyz, float w) + : X((float)xyz.X) + , Y((float)xyz.Y) + , Z((float)xyz.Z) , W(w) { } -Vector4::Vector4(const Double4& xyzw) - : X(static_cast(xyzw.X)) - , Y(static_cast(xyzw.Y)) - , Z(static_cast(xyzw.Z)) - , W(static_cast(xyzw.W)) -{ -} - -Vector4::Vector4(const Color& color) +template<> +Float4::Vector4Base(const Color& color) : X(color.R) , Y(color.G) , Z(color.B) @@ -110,7 +110,8 @@ Vector4::Vector4(const Color& color) { } -Vector4::Vector4(const Rectangle& rect) +template<> +Float4::Vector4Base(const Rectangle& rect) : X(rect.Location.X) , Y(rect.Location.Y) , Z(rect.Size.X) @@ -118,99 +119,270 @@ Vector4::Vector4(const Rectangle& rect) { } -String Vector4::ToString() const +template<> +String Float4::ToString() const { return String::Format(TEXT("{}"), *this); } -Vector4 Vector4::Floor(const Vector4& v) +template<> +Float4 Float4::Transform(const Float4& v, const Matrix& m) { - return Vector4( - Math::Floor(v.X), - Math::Floor(v.Y), - Math::Floor(v.Z), - Math::Floor(v.W) - ); -} - -Vector4 Vector4::Frac(const Vector4& v) -{ - return Vector4( - v.X - (int32)v.X, - v.Y - (int32)v.Y, - v.Z - (int32)v.Z, - v.W - (int32)v.W - ); -} - -Vector4 Vector4::Round(const Vector4& v) -{ - return Vector4( - Math::Round(v.X), - Math::Round(v.Y), - Math::Round(v.Z), - Math::Round(v.W) - ); -} - -Vector4 Vector4::Ceil(const Vector4& v) -{ - return Vector4( - Math::Ceil(v.X), - Math::Ceil(v.Y), - Math::Ceil(v.Z), - Math::Ceil(v.W) - ); -} - -Vector4 Vector4::Clamp(const Vector4& value, const Vector4& min, const Vector4& max) -{ - float x = value.X; - x = x > max.X ? max.X : x; - x = x < min.X ? min.X : x; - - float y = value.Y; - y = y > max.Y ? max.Y : y; - y = y < min.Y ? min.Y : y; - - float z = value.Z; - z = z > max.Z ? max.Z : z; - z = z < min.Z ? min.Z : z; - - float w = value.W; - w = w > max.W ? max.W : w; - w = w < min.W ? min.W : w; - - return Vector4(x, y, z, w); -} - -void Vector4::Clamp(const Vector4& value, const Vector4& min, const Vector4& max, Vector4& result) -{ - float x = value.X; - x = x > max.X ? max.X : x; - x = x < min.X ? min.X : x; - - float y = value.Y; - y = y > max.Y ? max.Y : y; - y = y < min.Y ? min.Y : y; - - float z = value.Z; - z = z > max.Z ? max.Z : z; - z = z < min.Z ? min.Z : z; - - float w = value.W; - w = w > max.W ? max.W : w; - w = w < min.W ? min.W : w; - - result = Vector4(x, y, z, w); -} - -Vector4 Vector4::Transform(const Vector4& v, const Matrix& m) -{ - return Vector4( + return Float4( m.Values[0][0] * v.Raw[0] + m.Values[1][0] * v.Raw[1] + m.Values[2][0] * v.Raw[2] + m.Values[3][0] * v.Raw[3], m.Values[0][1] * v.Raw[0] + m.Values[1][1] * v.Raw[1] + m.Values[2][1] * v.Raw[2] + m.Values[3][1] * v.Raw[3], m.Values[0][2] * v.Raw[0] + m.Values[1][2] * v.Raw[1] + m.Values[2][2] * v.Raw[2] + m.Values[3][2] * v.Raw[3], m.Values[0][3] * v.Raw[0] + m.Values[1][3] * v.Raw[1] + m.Values[2][3] * v.Raw[2] + m.Values[3][3] * v.Raw[3] ); } + +// Double + +static_assert(sizeof(Double4) == 32, "Invalid Double4 type size."); + +template<> +const Double4 Double4::Zero(0.0); +template<> +const Double4 Double4::One(1.0); +template<> +const Double4 Double4::UnitX(1.0, 0.0, 0.0, 0.0); +template<> +const Double4 Double4::UnitY(0.0, 1.0, 0.0, 0.0); +template<> +const Double4 Double4::UnitZ(0.0, 0.0, 1.0, 0.0); +template<> +const Double4 Double4::UnitW(0.0, 0.0, 0.0, 1.0); +template<> +const Double4 Double4::Minimum(MIN_double); +template<> +const Double4 Double4::Maximum(MAX_double); + +template<> +Double4::Vector4Base(const Float2& xy, double z, double w) + : X((double)xy.X) + , Y((double)xy.Y) + , Z(z) + , W(w) +{ +} + +template<> +Double4::Vector4Base(const Float2& xy, const Float2& zw) + : X((double)xy.X) + , Y((double)xy.Y) + , Z((double)zw.X) + , W((double)zw.Y) +{ +} + +template<> +Double4::Vector4Base(const Float3& xyz, double w) + : X((double)xyz.X) + , Y((double)xyz.Y) + , Z((double)xyz.Z) + , W(w) +{ +} + +template<> +Double4::Vector4Base(const Int2& xy, double z, double w) + : X((double)xy.X) + , Y((double)xy.Y) + , Z(z) + , W(w) +{ +} + +template<> +Double4::Vector4Base(const Int3& xyz, double w) + : X((double)xyz.X) + , Y((double)xyz.Y) + , Z((double)xyz.Z) + , W(w) +{ +} + +template<> +Double4::Vector4Base(const Double2& xy, double z, double w) + : X(xy.X) + , Y(xy.Y) + , Z(z) + , W(w) +{ +} + +template<> +Double4::Vector4Base(const Double2& xy, const Double2& zw) + : X(xy.X) + , Y(xy.Y) + , Z(zw.X) + , W(zw.Y) +{ +} + +template<> +Double4::Vector4Base(const Double3& xyz, double w) + : X((double)xyz.X) + , Y((double)xyz.Y) + , Z((double)xyz.Z) + , W(w) +{ +} + +template<> +Double4::Vector4Base(const Color& color) + : X((double)color.R) + , Y((double)color.G) + , Z((double)color.B) + , W((double)color.A) +{ +} + +template<> +Double4::Vector4Base(const Rectangle& rect) + : X((double)rect.Location.X) + , Y((double)rect.Location.Y) + , Z((double)rect.Size.X) + , W((double)rect.Size.Y) +{ +} + +template<> +String Double4::ToString() const +{ + return String::Format(TEXT("{}"), *this); +} + +template<> +Double4 Double4::Transform(const Double4& v, const Matrix& m) +{ + return Double4( + m.Values[0][0] * v.Raw[0] + m.Values[1][0] * v.Raw[1] + m.Values[2][0] * v.Raw[2] + m.Values[3][0] * v.Raw[3], + m.Values[0][1] * v.Raw[0] + m.Values[1][1] * v.Raw[1] + m.Values[2][1] * v.Raw[2] + m.Values[3][1] * v.Raw[3], + m.Values[0][2] * v.Raw[0] + m.Values[1][2] * v.Raw[1] + m.Values[2][2] * v.Raw[2] + m.Values[3][2] * v.Raw[3], + m.Values[0][3] * v.Raw[0] + m.Values[1][3] * v.Raw[1] + m.Values[2][3] * v.Raw[2] + m.Values[3][3] * v.Raw[3] + ); +} + +// Int + +static_assert(sizeof(Int4) == 16, "Invalid Int4 type size."); + +template<> +const Int4 Int4::Zero(0); +template<> +const Int4 Int4::One(1); +template<> +const Int4 Int4::UnitX(1, 0, 0, 0); +template<> +const Int4 Int4::UnitY(0, 1, 0, 0); +template<> +const Int4 Int4::UnitZ(0, 0, 1, 0); +template<> +const Int4 Int4::UnitW(0, 0, 0, 1); +template<> +const Int4 Int4::Minimum(MIN_int32); +template<> +const Int4 Int4::Maximum(MAX_int32); + +template<> +Int4::Vector4Base(const Float2& xy, int32 z, int32 w) + : X((int32)xy.X) + , Y((int32)xy.Y) + , Z(z) + , W(w) +{ +} + +template<> +Int4::Vector4Base(const Float2& xy, const Float2& zw) + : X((int32)xy.X) + , Y((int32)xy.Y) + , Z((int32)zw.X) + , W((int32)zw.Y) +{ +} + +template<> +Int4::Vector4Base(const Float3& xyz, int32 w) + : X((int32)xyz.X) + , Y((int32)xyz.Y) + , Z((int32)xyz.Z) + , W(w) +{ +} + +template<> +Int4::Vector4Base(const Int2& xy, int32 z, int32 w) + : X(xy.X) + , Y(xy.Y) + , Z(z) + , W(w) +{ +} + +template<> +Int4::Vector4Base(const Int3& xyz, int32 w) + : X(xyz.X) + , Y(xyz.Y) + , Z(xyz.Z) + , W(w) +{ +} + +template<> +Int4::Vector4Base(const Double2& xy, int32 z, int32 w) + : X((int32)xy.X) + , Y((int32)xy.Y) + , Z(z) + , W(w) +{ +} + +template<> +Int4::Vector4Base(const Double2& xy, const Double2& zw) + : X((int32)xy.X) + , Y((int32)xy.Y) + , Z((int32)zw.X) + , W((int32)zw.Y) +{ +} + +template<> +Int4::Vector4Base(const Double3& xyz, int32 w) + : X((int32)xyz.X) + , Y((int32)xyz.Y) + , Z((int32)xyz.Z) + , W(w) +{ +} + +template<> +Int4::Vector4Base(const Color& color) + : X((int32)color.R) + , Y((int32)color.G) + , Z((int32)color.B) + , W((int32)color.A) +{ +} + +template<> +Int4::Vector4Base(const Rectangle& rect) + : X((int32)rect.Location.X) + , Y((int32)rect.Location.Y) + , Z((int32)rect.Size.X) + , W((int32)rect.Size.Y) +{ +} + +template<> +String Int4::ToString() const +{ + return String::Format(TEXT("{}"), *this); +} + +template<> +Int4 Int4::Transform(const Int4& v, const Matrix& m) +{ + return v; +} diff --git a/Source/Engine/Core/Math/Vector4.cs b/Source/Engine/Core/Math/Vector4.cs index 237132a20..373308ef4 100644 --- a/Source/Engine/Core/Math/Vector4.cs +++ b/Source/Engine/Core/Math/Vector4.cs @@ -57,6 +57,34 @@ using System.Runtime.InteropServices; namespace FlaxEngine { + /// + /// Represents a four dimensional mathematical vector. + /// + [Unmanaged] + [StructLayout(LayoutKind.Sequential)] + public unsafe partial struct Vector4 + { + /// + /// The X component. + /// + public float X; + + /// + /// The Y component. + /// + public float Y; + + /// + /// The Z component. + /// + public float Z; + + /// + /// The W component. + /// + public float W; + } + [Serializable] [TypeConverter(typeof(TypeConverters.Vector4Converter))] partial struct Vector4 : IEquatable, IFormattable diff --git a/Source/Engine/Core/Math/Vector4.h b/Source/Engine/Core/Math/Vector4.h index 7df59e902..eeddc74a1 100644 --- a/Source/Engine/Core/Math/Vector4.h +++ b/Source/Engine/Core/Math/Vector4.h @@ -3,29 +3,19 @@ #pragma once #include "Math.h" +#include "Mathd.h" #include "Engine/Core/Formatting.h" #include "Engine/Core/Templates.h" -struct Double2; -struct Double3; -struct Double4; -struct Vector2; -struct Vector3; -struct Color; -struct Matrix; -struct Rectangle; -class String; -struct Int2; -struct Int3; -struct Int4; - /// /// Represents a four dimensional mathematical vector with 32-bit precision (per-component). /// -API_STRUCT() struct FLAXENGINE_API Vector4 +template +API_STRUCT(Template) struct Vector4Base { - DECLARE_SCRIPTING_TYPE_MINIMAL(Vector4); -public: + typedef T Real; + static struct ScriptingTypeInitializer TypeInitializer; + union { struct @@ -33,66 +23,64 @@ public: /// /// The X component. /// - API_FIELD() float X; + API_FIELD() T X; /// /// The Y component. /// - API_FIELD() float Y; + API_FIELD() T Y; /// /// The Z component. /// - API_FIELD() float Z; + API_FIELD() T Z; /// /// The W component. /// - API_FIELD() float W; + API_FIELD() T W; }; /// - /// The raw vector values (in xyzw order). + /// The raw vector values (in XYZW order). /// - float Raw[4]; + T Raw[4]; }; public: // Vector with all components equal 0 - static const Vector4 Zero; + static FLAXENGINE_API const Vector4Base Zero; // Vector with all components equal 1 - static const Vector4 One; + static FLAXENGINE_API const Vector4Base One; // Vector X=1, Y=0, Z=0, W=0 - static const Vector4 UnitX; + static FLAXENGINE_API const Vector4Base UnitX; // Vector X=0, Y=1, Z=0, W=0 - static const Vector4 UnitY; + static FLAXENGINE_API const Vector4Base UnitY; // Vector X=0, Y=0, Z=1, W=0 - static const Vector4 UnitZ; + static FLAXENGINE_API const Vector4Base UnitZ; // Vector X=0, Y=0, Z=0, W=1 - static const Vector4 UnitW; + static FLAXENGINE_API const Vector4Base UnitW; - // A minimum Vector4 - static const Vector4 Minimum; + // Vector with all components equal maximum value. + static FLAXENGINE_API const Vector4Base Minimum; - // A maximum Vector4 - static const Vector4 Maximum; + // Vector with all components equal minimum value. + static FLAXENGINE_API const Vector4Base Maximum; public: /// /// Empty constructor. /// - Vector4() + Vector4Base() { } - // Init - // @param xyzw Value to assign to the all components - Vector4(float xyzw) + FORCE_INLINE Vector4Base(T xyzw) : X(xyzw) , Y(xyzw) , Z(xyzw) @@ -100,16 +88,15 @@ public: { } - // Init - // @param xyzw Values to assign - explicit Vector4(float xyzw[4]); + FORCE_INLINE explicit Vector4Base(const T* xyzw) + : X(xyzw[0]) + , Y(xyzw[1]) + , Z(xyzw[2]) + , W(xyzw[3]) + { + } - // Init - // @param x X component value - // @param y Y component value - // @param z Z component value - // @param w W component value - Vector4(float x, float y, float z, float w) + FORCE_INLINE Vector4Base(T x, T y, T z, T w) : X(x) , Y(y) , Z(z) @@ -117,20 +104,28 @@ public: { } - explicit Vector4(const Vector2& xy, float z, float w); - explicit Vector4(const Vector2& xy, const Vector2& zw); - explicit Vector4(const Vector3& xyz, float w); - explicit Vector4(const Int2& xy, float z, float w); - explicit Vector4(const Int3& xyz, float w); - explicit Vector4(const Int4& xyzw); - explicit Vector4(const Double2& xy, float z, float w); - explicit Vector4(const Double3& xyz, float w); - Vector4(const Double4& xyzw); - explicit Vector4(const Color& color); - explicit Vector4(const Rectangle& rect); + template>::Value>::Type...> + FORCE_INLINE explicit Vector4Base(const Vector4Base& xyzw) + : X((T)xyzw.X) + , Y((T)xyzw.Y) + , Z((T)xyzw.Z) + , W((T)xyzw.W) + { + } + + FLAXENGINE_API explicit Vector4Base(const Float2& xy, T z = 0, T w = 0); + FLAXENGINE_API explicit Vector4Base(const Float2& xy, const Float2& zw); + FLAXENGINE_API explicit Vector4Base(const Float3& xyz, T w = 0); + FLAXENGINE_API explicit Vector4Base(const Int2& xy, T z = 0, T w = 0); + FLAXENGINE_API explicit Vector4Base(const Int3& xyz, T w = 0); + FLAXENGINE_API explicit Vector4Base(const Double2& xy, T z = 0, T w = 0); + FLAXENGINE_API explicit Vector4Base(const Double2& xy, const Double2& zw); + FLAXENGINE_API explicit Vector4Base(const Double3& xyz, T w = 0); + FLAXENGINE_API explicit Vector4Base(const Color& color); + FLAXENGINE_API explicit Vector4Base(const Rectangle& rect); public: - String ToString() const; + FLAXENGINE_API String ToString() const; public: // Gets a value indicting whether this vector is zero. @@ -151,26 +146,10 @@ public: return Math::IsOne(X) && Math::IsOne(Y) && Math::IsOne(Z) && Math::IsOne(W); } - /// - /// Calculates a vector with values being absolute values of that vector. - /// - Vector4 GetAbsolute() const - { - return Vector4(Math::Abs(X), Math::Abs(Y), Math::Abs(Z), Math::Abs(W)); - } - - /// - /// Calculates a vector with values being opposite to values of that vector. - /// - Vector4 GetNegative() const - { - return Vector4(-X, -Y, -Z, -W); - } - /// /// Returns the average arithmetic of all the components. /// - float AverageArithmetic() const + T AverageArithmetic() const { return (X + Y + Z + W) * 0.25f; } @@ -178,7 +157,7 @@ public: /// /// Gets the sum of all vector components values. /// - float SumValues() const + T SumValues() const { return X + Y + Z + W; } @@ -186,7 +165,7 @@ public: /// /// Returns the minimum value of all the components. /// - float MinValue() const + T MinValue() const { return Math::Min(X, Y, Z, W); } @@ -194,7 +173,7 @@ public: /// /// Returns the maximum value of all the components. /// - float MaxValue() const + T MaxValue() const { return Math::Max(X, Y, Z, W); } @@ -223,218 +202,257 @@ public: return IsInfinity() || IsNaN(); } + /// + /// Calculates a vector with values being absolute values of that vector. + /// + Vector4Base GetAbsolute() const + { + return Vector4Base(Math::Abs(X), Math::Abs(Y), Math::Abs(Z), Math::Abs(W)); + } + + /// + /// Calculates a vector with values being opposite to values of that vector. + /// + Vector4Base GetNegative() const + { + return Vector4Base(-X, -Y, -Z, -W); + } + public: - // Arithmetic operators with Vector4 - inline Vector4 operator+(const Vector4& b) const + Vector4Base operator+(const Vector4Base& b) const { - return Add(*this, b); + return Vector4Base(X + b.X, Y + b.Y, Z + b.Z, W + b.W); } - inline Vector4 operator-(const Vector4& b) const + Vector4Base operator-(const Vector4Base& b) const { - return Subtract(*this, b); + return Vector4Base(X - b.X, Y - b.Y, Z - b.Z, W - b.W); } - inline Vector4 operator*(const Vector4& b) const + Vector4Base operator*(const Vector4Base& b) const { - return Multiply(*this, b); + return Vector4Base(X * b.X, Y * b.Y, Z * b.Z, W * b.W); } - inline Vector4 operator/(const Vector4& b) const + Vector4Base operator/(const Vector4Base& b) const { - return Divide(*this, b); + return Vector4Base(X / b.X, Y / b.Y, Z / b.Z, W / b.W); } - // op= operators with Vector4 - inline Vector4& operator+=(const Vector4& b) + Vector4Base operator-() const { - *this = Add(*this, b); + return Vector4Base(-X, -Y, -Z, -W); + } + + Vector4Base operator+(T b) const + { + return Vector4Base(X + b, Y + b, Z + b, W + b); + } + + Vector4Base operator-(T b) const + { + return Vector4Base(X - b, Y - b, Z - b, W - b); + } + + Vector4Base operator*(T b) const + { + return Vector4Base(X * b, Y * b, Z * b, W * b); + } + + Vector4Base operator/(T b) const + { + return Vector4Base(X / b, Y / b, Z / b, W / b); + } + + Vector4Base& operator+=(const Vector4Base& b) + { + X += b.X; + Y += b.Y; + Z += b.Z; + W += b.W; return *this; } - inline Vector4& operator-=(const Vector4& b) + Vector4Base& operator-=(const Vector4Base& b) { - *this = Subtract(*this, b); + X -= b.X; + Y -= b.Y; + Z -= b.Z; + W -= b.W; return *this; } - inline Vector4& operator*=(const Vector4& b) + Vector4Base& operator*=(const Vector4Base& b) { - *this = Multiply(*this, b); + X *= b.X; + Y *= b.Y; + Z *= b.Z; + W *= b.W; return *this; } - inline Vector4& operator/=(const Vector4& b) + Vector4Base& operator/=(const Vector4Base& b) { - *this = Divide(*this, b); + X /= b.X; + Y /= b.Y; + Z /= b.Z; + W /= b.W; return *this; } - // Arithmetic operators with float - inline Vector4 operator+(float b) const + Vector4Base& operator+=(T b) { - return Add(*this, b); - } - - inline Vector4 operator-(float b) const - { - return Subtract(*this, b); - } - - inline Vector4 operator*(float b) const - { - return Multiply(*this, b); - } - - inline Vector4 operator/(float b) const - { - return Divide(*this, b); - } - - // op= operators with float - inline Vector4& operator+=(float b) - { - *this = Add(*this, b); + X += b; + Y += b; + Z += b; + W += b; return *this; } - inline Vector4& operator-=(float b) + Vector4Base& operator-=(T b) { - *this = Subtract(*this, b); + X -= b; + Y -= b; + Z -= b; + W -= b; return *this; } - inline Vector4& operator*=(float b) + Vector4Base& operator*=(T b) { - *this = Multiply(*this, b); + X *= b; + Y *= b; + Z *= b; + W *= b; return *this; } - inline Vector4& operator/=(float b) + Vector4Base& operator/=(T b) { - *this = Divide(*this, b); + X /= b; + Y /= b; + Z /= b; + W /= b; return *this; } - // Comparison - inline bool operator==(const Vector4& b) const + bool operator==(const Vector4Base& b) const { return X == b.X && Y == b.Y && Z == b.Z && W == b.W; } - inline bool operator!=(const Vector4& b) const + bool operator!=(const Vector4Base& b) const { return X != b.X || Y != b.Y || Z != b.Z || W != b.W; } - inline bool operator>(const Vector4& b) const + bool operator>(const Vector4Base& b) const { return X > b.X && Y > b.Y && Z > b.Z && W > b.W; } - inline bool operator>=(const Vector4& b) const + bool operator>=(const Vector4Base& b) const { return X >= b.X && Y >= b.Y && Z >= b.Z && W >= b.W; } - inline bool operator<(const Vector4& b) const + bool operator<(const Vector4Base& b) const { return X < b.X && Y < b.Y && Z < b.Z && W < b.W; } - inline bool operator<=(const Vector4& b) const + bool operator<=(const Vector4Base& b) const { return X <= b.X && Y <= b.Y && Z <= b.Z && W <= b.W; } public: - static bool NearEqual(const Vector4& a, const Vector4& b) + static bool NearEqual(const Vector4Base& a, const Vector4Base& b) { return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y) && Math::NearEqual(a.Z, b.Z) && Math::NearEqual(a.W, b.W); } - static bool NearEqual(const Vector4& a, const Vector4& b, float epsilon) + static bool NearEqual(const Vector4Base& a, const Vector4Base& b, T epsilon) { return Math::NearEqual(a.X, b.X, epsilon) && Math::NearEqual(a.Y, b.Y, epsilon) && Math::NearEqual(a.Z, b.Z, epsilon) && Math::NearEqual(a.W, b.W, epsilon); } public: - static void Add(const Vector4& a, const Vector4& b, Vector4& result) + static void Add(const Vector4Base& a, const Vector4Base& b, Vector4Base& result) { - result.X = a.X + b.X; - result.Y = a.Y + b.Y; - result.Z = a.Z + b.Z; - result.W = a.W + b.W; + result = Vector4Base(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W); } - static Vector4 Add(const Vector4& a, const Vector4& b) + static void Subtract(const Vector4Base& a, const Vector4Base& b, Vector4Base& result) { - Vector4 result; - Add(a, b, result); - return result; + result = Vector4Base(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W); } - static void Subtract(const Vector4& a, const Vector4& b, Vector4& result) + static void Multiply(const Vector4Base& a, const Vector4Base& b, Vector4Base& result) { - result.X = a.X - b.X; - result.Y = a.Y - b.Y; - result.Z = a.Z - b.Z; - result.W = a.W - b.W; + result = Vector4Base(a.X * b, a.Y * b, a.Z * b, a.W * b); } - static Vector4 Subtract(const Vector4& a, const Vector4& b) + static void Divide(const Vector4Base& a, const Vector4Base& b, Vector4Base& result) { - Vector4 result; - Subtract(a, b, result); - return result; + result = Vector4Base(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W); } - static Vector4 Multiply(const Vector4& a, const Vector4& b) +public: + static Vector4Base Floor(const Vector4Base& v) { - return Vector4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W); + return Vector4Base(Math::Floor(v.X), Math::Floor(v.Y), Math::Floor(v.Z), Math::Floor(v.W)); } - static Vector4 Multiply(const Vector4& a, float b) + static Vector4Base Frac(const Vector4Base& v) { - return Vector4(a.X * b, a.Y * b, a.Z * b, a.W * b); + return Vector4Base(v.X - (int32)v.X, v.Y - (int32)v.Y, v.Z - (int32)v.Z, v.W - (int32)v.W); } - static Vector4 Divide(const Vector4& a, const Vector4& b) + static Vector4Base Round(const Vector4Base& v) { - return Vector4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W); + return Vector4Base(Math::Round(v.X), Math::Round(v.Y), Math::Round(v.Z), Math::Round(v.W)); } - static Vector4 Divide(const Vector4& a, float b) + static Vector4Base Ceil(const Vector4Base& v) { - return Vector4(a.X / b, a.Y / b, a.Z / b, a.W / b); + return Vector4Base(Math::Ceil(v.X), Math::Ceil(v.Y), Math::Ceil(v.Z), Math::Ceil(v.W)); } - static Vector4 Floor(const Vector4& v); - static Vector4 Frac(const Vector4& v); - static Vector4 Round(const Vector4& v); - static Vector4 Ceil(const Vector4& v); + static Vector4Base Abs(const Vector4Base& v) + { + return Vector4Base(Math::Abs(v.X), Math::Abs(v.Y), Math::Abs(v.Z), Math::Abs(v.W)); + } public: // Restricts a value to be within a specified range - // @param value The value to clamp + // @param v The value to clamp // @param min The minimum value, // @param max The maximum value // @returns Clamped value - static Vector4 Clamp(const Vector4& value, const Vector4& min, const Vector4& max); + static Vector4Base Clamp(const Vector4Base& v, const Vector4Base& min, const Vector4Base& max) + { + Vector4Base result; + Clamp(v, min, max, result); + return result; + } // Restricts a value to be within a specified range - // @param value The value to clamp + // @param v The value to clamp // @param min The minimum value, // @param max The maximum value // @param result When the method completes, contains the clamped value - static void Clamp(const Vector4& value, const Vector4& min, const Vector4& max, Vector4& result); + static void Clamp(const Vector4Base& v, const Vector4Base& min, const Vector4Base& max, Vector4Base& result) + { + result = Vector4Base(Math::Clamp(v.X, min.X, max.X), Math::Clamp(v.Y, min.Y, max.Y), Math::Clamp(v.Z, min.Z, max.Z), Math::Clamp(v.W, min.W, max.W)); + } // Performs a linear interpolation between two vectors // @param start Start vector // @param end End vector // @param amount Value between 0 and 1 indicating the weight of end // @param result When the method completes, contains the linear interpolation of the two vectors - static void Lerp(const Vector4& start, const Vector4& end, float amount, Vector4& result) + static void Lerp(const Vector4Base& start, const Vector4Base& end, T amount, Vector4Base& result) { result.X = Math::Lerp(start.X, end.X, amount); result.Y = Math::Lerp(start.Y, end.Y, amount); @@ -449,48 +467,69 @@ public: // @param end End vector, // @param amount Value between 0 and 1 indicating the weight of @paramref end"/>, // @returns The linear interpolation of the two vectors - static Vector4 Lerp(const Vector4& start, const Vector4& end, float amount) + static Vector4Base Lerp(const Vector4Base& start, const Vector4Base& end, T amount) { - Vector4 result; + Vector4Base result; Lerp(start, end, amount, result); return result; } - static Vector4 Transform(const Vector4& v, const Matrix& m); + FLAXENGINE_API static Vector4Base Transform(const Vector4Base& v, const Matrix& m); }; -inline Vector4 operator+(float a, const Vector4& b) +template +inline Vector4Base operator+(T a, const Vector4Base& b) { return b + a; } -inline Vector4 operator-(float a, const Vector4& b) +template +inline Vector4Base operator-(T a, const Vector4Base& b) { - return Vector4(a) - b; + return Vector4Base(a) - b; } -inline Vector4 operator*(float a, const Vector4& b) +template +inline Vector4Base operator*(T a, const Vector4Base& b) { return b * a; } -inline Vector4 operator/(float a, const Vector4& b) +template +inline Vector4Base operator/(T a, const Vector4Base& b) { - return Vector4(a) / b; + return Vector4Base(a) / b; } namespace Math { - FORCE_INLINE static bool NearEqual(const Vector4& a, const Vector4& b) + template + FORCE_INLINE static bool NearEqual(const Vector4Base& a, const Vector4Base& b) { - return Vector4::NearEqual(a, b); + return Vector4Base::NearEqual(a, b); } } template<> -struct TIsPODType +struct TIsPODType { enum { Value = true }; }; -DEFINE_DEFAULT_FORMATTING(Vector4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W); +DEFINE_DEFAULT_FORMATTING(Float4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W); + +template<> +struct TIsPODType +{ + enum { Value = true }; +}; + +DEFINE_DEFAULT_FORMATTING(Double4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W); + +template<> +struct TIsPODType +{ + enum { Value = true }; +}; + +DEFINE_DEFAULT_FORMATTING(Int4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W); diff --git a/Source/Engine/Core/Math/Viewport.h b/Source/Engine/Core/Math/Viewport.h index 62dd3fa5b..cd10da331 100644 --- a/Source/Engine/Core/Math/Viewport.h +++ b/Source/Engine/Core/Math/Viewport.h @@ -5,7 +5,6 @@ #include "Vector2.h" -struct Vector3; struct Matrix; struct Rectangle; diff --git a/Source/Engine/Core/Types/BaseTypes.h b/Source/Engine/Core/Types/BaseTypes.h index 7011b9920..90015f2b2 100644 --- a/Source/Engine/Core/Types/BaseTypes.h +++ b/Source/Engine/Core/Types/BaseTypes.h @@ -69,25 +69,6 @@ class StringAnsiView; struct Guid; struct DateTime; struct TimeSpan; -struct Vector2; -struct Vector3; -struct Vector4; -struct Double2; -struct Double3; -struct Double4; -struct Int2; -struct Int3; -struct Int4; -struct Quaternion; -struct Matrix; -struct Ray; -struct Rectangle; -struct Plane; -struct BoundingBox; -struct BoundingSphere; -struct BoundingFrustum; -struct Color; -struct Color32; struct Variant; template class Span; @@ -107,6 +88,55 @@ class Function; template class Delegate; +// @formatter:off + +// TODO: move it to Engine configuration +#define USE_LARGE_WORLDS 0 + +#if USE_LARGE_WORLDS +// 64-bit precision for world coordinates +API_TYPEDEF(Alias) typedef double Real; +#else +// 32-bit precision for world coordinates +API_TYPEDEF(Alias) typedef float Real; +#endif + +// Vector2 +template struct Vector2Base; +API_TYPEDEF() typedef Vector2Base Float2; +API_TYPEDEF() typedef Vector2Base Double2; +API_TYPEDEF() typedef Vector2Base Int2; +API_TYPEDEF(Alias) typedef Vector2Base Vector2; + +// Vector3 +template struct Vector3Base; +API_TYPEDEF() typedef Vector3Base Float3; +API_TYPEDEF() typedef Vector3Base Double3; +API_TYPEDEF() typedef Vector3Base Int3; +API_TYPEDEF(Alias) typedef Vector3Base Vector3; + +// Vector4 +template struct Vector4Base; +API_TYPEDEF() typedef Vector4Base Float4; +API_TYPEDEF() typedef Vector4Base Double4; +API_TYPEDEF() typedef Vector4Base Int4; +API_TYPEDEF(Alias) typedef Vector4Base Vector4; + +struct BoundingBox; +struct Matrix; +struct Matrix3x3; +struct Ray; +struct Plane; +struct Rectangle; +struct Quaternion; +struct BoundingSphere; +struct BoundingFrustum; +struct OrientedBoundingBox; +struct Color; +struct Color32; + +// @formatter:on + // Declares full set of operators for the enum type (using binary operation on integer values) #define DECLARE_ENUM_OPERATORS(T) \ inline T operator~ (T a) { return (T)~(int)a; } \ diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp index c5aa7d84b..a371bf64e 100644 --- a/Source/Engine/Debug/DebugDraw.cpp +++ b/Source/Engine/Debug/DebugDraw.cpp @@ -1555,7 +1555,7 @@ void DebugDraw::DrawArc(const Vector3& position, const Quaternion& orientation, t.Color = Color32(color); t.TimeLeft = duration; t.V0 = world.GetTranslation(); - Vector3 pos(Math::Cos(0) * radius, Math::Sin(0) * radius, 0); + Vector3 pos(Math::Cos(0.0f) * radius, Math::Sin(0.0f) * radius, 0); Vector3::Transform(pos, world, t.V2); for (int32 i = 0; i < resolution; i++) { diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h index 46d9090ac..03835e4e8 100644 --- a/Source/Engine/Debug/DebugDraw.h +++ b/Source/Engine/Debug/DebugDraw.h @@ -9,7 +9,6 @@ #include "Engine/Core/Types/Span.h" struct RenderContext; -struct OrientedBoundingBox; class GPUTextureView; class GPUContext; class RenderTask; diff --git a/Source/Engine/Engine/Screen.h b/Source/Engine/Engine/Screen.h index 1a6219709..6545c1a3c 100644 --- a/Source/Engine/Engine/Screen.h +++ b/Source/Engine/Engine/Screen.h @@ -4,6 +4,7 @@ #include "Engine/Scripting/ScriptingType.h" #include "Engine/Input/Enums.h" +#include "Engine/Core/Math/Vector2.h" /// /// Helper class to access display information. diff --git a/Source/Engine/Graphics/GPUContext.h b/Source/Engine/Graphics/GPUContext.h index b87faf6a2..0591e7d33 100644 --- a/Source/Engine/Graphics/GPUContext.h +++ b/Source/Engine/Graphics/GPUContext.h @@ -9,8 +9,6 @@ #include "PixelFormat.h" #include "Config.h" -struct Color; -struct Vector4; class GPUConstantBuffer; class GPUShaderProgramCS; class GPUBuffer; diff --git a/Source/Engine/Level/Actors/BoxVolume.cpp b/Source/Engine/Level/Actors/BoxVolume.cpp index 500451e10..278b0bf0d 100644 --- a/Source/Engine/Level/Actors/BoxVolume.cpp +++ b/Source/Engine/Level/Actors/BoxVolume.cpp @@ -84,8 +84,8 @@ void BoxVolume::OnDebugDrawSelected() for (int32 i = 0; i < 6; i++) { sideLinksFinal[i] = sideLinks[i] * _size; + _transform.LocalToWorld(sideLinksFinal[i], sideLinksFinal[i]); } - _transform.LocalToWorld(sideLinksFinal, 6, sideLinksFinal); for (int32 i = 0; i < 6; i++) { DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(sideLinksFinal[i], 10.0f), Color::YellowGreen, 0, true); diff --git a/Source/Engine/Navigation/NavMeshBuilder.h b/Source/Engine/Navigation/NavMeshBuilder.h index 607e5210c..12b3ec098 100644 --- a/Source/Engine/Navigation/NavMeshBuilder.h +++ b/Source/Engine/Navigation/NavMeshBuilder.h @@ -4,6 +4,8 @@ #if COMPILE_WITH_NAV_MESH_BUILDER +#include "Engine/Core/Types/BaseTypes.h" + class Scene; /// @@ -18,7 +20,7 @@ public: static float GetNavMeshBuildingProgress(); static void Update(); static void Build(Scene* scene, float timeoutMs); - static void Build(Scene* scene, const struct BoundingBox& dirtyBounds, float timeoutMs); + static void Build(Scene* scene, const BoundingBox& dirtyBounds, float timeoutMs); }; #endif diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp index 901d840c9..b53e138b9 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.cpp +++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp @@ -136,8 +136,7 @@ void BoxCollider::UpdateBounds() void BoxCollider::GetGeometry(CollisionShape& collision) { Vector3 size = _size * _cachedScale; - size.Absolute(); const float minSize = 0.001f; - size = Vector3::Max(size * 0.5f, Vector3(minSize)); + size = Vector3::Max(size.GetAbsolute() * 0.5f, Vector3(minSize)); collision.SetBox(size.Raw); } diff --git a/Source/Engine/Physics/Colliders/MeshCollider.cpp b/Source/Engine/Physics/Colliders/MeshCollider.cpp index 7db510f76..36c373e9c 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.cpp +++ b/Source/Engine/Physics/Colliders/MeshCollider.cpp @@ -150,9 +150,8 @@ void MeshCollider::GetGeometry(CollisionShape& collision) { // Prepare scale Vector3 scale = _cachedScale; - scale.Absolute(); const float minSize = 0.001f; - scale = Vector3::Max(scale, minSize); + scale = Vector3::Max(scale.GetNegative(), minSize); // Setup shape (based on type) CollisionDataType type = CollisionDataType::None; diff --git a/Source/Engine/Physics/Colliders/SplineCollider.cpp b/Source/Engine/Physics/Colliders/SplineCollider.cpp index 2a9294404..5283c5a1a 100644 --- a/Source/Engine/Physics/Colliders/SplineCollider.cpp +++ b/Source/Engine/Physics/Colliders/SplineCollider.cpp @@ -280,8 +280,7 @@ void SplineCollider::GetGeometry(CollisionShape& collision) // Prepare scale Vector3 scale = _cachedScale; - scale.Absolute(); - scale = Vector3::Max(scale, minSize); + scale = Vector3::Max(scale.GetAbsolute(), minSize); // TODO: add support for cooking collision for static splines in editor and reusing it in game diff --git a/Source/Engine/Platform/Windows/WindowsInput.h b/Source/Engine/Platform/Windows/WindowsInput.h index e9e695f40..265a5b31d 100644 --- a/Source/Engine/Platform/Windows/WindowsInput.h +++ b/Source/Engine/Platform/Windows/WindowsInput.h @@ -7,8 +7,6 @@ #include "Engine/Platform/Types.h" #include "../Win32/WindowsMinimal.h" -struct Vector2; - /// /// Windows platform specific implementation of the input system parts. Handles XInput devices. /// diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp index 8803c7e5b..fbd945a92 100644 --- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp +++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp @@ -883,8 +883,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con // Calculate optimal tile resolution for the object side Vector3 boundsSizeTile = boundsSize; boundsSizeTile.Raw[tileIndex / 2] = MAX_float; // Ignore depth size - boundsSizeTile.Absolute(); - uint16 tileResolution = (uint16)(boundsSizeTile.MinValue() * tilesScale); + uint16 tileResolution = (uint16)(boundsSizeTile.GetAbsolute().MinValue() * tilesScale); if (tileResolution < 4) { // Skip too small surfaces diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index 09f4c21ec..e389f0d5d 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -387,7 +387,8 @@ RenderList::RenderList(const SpawnParams& params) void RenderList::Init(RenderContext& renderContext) { renderContext.View.Frustum.GetCorners(FrustumCornersWs); - Vector3::Transform(FrustumCornersWs, renderContext.View.View, FrustumCornersVs, 8); + for (int32 i = 0; i < 8; i++) + Vector3::Transform(FrustumCornersWs[i], renderContext.View.View, FrustumCornersVs[i]); } void RenderList::Clear() diff --git a/Source/Engine/Terrain/TerrainPatch.cpp b/Source/Engine/Terrain/TerrainPatch.cpp index f4320400c..efb160272 100644 --- a/Source/Engine/Terrain/TerrainPatch.cpp +++ b/Source/Engine/Terrain/TerrainPatch.cpp @@ -629,8 +629,8 @@ bool ModifyCollision(const TerrainDataUpdateInfo& info, TextureBase::InitData* i const int32 collisionLOD = Math::Clamp(collisionLod, 0, initData->Mips.Count() - 1); const int32 heightFieldChunkSize = ((info.ChunkSize + 1) >> collisionLOD) - 1; const int32 heightFieldSize = heightFieldChunkSize * TerrainPatch::CHUNKS_COUNT_EDGE + 1; - const Int2 samplesOffset = Vector2::FloorToInt(modifiedOffsetRatio * (float)heightFieldSize); - Int2 samplesSize = Vector2::CeilToInt(modifiedSizeRatio * (float)heightFieldSize); + const Int2 samplesOffset(Vector2::Floor(modifiedOffsetRatio * (float)heightFieldSize)); + Int2 samplesSize(Vector2::Ceil(modifiedSizeRatio * (float)heightFieldSize)); samplesSize.X = Math::Max(samplesSize.X, 1); samplesSize.Y = Math::Max(samplesSize.Y, 1); Int2 samplesEnd = samplesOffset + samplesSize; diff --git a/Source/Engine/Tests/TestMath.cpp b/Source/Engine/Tests/TestMath.cpp index 0f1082bb4..a54e8d4de 100644 --- a/Source/Engine/Tests/TestMath.cpp +++ b/Source/Engine/Tests/TestMath.cpp @@ -107,7 +107,8 @@ TEST_CASE("Transform") Vector3 a4T[1]; Vector3 a4Ta[1] = { t2.Translation }; - t1.LocalToWorld(a4Ta, ARRAY_COUNT(a4Ta), a4T); + for (int32 i = 0; i < ARRAY_COUNT(a4Ta); i++) + a4T[i] = t1.LocalToWorld(a4Ta[i]); Vector3 a4 = a4T[0]; CHECK(Vector3::NearEqual(a1.Translation, a2)); @@ -135,7 +136,8 @@ TEST_CASE("Transform") Vector3 a4T[1]; Vector3 a4Ta[1] = { t2.Translation }; - t1.WorldToLocal(a4Ta, ARRAY_COUNT(a4Ta), a4T); + for (int32 i = 0; i < ARRAY_COUNT(a4Ta); i++) + a4T[i] = t1.WorldToLocal(a4Ta[i]); Vector3 a4 = a4T[0]; CHECK(Vector3::NearEqual(a1.Translation, a2)); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.h b/Source/Engine/Tools/ModelTool/ModelTool.h index 5af8a84eb..69c083843 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.h +++ b/Source/Engine/Tools/ModelTool/ModelTool.h @@ -223,7 +223,7 @@ public: // Transform float Scale = 1.0f; Quaternion Rotation = Quaternion::Identity; - Vector3 Translation = Vector3::Zero; + Float3 Translation = Float3::Zero; bool CenterGeometry = false; // Animation diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp index 9d2d8a25c..ca3ddd3dd 100644 --- a/Source/Engine/Visject/VisjectGraph.cpp +++ b/Source/Engine/Visject/VisjectGraph.cpp @@ -338,13 +338,13 @@ void VisjectExecutor::ProcessGroupMath(Box* box, Node* node, Value& value) switch (v1.Type.Type) { case VariantType::Vector2: - value = v1.AsVector2() - 2 * v2.AsVector2() * Vector2::Dot(v1.AsVector2(), v2.AsVector2()); + value = v1.AsVector2() - 2.0f * v2.AsVector2() * Vector2::Dot(v1.AsVector2(), v2.AsVector2()); break; case VariantType::Vector3: - value = v1.AsVector3() - 2 * v2.AsVector3() * Vector3::Dot(v1.AsVector3(), v2.AsVector3()); + value = v1.AsVector3() - 2.0f * v2.AsVector3() * Vector3::Dot(v1.AsVector3(), v2.AsVector3()); break; case VariantType::Vector4: - value = Vector4(v1.AsVector4() - 2 * v2.AsVector4() * Vector3::Dot((Vector3)v1, (Vector3)v2)); + value = Vector4(v1.AsVector4() - 2.0f * v2.AsVector4() * Vector3::Dot((Vector3)v1, (Vector3)v2)); break; default: CRASH; break;