Refactor Vector types to support 64-bit precision via define switch

This commit is contained in:
Wojtek Figat
2022-05-25 20:04:33 +02:00
parent 1303740611
commit f82e370392
55 changed files with 2264 additions and 5482 deletions

View File

@@ -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)
{

View File

@@ -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]);
}
}
}

View File

@@ -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"
/// <summary>
/// Describes how one bounding volume contains another.

View File

@@ -6,9 +6,6 @@
#include "Engine/Core/Math/Math.h"
#include "Engine/Core/Templates.h"
class String;
struct Vector3;
struct Vector4;
struct Color32;
/// <summary>

View File

@@ -5,9 +5,6 @@
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
class String;
struct Vector3;
struct Vector4;
struct Color;
/// <summary>

View File

@@ -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<double>(xy.X))
, Y(static_cast<double>(xy.Y))
{
}
Double2::Double2(const Int3& xyz)
: X(static_cast<double>(xyz.X))
, Y(static_cast<double>(xyz.Y))
{
}
Double2::Double2(const Int4& xyzw)
: X(static_cast<double>(xyzw.X))
, Y(static_cast<double>(xyzw.Y))
{
}
Double2::Double2(const Vector2& xy)
: X(static_cast<double>(xy.X))
, Y(static_cast<double>(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);
}

View File

@@ -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;
/// <summary>
/// Represents a two dimensional mathematical vector with 64-bit precision (per-component).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Double2
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Double2);
public:
union
{
struct
{
/// <summary>
/// The X component of the vector.
/// </summary>
API_FIELD() double X;
/// <summary>
/// The Y component of the vector.
/// </summary>
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:
/// <summary>
/// Empty constructor.
/// </summary>
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)
{
}
/// <summary>
/// Init
/// </summary>
/// <param name="v">X and Z components in an array</param>
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);
}
/// <summary>
/// Returns the average arithmetic of all the components.
/// </summary>
double AverageArithmetic() const
{
return (X + Y) * 0.5;
}
/// <summary>
/// Gets the sum of all vector components values.
/// </summary>
double SumValues() const
{
return X + Y;
}
/// <summary>
/// Gets the multiplication result of all vector components values.
/// </summary>
double MulValues() const
{
return X * Y;
}
/// <summary>
/// Returns the minimum value of all the components.
/// </summary>
double MinValue() const
{
return Math::Min(X, Y);
}
/// <summary>
/// Returns the maximum value of all the components.
/// </summary>
double MaxValue() const
{
return Math::Max(X, Y);
}
/// <summary>
/// Returns true if vector has one or more components is not a number (NaN).
/// </summary>
bool IsNaN() const
{
return isnan(X) || isnan(Y);
}
/// <summary>
/// Returns true if vector has one or more components equal to +/- infinity.
/// </summary>
bool IsInfinity() const
{
return isinf(X) || isinf(Y);
}
/// <summary>
/// Returns true if vector has one or more components equal to +/- infinity or NaN.
/// </summary>
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);
}
// <summary>
// Performs a linear interpolation between two vectors.
// </summary>
// @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:
/// <summary>
/// Calculates the area of the triangle.
/// </summary>
/// <param name="v0">The first triangle vertex.</param>
/// <param name="v1">The second triangle vertex.</param>
/// <param name="v2">The third triangle vertex.</param>
/// <returns>The triangle area.</returns>
static double TriangleArea(const Double2& v0, const Double2& v1, const Double2& v2);
/// <summary>
/// Calculates the angle (in radians) between from and to. This is always the smallest value.
/// </summary>
/// <param name="from">The first vector.</param>
/// <param name="to">The second vector.</param>
/// <returns>The angle (in radians).</returns>
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<Double2>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Double2, "X:{0} Y:{1}", v.X, v.Y);
#include "Vector2.h"

View File

@@ -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<double>(xy.X))
, Y(static_cast<double>(xy.Y))
, Z(z)
{
}
Double3::Double3(const Int3& xyz)
: X(static_cast<double>(xyz.X))
, Y(static_cast<double>(xyz.Y))
, Z(static_cast<double>(xyz.Z))
{
}
Double3::Double3(const Int4& xyzw)
: X(static_cast<double>(xyzw.X))
, Y(static_cast<double>(xyzw.Y))
, Z(static_cast<double>(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);
}

View File

@@ -337,16 +337,6 @@ namespace FlaxEngine
}
}
/// <summary>
/// Reverses the direction of the vector.
/// </summary>
public void Negate()
{
X *= -1;
Y *= -1;
Z *= -1;
}
/// <summary>
/// When this vector contains Euler angles (degrees), ensure that angles are between +/-180
/// </summary>

View File

@@ -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;
/// <summary>
/// Represents a two dimensional mathematical vector with 64-bit precision (per-component).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Double3
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Double3);
public:
union
{
struct
{
/// <summary>
/// The X component of the vector.
/// </summary>
API_FIELD() double X;
/// <summary>
/// The Y component of the vector.
/// </summary>
API_FIELD() double Y;
/// <summary>
/// The Z component of the vector.
/// </summary>
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:
/// <summary>
/// Empty constructor.
/// </summary>
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)
{
}
/// <summary>
/// Init
/// </summary>
/// <param name="xyz">X, Y and Z components in an array</param>
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();
}
/// <summary>
/// Calculates a vector with values being absolute values of that vector.
/// </summary>
Double3 GetAbsolute() const
{
return Double3(Math::Abs(X), Math::Abs(Y), Math::Abs(Z));
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector.
/// </summary>
Double3 GetNegative() const
{
return Double3(-X, -Y, -Z);
}
/// <summary>
/// Calculates a normalized vector that has length equal to 1.
/// </summary>
Double3 GetNormalized() const
{
const double rcp = 1.0 / Length();
return Double3(X * rcp, Y * rcp, Z * rcp);
}
/// <summary>
/// Returns the average arithmetic of all the components.
/// </summary>
double AverageArithmetic() const
{
return (X + Y + Z) * 0.333333334;
}
/// <summary>
/// Gets the sum of all vector components values.
/// </summary>
double SumValues() const
{
return X + Y + Z;
}
/// <summary>
/// Returns the minimum value of all the components.
/// </summary>
double MinValue() const
{
return Math::Min(X, Y, Z);
}
/// <summary>
/// Returns the maximum value of all the components.
/// </summary>
double MaxValue() const
{
return Math::Max(X, Y, Z);
}
/// <summary>
/// Returns true if vector has one or more components is not a number (NaN).
/// </summary>
bool IsNaN() const
{
return isnan(X) || isnan(Y) || isnan(Z);
}
/// <summary>
/// Returns true if vector has one or more components equal to +/- infinity.
/// </summary>
bool IsInfinity() const
{
return isinf(X) || isinf(Y) || isinf(Z);
}
/// <summary>
/// Returns true if vector has one or more components equal to +/- infinity or NaN.
/// </summary>
bool IsNanOrInfinity() const
{
return IsInfinity() || IsNaN();
}
public:
/// <summary>
/// Performs vector normalization (scales vector up to unit length).
/// </summary>
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;
}
}
/// <summary>
/// Performs fast vector normalization (scales vector up to unit length).
/// </summary>
void NormalizeFast()
{
const double inv = 1.0 / Math::Sqrt(X * X + Y * Y + Z * Z);
X *= inv;
Y *= inv;
Z *= inv;
}
/// <summary>
/// Sets all vector components to the absolute values.
/// </summary>
void Absolute()
{
X = Math::Abs(X);
Y = Math::Abs(Y);
Z = Math::Abs(Z);
}
/// <summary>
/// Negates all components of that vector.
/// </summary>
void Negate()
{
X = -X;
Y = -Y;
Z = -Z;
}
/// <summary>
/// When this vector contains Euler angles (degrees), ensure that angles are between +/-180.
/// </summary>
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);
}
/// <summary>
/// Performs a linear interpolation between two vectors.
/// </summary>
static Double3 Lerp(const Double3& start, const Double3& end, double amount)
{
Double3 result;
Lerp(start, end, amount, result);
return result;
}
/// <summary>
/// Performs a cubic interpolation between two vectors
/// </summary>
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));
}
/// <summary>
/// Calculates the area of the triangle.
/// </summary>
/// <param name="v0">The first triangle vertex.</param>
/// <param name="v1">The second triangle vertex.</param>
/// <param name="v2">The third triangle vertex.</param>
/// <returns>The triangle area.</returns>
static double TriangleArea(const Double3& v0, const Double3& v1, const Double3& v2);
/// <summary>
/// Calculates the angle (in radians) between from and to. This is always the smallest value.
/// </summary>
/// <param name="from">The first vector.</param>
/// <param name="to">The second vector.</param>
/// <returns>The angle (in radians).</returns>
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<Double3>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Double3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z);
#include "Vector3.h"

View File

@@ -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<double>(xy.X))
, Y(static_cast<double>(xy.Y))
, Z(z)
, W(w)
{
}
Double4::Double4(const Int3& xyz, double w)
: X(static_cast<double>(xyz.X))
, Y(static_cast<double>(xyz.Y))
, Z(static_cast<double>(xyz.Z))
, W(w)
{
}
Double4::Double4(const Int4& xyzw)
: X(static_cast<double>(xyzw.X))
, Y(static_cast<double>(xyzw.Y))
, Z(static_cast<double>(xyzw.X))
, W(static_cast<double>(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]
);
}

View File

@@ -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;
/// <summary>
/// Represents a four dimensional mathematical vector with 64-bit precision (per-component).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Double4
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Double4);
public:
union
{
struct
{
/// <summary>
/// The X component.
/// </summary>
API_FIELD() double X;
/// <summary>
/// The Y component.
/// </summary>
API_FIELD() double Y;
/// <summary>
/// The Z component.
/// </summary>
API_FIELD() double Z;
/// <summary>
/// The W component.
/// </summary>
API_FIELD() double W;
};
/// <summary>
/// The raw vector values (in xyzw order).
/// </summary>
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:
/// <summary>
/// Empty constructor.
/// </summary>
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);
}
/// <summary>
/// Calculates a vector with values being absolute values of that vector.
/// </summary>
Double4 GetAbsolute() const
{
return Double4(Math::Abs(X), Math::Abs(Y), Math::Abs(Z), Math::Abs(W));
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector.
/// </summary>
Double4 GetNegative() const
{
return Double4(-X, -Y, -Z, -W);
}
/// <summary>
/// Returns the average arithmetic of all the components.
/// </summary>
double AverageArithmetic() const
{
return (X + Y + Z + W) * 0.25;
}
/// <summary>
/// Gets the sum of all vector components values.
/// </summary>
double SumValues() const
{
return X + Y + Z + W;
}
/// <summary>
/// Returns the minimum value of all the components.
/// </summary>
double MinValue() const
{
return Math::Min(X, Y, Z, W);
}
/// <summary>
/// Returns the maximum value of all the components.
/// </summary>
double MaxValue() const
{
return Math::Max(X, Y, Z, W);
}
/// <summary>
/// Returns true if vector has one or more components is not a number (NaN).
/// </summary>
bool IsNaN() const
{
return isnan(X) || isnan(Y) || isnan(Z) || isnan(W);
}
/// <summary>
/// Returns true if vector has one or more components equal to +/- infinity.
/// </summary>
bool IsInfinity() const
{
return isinf(X) || isinf(Y) || isinf(Z) || isinf(W);
}
/// <summary>
/// Returns true if vector has one or more components equal to +/- infinity or NaN.
/// </summary>
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);
}
// <summary>
// Performs a linear interpolation between two vectors.
// </summary>
// @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<Double4>
{
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"

View File

@@ -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<int32>(xy.X))
, Y(static_cast<int32>(xy.Y))
{
}
Int2::Int2(const Vector3& xyz)
: X(static_cast<int32>(xyz.X))
, Y(static_cast<int32>(xyz.Y))
{
}
Int2::Int2(const Vector4& xyzw)
: X(static_cast<int32>(xyzw.X))
, Y(static_cast<int32>(xyzw.Y))
{
}
String Int2::ToString() const
{
return String::Format(TEXT("{}"), *this);
}

View File

@@ -2,389 +2,4 @@
#pragma once
#include "Math.h"
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
/// <summary>
/// Two-components vector (32 bit integer type).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Int2
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Int2);
public:
union
{
struct
{
/// <summary>
/// The X component.
/// </summary>
API_FIELD() int32 X;
/// <summary>
/// The Y component.
/// </summary>
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:
/// <summary>
/// Empty constructor.
/// </summary>
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);
}
/// <summary>
/// Gets a value indicting whether this vector is zero.
/// </summary>
/// <returns> True if the vector is zero, otherwise false.</returns>
bool IsZero() const
{
return X == 0 && Y == 0;
}
/// <summary>
/// Gets a value indicting whether any vector component is zero.
/// </summary>
/// <returns> True if a component is zero, otherwise false.</returns>
bool IsAnyZero() const
{
return X == 0 || Y == 0;
}
/// <summary>
/// Gets a value indicting whether this vector is one.
/// </summary>
/// <returns> True if the vector is one, otherwise false.</returns>
bool IsOne() const
{
return X == 1 && Y == 1;
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector
/// </summary>
/// <returns>Negative vector</returns>
Int2 GetNegative() const
{
return Int2(-X, -Y);
}
/// <summary>
/// Returns average arithmetic of all the components
/// </summary>
/// <returns>Average arithmetic of all the components</returns>
float AverageArithmetic() const
{
return (X + Y) * 0.5f;
}
/// <summary>
/// Gets sum of all vector components values
/// </summary>
/// <returns>Sum of X, Y, Z and W</returns>
int32 SumValues() const
{
return X + Y;
}
/// <summary>
/// Returns minimum value of all the components
/// </summary>
/// <returns>Minimum value</returns>
int32 MinValue() const
{
return Math::Min(X, Y);
}
/// <summary>
/// Returns maximum value of all the components
/// </summary>
/// <returns>Maximum value</returns>
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<Int2>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Int2, "X:{0} Y:{1}", v.X, v.Y);
#include "Vector2.h"

View File

@@ -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<int32>(xy.X))
, Y(static_cast<int32>(xy.Y))
, Z(z)
{
}
Int3::Int3(const Vector3& xyz)
: X(static_cast<int32>(xyz.X))
, Y(static_cast<int32>(xyz.Y))
, Z(static_cast<int32>(xyz.Z))
{
}
Int3::Int3(const Vector4& xyzw)
: X(static_cast<int32>(xyzw.X))
, Y(static_cast<int32>(xyzw.Y))
, Z(static_cast<int32>(xyzw.Z))
{
}
String Int3::ToString() const
{
return String::Format(TEXT("{}"), *this);
}

View File

@@ -2,402 +2,4 @@
#pragma once
#include "Math.h"
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
/// <summary>
/// Three-components vector (32 bit integer type).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Int3
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Int3);
public:
union
{
struct
{
/// <summary>
/// The X component.
/// </summary>
API_FIELD() int32 X;
/// <summary>
/// The Y component.
/// </summary>
API_FIELD() int32 Y;
/// <summary>
/// The Z component.
/// </summary>
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:
/// <summary>
/// Empty constructor.
/// </summary>
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:
/// <summary>
/// Gets a value indicting whether this vector is zero.
/// </summary>
/// <returns> True if the vector is zero, otherwise false.</returns>
bool IsZero() const
{
return X == 0 && Y == 0 && Z == 0;
}
/// <summary>
/// Gets a value indicting whether any vector component is zero.
/// </summary>
/// <returns> True if a component is zero, otherwise false.</returns>
bool IsAnyZero() const
{
return X == 0 || Y == 0 || Z == 0;
}
/// <summary>
/// Gets a value indicting whether this vector is one.
/// </summary>
/// <returns> True if the vector is one, otherwise false.</returns>
bool IsOne() const
{
return X == 1 && Y == 1 && Z == 1;
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector
/// </summary>
/// <returns>Negative vector</returns>
Int3 GetNegative() const
{
return Int3(-X, -Y, -Z);
}
/// <summary>
/// Returns average arithmetic of all the components
/// </summary>
/// <returns>Average arithmetic of all the components</returns>
float AverageArithmetic() const
{
return (X + Y + Z) / 3.0f;
}
/// <summary>
/// Gets sum of all vector components values
/// </summary>
/// <returns>Sum of X, Y, Z and W</returns>
int32 SumValues() const
{
return X + Y + Z;
}
/// <summary>
/// Returns minimum value of all the components
/// </summary>
/// <returns>Minimum value</returns>
int32 MinValue() const
{
return Math::Min(X, Y, Z);
}
/// <summary>
/// Returns maximum value of all the components
/// </summary>
/// <returns>Maximum value</returns>
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<Int3>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Int3, "X:{0} Y:{1} Z:{2}", v.X, v.Y, v.Z);
#include "Vector3.h"

View File

@@ -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<int32>(v.X))
, Y(static_cast<int32>(v.Y))
, Z(z)
, W(w)
{
}
Int4::Int4(const Vector3& v, int32 w)
: X(static_cast<int32>(v.X))
, Y(static_cast<int32>(v.Y))
, Z(static_cast<int32>(v.Z))
, W(w)
{
}
Int4::Int4(const Vector4& v)
: X(static_cast<int32>(v.X))
, Y(static_cast<int32>(v.Y))
, Z(static_cast<int32>(v.Z))
, W(static_cast<int32>(v.W))
{
}
String Int4::ToString() const
{
return String::Format(TEXT("{}"), *this);
}

View File

@@ -2,416 +2,4 @@
#pragma once
#include "Math.h"
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
/// <summary>
/// Four-components vector (32 bit integer type).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Int4
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Int4);
public:
union
{
struct
{
/// <summary>
/// The X component.
/// </summary>
API_FIELD() int32 X;
/// <summary>
/// The Y component.
/// </summary>
API_FIELD() int32 Y;
/// <summary>
/// The Z component.
/// </summary>
API_FIELD() int32 Z;
/// <summary>
/// The W component.
/// </summary>
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:
/// <summary>
/// Empty constructor.
/// </summary>
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:
/// <summary>
/// Gets a value indicting whether this vector is zero.
/// </summary>
/// <returns> True if the vector is zero, otherwise false.</returns>
bool IsZero() const
{
return X == 0 && Y == 0 && Z == 0 && W == 0;
}
/// <summary>
/// Gets a value indicting whether any vector component is zero.
/// </summary>
/// <returns> True if a component is zero, otherwise false.</returns>
bool IsAnyZero() const
{
return X == 0 || Y == 0 || Z == 0 || W == 0;
}
/// <summary>
/// Gets a value indicting whether this vector is one.
/// </summary>
/// <returns> True if the vector is one, otherwise false.</returns>
bool IsOne() const
{
return X == 1 && Y == 1 && Z == 1 && W == 1;
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector
/// </summary>
/// <returns>Negative vector</returns>
Int4 GetNegative() const
{
return Int4(-X, -Y, -Z, -W);
}
/// <summary>
/// Returns average arithmetic of all the components
/// </summary>
/// <returns>Average arithmetic of all the components</returns>
float AverageArithmetic() const
{
return (X + Y + Z + W) * 0.25f;
}
/// <summary>
/// Gets sum of all vector components values
/// </summary>
/// <returns>Sum of X, Y, Z and W</returns>
int32 SumValues() const
{
return X + Y + Z + W;
}
/// <summary>
/// Returns minimum value of all the components
/// </summary>
/// <returns>Minimum value</returns>
int32 MinValue() const
{
return Math::Min(X, Y, Z, W);
}
/// <summary>
/// Returns maximum value of all the components
/// </summary>
/// <returns>Maximum value</returns>
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<Int4>
{
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"

View File

@@ -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<typename T>
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<typename T>
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;
}

View File

@@ -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;
}
/// <summary>
/// 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.
/// </summary>

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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));
}
}

View File

@@ -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:
}
}
/// <summary>
/// Reverses the direction of the quaternion.
/// </summary>
void Negate()
{
X = -X;
Y = -Y;
Z = -Z;
W = -W;
}
/// <summary>
/// Converts the quaternion into a unit quaternion.
/// </summary>

View File

@@ -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;

View File

@@ -85,18 +85,16 @@ public:
public:
/// <summary>
/// Checks if transform is an identity transformation
/// Checks if transform is an identity transformation.
/// </summary>
/// <returns>True if is identity, otherwise false</returns>
bool IsIdentity() const
{
return Translation.IsZero() && Orientation.IsIdentity() && Scale.IsOne();
}
/// <summary>
/// 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.
/// </summary>
/// <returns>True if one or more components equal to +/- infinity or NaN</returns>
bool IsNanOrInfinity() const
{
return Translation.IsNanOrInfinity() || Orientation.IsNanOrInfinity() || Scale.IsNanOrInfinity();
@@ -105,7 +103,6 @@ public:
/// <summary>
/// Calculates the determinant of this transformation.
/// </summary>
/// <returns>The determinant.</returns>
FORCE_INLINE float GetDeterminant() const
{
return Scale.X * Scale.Y * Scale.Z;
@@ -113,31 +110,31 @@ public:
public:
/// <summary>
/// Gets rotation matrix (from Orientation)
/// Gets rotation matrix (from Orientation).
/// </summary>
/// <returns>Rotation matrix</returns>
Matrix GetRotation() const;
/// <summary>
/// Gets rotation matrix (from Orientation)
/// Gets rotation matrix (from Orientation).
/// </summary>
/// <param name="result">Matrix to set</param>
void GetRotation(Matrix& result) const;
/// <summary>
/// Sets rotation matrix (from Orientation)
/// Sets rotation matrix (from Orientation).
/// </summary>
/// <param name="value">Rotation matrix</param>
void SetRotation(const Matrix& value);
/// <summary>
/// Gets world matrix that describes transformation as a 4 by 4 matrix
/// Gets world matrix that describes transformation as a 4 by 4 matrix.
/// </summary>
/// <returns>World matrix</returns>
Matrix GetWorld() const;
/// <summary>
/// Gets world matrix that describes transformation as a 4 by 4 matrix
/// Gets world matrix that describes transformation as a 4 by 4 matrix.
/// </summary>
/// <param name="result">World matrix</param>
void GetWorld(Matrix& result) const;
@@ -169,7 +166,12 @@ public:
/// </summary>
/// <param name="other">The local space transformation.</param>
/// <returns>The world space transformation.</returns>
Transform LocalToWorld(const Transform& other) const;
Transform LocalToWorld(const Transform& other) const
{
Transform result;
LocalToWorld(other, result);
return result;
}
/// <summary>
/// Performs transformation of the given transform in local space to the world space of this transform.
@@ -183,7 +185,12 @@ public:
/// </summary>
/// <param name="point">The local space point.</param>
/// <returns>The world space point.</returns>
Vector3 LocalToWorld(const Vector3& point) const;
Vector3 LocalToWorld(const Vector3& point) const
{
Vector3 result;
LocalToWorld(point, result);
return result;
}
/// <summary>
/// Performs transformation of the given vector in local space to the world space of this transform.
@@ -199,20 +206,17 @@ public:
/// <param name="result">The world space point.</param>
void LocalToWorld(const Vector3& point, Vector3& result) const;
/// <summary>
/// Performs transformation of the given points in local space to the world space of this transform.
/// </summary>
/// <param name="points">The local space points.</param>
/// <param name="pointsCount">The amount of the points.</param>
/// <param name="result">The world space points.</param>
void LocalToWorld(const Vector3* points, int32 pointsCount, Vector3* result) const;
/// <summary>
/// Performs transformation of the given transform in local space to the world space of this transform.
/// </summary>
/// <param name="other">The world space transformation.</param>
/// <returns>The local space transformation.</returns>
Transform WorldToLocal(const Transform& other) const;
Transform WorldToLocal(const Transform& other) const
{
Transform result;
WorldToLocal(other, result);
return result;
}
/// <summary>
/// Performs transformation of the given transform in world space to the local space of this transform.
@@ -221,12 +225,24 @@ public:
/// <param name="result">The local space transformation.</param>
void WorldToLocal(const Transform& other, Transform& result) const;
/// <summary>
/// Performs transformation of the given point in world space to the local space of this transform.
/// </summary>
/// <param name="point">The world space point.</param>
/// <param name="result">The local space point.</param>
void WorldToLocal(const Vector3& point, Vector3& result) const;
/// <summary>
/// Performs transformation of the given point in world space to the local space of this transform.
/// </summary>
/// <param name="point">The world space point.</param>
/// <returns>The local space point.</returns>
Vector3 WorldToLocal(const Vector3& point) const;
Vector3 WorldToLocal(const Vector3& point) const
{
Vector3 result;
WorldToLocal(point, result);
return result;
}
/// <summary>
/// Performs transformation of the given vector in world space to the local space of this transform.
@@ -235,14 +251,6 @@ public:
/// <returns>The local space vector.</returns>
Vector3 WorldToLocalVector(const Vector3& vector) const;
/// <summary>
/// Performs transformation of the given points in world space to the local space of this transform.
/// </summary>
/// <param name="points">The world space points.</param>
/// <param name="pointsCount">The amount of the points.</param>
/// <param name="result">The local space points.</param>
void WorldToLocal(const Vector3* points, int32 pointsCount, Vector3* result) const;
public:
FORCE_INLINE Transform operator*(const Transform& other) const
{

View File

@@ -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<float>(xy.X))
, Y(static_cast<float>(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<float>(xyz.X))
, Y(static_cast<float>(xyz.Y))
template<>
Float2::Vector2Base(const Int4& xy)
: X((float)xy.X)
, Y((float)xy.Y)
{
}
Vector2::Vector2(const Int4& xyzw)
: X(static_cast<float>(xyzw.X))
, Y(static_cast<float>(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<float>(xy.X))
, Y(static_cast<float>(xy.Y))
template<>
Float2::Vector2Base(const Double4& xy)
: X((float)xy.X)
, Y((float)xy.Y)
{
}
Vector2::Vector2(const Double3& xyz)
: X(static_cast<float>(xyz.X))
, Y(static_cast<float>(xyz.Y))
{
}
Vector2::Vector2(const Double4& xyzw)
: X(static_cast<float>(xyzw.X))
, Y(static_cast<float>(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;
}

View File

@@ -57,6 +57,24 @@ using System.Runtime.InteropServices;
namespace FlaxEngine
{
/// <summary>
/// Represents a two dimensional mathematical vector.
/// </summary>
[Unmanaged]
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Vector2
{
/// <summary>
/// The X component.
/// </summary>
public float X;
/// <summary>
/// The Y component.
/// </summary>
public float Y;
}
[Serializable]
[TypeConverter(typeof(TypeConverters.Vector2Converter))]
partial struct Vector2 : IEquatable<Vector2>, IFormattable

View File

@@ -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 <type_traits>
/// <summary>
/// Represents a two dimensional mathematical vector with 32-bit precision (per-component).
/// Represents a two dimensional mathematical vector.
/// </summary>
API_STRUCT() struct FLAXENGINE_API Vector2
template<typename T>
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:
/// <summary>
/// The X component of the vector.
/// </summary>
API_FIELD() float X;
API_FIELD() T X;
/// <summary>
/// The Y component of the vector.
/// </summary>
API_FIELD() float Y;
API_FIELD() T Y;
};
// Raw values
float Raw[2];
/// <summary>
/// The raw vector values (in XY order).
/// </summary>
T Raw[2];
};
public:
// Vector with all components equal 0
static const Vector2 Zero;
static FLAXENGINE_API const Vector2Base<T> Zero;
// Vector with all components equal 1
static const Vector2 One;
static FLAXENGINE_API const Vector2Base<T> One;
// Vector X=1, Y=0
static const Vector2 UnitX;
static FLAXENGINE_API const Vector2Base<T> UnitX;
// Vector X=0, Y=1
static const Vector2 UnitY;
static FLAXENGINE_API const Vector2Base<T> UnitY;
// A minimum Vector2
static const Vector2 Minimum;
// Vector with all components equal maximum value.
static FLAXENGINE_API const Vector2Base<T> Minimum;
// A maximum Vector2
static const Vector2 Maximum;
// Vector with all components equal minimum value.
static FLAXENGINE_API const Vector2Base<T> Maximum;
public:
/// <summary>
/// Empty constructor.
/// </summary>
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<typename U = T, typename TEnableIf<TNot<TIsTheSame<T, U>>::Value>::Type...>
FORCE_INLINE explicit Vector2Base(const Vector2Base<U>& 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);
}
/// <summary>
/// Returns the average arithmetic of all the components.
/// </summary>
float AverageArithmetic() const
T AverageArithmetic() const
{
return (X + Y) * 0.5f;
}
@@ -417,7 +156,7 @@ public:
/// <summary>
/// Gets the sum of all vector components values.
/// </summary>
float SumValues() const
T SumValues() const
{
return X + Y;
}
@@ -425,7 +164,7 @@ public:
/// <summary>
/// Gets the multiplication result of all vector components values.
/// </summary>
float MulValues() const
T MulValues() const
{
return X * Y;
}
@@ -433,7 +172,7 @@ public:
/// <summary>
/// Returns the minimum value of all the components.
/// </summary>
float MinValue() const
T MinValue() const
{
return Math::Min(X, Y);
}
@@ -441,7 +180,7 @@ public:
/// <summary>
/// Returns the maximum value of all the components.
/// </summary>
float MaxValue() const
T MaxValue() const
{
return Math::Max(X, Y);
}
@@ -470,13 +209,322 @@ public:
return IsInfinity() || IsNaN();
}
/// <summary>
/// Calculates a vector with values being absolute values of that vector.
/// </summary>
Vector2Base GetAbsolute() const
{
return Vector2Base(Math::Abs(X), Math::Abs(Y));
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector.
/// </summary>
Vector2Base GetNegative() const
{
return Vector2Base(-X, -Y);
}
public:
/// <summary>
/// Performs vector normalization (scales vector up to unit length).
/// </summary>
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:
/// <summary>
/// Calculates the area of the triangle.
@@ -567,7 +552,7 @@ public:
/// <param name="v1">The second triangle vertex.</param>
/// <param name="v2">The third triangle vertex.</param>
/// <returns>The triangle area.</returns>
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);
/// <summary>
/// Calculates the angle (in radians) between from and to. This is always the smallest value.
@@ -575,41 +560,62 @@ public:
/// <param name="from">The first vector.</param>
/// <param name="to">The second vector.</param>
/// <returns>The angle (in radians).</returns>
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<typename T>
inline Vector2Base<T> operator+(T a, const Vector2Base<T>& b)
{
return b + a;
}
inline Vector2 operator-(float a, const Vector2& b)
template<typename T>
inline Vector2Base<T> operator-(T a, const Vector2Base<T>& b)
{
return Vector2(a) - b;
return Vector2Base<T>(a) - b;
}
inline Vector2 operator*(float a, const Vector2& b)
template<typename T>
inline Vector2Base<T> operator*(T a, const Vector2Base<T>& b)
{
return b * a;
}
inline Vector2 operator/(float a, const Vector2& b)
template<typename T>
inline Vector2Base<T> operator/(T a, const Vector2Base<T>& b)
{
return Vector2(a) / b;
return Vector2Base<T>(a) / b;
}
namespace Math
{
FORCE_INLINE static bool NearEqual(const Vector2& a, const Vector2& b)
template<typename T>
FORCE_INLINE static bool NearEqual(const Vector2Base<T>& a, const Vector2Base<T>& b)
{
return Vector2::NearEqual(a, b);
return Vector2Base<T>::NearEqual(a, b);
}
}
template<>
struct TIsPODType<Vector2>
struct TIsPODType<Float2>
{
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<Double2>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Double2, "X:{0} Y:{1}", v.X, v.Y);
template<>
struct TIsPODType<Int2>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Int2, "X:{0} Y:{1}", v.X, v.Y);

View File

@@ -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<float>(xy.X))
, Y(static_cast<float>(xy.Y))
, Z(static_cast<float>(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<float>(xyz.X))
, Y(static_cast<float>(xyz.Y))
, Z(static_cast<float>(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<float>(xyzw.X))
, Y(static_cast<float>(xyzw.Y))
, Z(static_cast<float>(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<float>(xy.X))
, Y(static_cast<float>(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<float>(xyz.X))
, Y(static_cast<float>(xyz.Y))
, Z(static_cast<float>(xyz.Z))
{
}
Vector3::Vector3(const Double4& xyzw)
: X(static_cast<float>(xyzw.X))
, Y(static_cast<float>(xyzw.Y))
, Z(static_cast<float>(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;
}

View File

@@ -57,6 +57,29 @@ using System.Runtime.InteropServices;
namespace FlaxEngine
{
/// <summary>
/// Represents a three dimensional mathematical vector.
/// </summary>
[Unmanaged]
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Vector3
{
/// <summary>
/// The X component.
/// </summary>
public float X;
/// <summary>
/// The Y component.
/// </summary>
public float Y;
/// <summary>
/// The Z component.
/// </summary>
public float Z;
}
[Serializable]
[TypeConverter(typeof(TypeConverters.Vector3Converter))]
partial struct Vector3 : IEquatable<Vector3>, IFormattable
@@ -326,26 +349,6 @@ namespace FlaxEngine
}
}
/// <summary>
/// Reverses the direction of the vector.
/// </summary>
public void Negate()
{
X *= -1;
Y *= -1;
Z *= -1;
}
/// <summary>
/// When this vector contains Euler angles (degrees), ensure that angles are between +/-180
/// </summary>
public void UnwindEuler()
{
X = Mathf.UnwindDegrees(X);
Y = Mathf.UnwindDegrees(Y);
Z = Mathf.UnwindDegrees(Z);
}
/// <summary>
/// Creates an array containing the elements of the vector.
/// </summary>

File diff suppressed because it is too large Load Diff

View File

@@ -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<float>(xy.X))
, Y(static_cast<float>(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<float>(xyz.X))
, Y(static_cast<float>(xyz.Y))
, Z(static_cast<float>(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<float>(xyzw.X))
, Y(static_cast<float>(xyzw.Y))
, Z(static_cast<float>(xyzw.Z))
, W(static_cast<float>(xyzw.W))
{
}
Vector4::Vector4(const Double2& xy, float z, float w)
: X(static_cast<float>(xy.X))
, Y(static_cast<float>(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<float>(xyz.X))
, Y(static_cast<float>(xyz.Y))
, Z(static_cast<float>(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<float>(xyzw.X))
, Y(static_cast<float>(xyzw.Y))
, Z(static_cast<float>(xyzw.Z))
, W(static_cast<float>(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;
}

View File

@@ -57,6 +57,34 @@ using System.Runtime.InteropServices;
namespace FlaxEngine
{
/// <summary>
/// Represents a four dimensional mathematical vector.
/// </summary>
[Unmanaged]
[StructLayout(LayoutKind.Sequential)]
public unsafe partial struct Vector4
{
/// <summary>
/// The X component.
/// </summary>
public float X;
/// <summary>
/// The Y component.
/// </summary>
public float Y;
/// <summary>
/// The Z component.
/// </summary>
public float Z;
/// <summary>
/// The W component.
/// </summary>
public float W;
}
[Serializable]
[TypeConverter(typeof(TypeConverters.Vector4Converter))]
partial struct Vector4 : IEquatable<Vector4>, IFormattable

View File

@@ -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;
/// <summary>
/// Represents a four dimensional mathematical vector with 32-bit precision (per-component).
/// </summary>
API_STRUCT() struct FLAXENGINE_API Vector4
template<typename T>
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:
/// <summary>
/// The X component.
/// </summary>
API_FIELD() float X;
API_FIELD() T X;
/// <summary>
/// The Y component.
/// </summary>
API_FIELD() float Y;
API_FIELD() T Y;
/// <summary>
/// The Z component.
/// </summary>
API_FIELD() float Z;
API_FIELD() T Z;
/// <summary>
/// The W component.
/// </summary>
API_FIELD() float W;
API_FIELD() T W;
};
/// <summary>
/// The raw vector values (in xyzw order).
/// The raw vector values (in XYZW order).
/// </summary>
float Raw[4];
T Raw[4];
};
public:
// Vector with all components equal 0
static const Vector4 Zero;
static FLAXENGINE_API const Vector4Base<T> Zero;
// Vector with all components equal 1
static const Vector4 One;
static FLAXENGINE_API const Vector4Base<T> One;
// Vector X=1, Y=0, Z=0, W=0
static const Vector4 UnitX;
static FLAXENGINE_API const Vector4Base<T> UnitX;
// Vector X=0, Y=1, Z=0, W=0
static const Vector4 UnitY;
static FLAXENGINE_API const Vector4Base<T> UnitY;
// Vector X=0, Y=0, Z=1, W=0
static const Vector4 UnitZ;
static FLAXENGINE_API const Vector4Base<T> UnitZ;
// Vector X=0, Y=0, Z=0, W=1
static const Vector4 UnitW;
static FLAXENGINE_API const Vector4Base<T> UnitW;
// A minimum Vector4
static const Vector4 Minimum;
// Vector with all components equal maximum value.
static FLAXENGINE_API const Vector4Base<T> Minimum;
// A maximum Vector4
static const Vector4 Maximum;
// Vector with all components equal minimum value.
static FLAXENGINE_API const Vector4Base<T> Maximum;
public:
/// <summary>
/// Empty constructor.
/// </summary>
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<typename U = T, typename TEnableIf<TNot<TIsTheSame<T, U>>::Value>::Type...>
FORCE_INLINE explicit Vector4Base(const Vector4Base<U>& 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);
}
/// <summary>
/// Calculates a vector with values being absolute values of that vector.
/// </summary>
Vector4 GetAbsolute() const
{
return Vector4(Math::Abs(X), Math::Abs(Y), Math::Abs(Z), Math::Abs(W));
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector.
/// </summary>
Vector4 GetNegative() const
{
return Vector4(-X, -Y, -Z, -W);
}
/// <summary>
/// Returns the average arithmetic of all the components.
/// </summary>
float AverageArithmetic() const
T AverageArithmetic() const
{
return (X + Y + Z + W) * 0.25f;
}
@@ -178,7 +157,7 @@ public:
/// <summary>
/// Gets the sum of all vector components values.
/// </summary>
float SumValues() const
T SumValues() const
{
return X + Y + Z + W;
}
@@ -186,7 +165,7 @@ public:
/// <summary>
/// Returns the minimum value of all the components.
/// </summary>
float MinValue() const
T MinValue() const
{
return Math::Min(X, Y, Z, W);
}
@@ -194,7 +173,7 @@ public:
/// <summary>
/// Returns the maximum value of all the components.
/// </summary>
float MaxValue() const
T MaxValue() const
{
return Math::Max(X, Y, Z, W);
}
@@ -223,218 +202,257 @@ public:
return IsInfinity() || IsNaN();
}
/// <summary>
/// Calculates a vector with values being absolute values of that vector.
/// </summary>
Vector4Base GetAbsolute() const
{
return Vector4Base(Math::Abs(X), Math::Abs(Y), Math::Abs(Z), Math::Abs(W));
}
/// <summary>
/// Calculates a vector with values being opposite to values of that vector.
/// </summary>
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<typename T>
inline Vector4Base<T> operator+(T a, const Vector4Base<T>& b)
{
return b + a;
}
inline Vector4 operator-(float a, const Vector4& b)
template<typename T>
inline Vector4Base<T> operator-(T a, const Vector4Base<T>& b)
{
return Vector4(a) - b;
return Vector4Base<T>(a) - b;
}
inline Vector4 operator*(float a, const Vector4& b)
template<typename T>
inline Vector4Base<T> operator*(T a, const Vector4Base<T>& b)
{
return b * a;
}
inline Vector4 operator/(float a, const Vector4& b)
template<typename T>
inline Vector4Base<T> operator/(T a, const Vector4Base<T>& b)
{
return Vector4(a) / b;
return Vector4Base<T>(a) / b;
}
namespace Math
{
FORCE_INLINE static bool NearEqual(const Vector4& a, const Vector4& b)
template<typename T>
FORCE_INLINE static bool NearEqual(const Vector4Base<T>& a, const Vector4Base<T>& b)
{
return Vector4::NearEqual(a, b);
return Vector4Base<T>::NearEqual(a, b);
}
}
template<>
struct TIsPODType<Vector4>
struct TIsPODType<Float4>
{
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<Double4>
{
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<Int4>
{
enum { Value = true };
};
DEFINE_DEFAULT_FORMATTING(Int4, "X:{0} Y:{1} Z:{2} W:{3}", v.X, v.Y, v.Z, v.W);

View File

@@ -5,7 +5,6 @@
#include "Vector2.h"
struct Vector3;
struct Matrix;
struct Rectangle;

View File

@@ -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<typename T>
class Span;
@@ -107,6 +88,55 @@ class Function;
template<typename... Params>
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<typename T> struct Vector2Base;
API_TYPEDEF() typedef Vector2Base<float> Float2;
API_TYPEDEF() typedef Vector2Base<double> Double2;
API_TYPEDEF() typedef Vector2Base<int32> Int2;
API_TYPEDEF(Alias) typedef Vector2Base<Real> Vector2;
// Vector3
template<typename T> struct Vector3Base;
API_TYPEDEF() typedef Vector3Base<float> Float3;
API_TYPEDEF() typedef Vector3Base<double> Double3;
API_TYPEDEF() typedef Vector3Base<int32> Int3;
API_TYPEDEF(Alias) typedef Vector3Base<Real> Vector3;
// Vector4
template<typename T> struct Vector4Base;
API_TYPEDEF() typedef Vector4Base<float> Float4;
API_TYPEDEF() typedef Vector4Base<double> Double4;
API_TYPEDEF() typedef Vector4Base<int32> Int4;
API_TYPEDEF(Alias) typedef Vector4Base<Real> 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; } \

View File

@@ -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++)
{

View File

@@ -9,7 +9,6 @@
#include "Engine/Core/Types/Span.h"
struct RenderContext;
struct OrientedBoundingBox;
class GPUTextureView;
class GPUContext;
class RenderTask;

View File

@@ -4,6 +4,7 @@
#include "Engine/Scripting/ScriptingType.h"
#include "Engine/Input/Enums.h"
#include "Engine/Core/Math/Vector2.h"
/// <summary>
/// Helper class to access display information.

View File

@@ -9,8 +9,6 @@
#include "PixelFormat.h"
#include "Config.h"
struct Color;
struct Vector4;
class GPUConstantBuffer;
class GPUShaderProgramCS;
class GPUBuffer;

View File

@@ -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);

View File

@@ -4,6 +4,8 @@
#if COMPILE_WITH_NAV_MESH_BUILDER
#include "Engine/Core/Types/BaseTypes.h"
class Scene;
/// <summary>
@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -7,8 +7,6 @@
#include "Engine/Platform/Types.h"
#include "../Win32/WindowsMinimal.h"
struct Vector2;
/// <summary>
/// Windows platform specific implementation of the input system parts. Handles XInput devices.
/// </summary>

View File

@@ -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

View File

@@ -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()

View File

@@ -629,8 +629,8 @@ bool ModifyCollision(const TerrainDataUpdateInfo& info, TextureBase::InitData* i
const int32 collisionLOD = Math::Clamp<int32>(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;

View File

@@ -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));

View File

@@ -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

View File

@@ -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;