From 281673dd6bda56b79d03b26a1869ff609660473a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Perrier Date: Wed, 18 Aug 2021 12:48:52 +0200 Subject: [PATCH] Add Double4 impl. cpp --- Source/Engine/Core/Math/Double4.cpp | 208 +++++++++++ Source/Engine/Core/Math/Double4.h | 556 ++++++++++++++++++++++++++++ 2 files changed, 764 insertions(+) create mode 100644 Source/Engine/Core/Math/Double4.cpp create mode 100644 Source/Engine/Core/Math/Double4.h diff --git a/Source/Engine/Core/Math/Double4.cpp b/Source/Engine/Core/Math/Double4.cpp new file mode 100644 index 000000000..ecaf611c1 --- /dev/null +++ b/Source/Engine/Core/Math/Double4.cpp @@ -0,0 +1,208 @@ +// Copyright (c) 2012-2021 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 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 new file mode 100644 index 000000000..65f32e279 --- /dev/null +++ b/Source/Engine/Core/Math/Double4.h @@ -0,0 +1,556 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Platform/Platform.h" +#include "Engine/Core/Formatting.h" +#include "Engine/Core/Templates.h" +#include "Math.h" +#include "Mathd.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. +/// +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) + { + } + + // Init + // @param xy X and Y values in the vector + // @param z Z component value + // @param w W component value + explicit Double4(const Vector2& xy, double z, double w); + + // Init + // @param xy X and Y values in the vector + // @param zw Z and W values in the vector + // @param z Z component value + // @param w W component value + explicit Double4(const Vector2& xy, const Vector2& zw); + + // Init + // @param xyz X, Y and Z values in the vector + // @param w W component value + explicit Double4(const Vector3& xyz, double w); + + // Init + // @param xy X and Y values in the vector + // @param z Z component value + // @param w W component value + explicit Double4(const Int2& xy, double z, double w); + + // Init + // @param xyz X, Y and Z values in the vector + // @param w W component value + explicit Double4(const Int3& xyz, double w); + + // Init + // @param color Int4 value + explicit Double4(const Int4& xyzw); + + // Init + // @param xy X and Y values in the vector + // @param z Z component value + // @param w W component value + explicit Double4(const Double2& xy, double z, double w); + + // Init + // @param xyz X, Y and Z values in the vector + // @param w W component value + explicit Double4(const Double3& xyz, double w); + + // Init + // @param color Color value + explicit Double4(const Color& color); + + // Init + // @param rect Rectangle value + 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 + /// + /// Absolute 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 + /// + /// Negative vector + Double4 GetNegative() const + { + return Double4(-X, -Y, -Z, -W); + } + + /// + /// Returns average arithmetic of all the components + /// + /// Average arithmetic of all the components + double AverageArithmetic() const + { + return (X + Y + Z + W) * 0.25f; + } + + /// + /// Gets sum of all vector components values + /// + /// Sum of X, Y, Z and W + double SumValues() const + { + return X + Y + Z + W; + } + + /// + /// Returns minimum value of all the components + /// + /// Minimum value + double MinValue() const + { + return Math::Min(X, Y, Z, W); + } + + /// + /// Returns maximum value of all the components + /// + /// Maximum value + double MaxValue() const + { + return Math::Max(X, Y, Z, W); + } + + /// + /// Returns true if vector has one or more components is not a number (NaN) + /// + /// True if 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 + /// + /// True if 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 + /// + /// True if 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);