Inline various operators in math types for better performance in Debug builds and better inlining

This commit is contained in:
Wojtek Figat
2022-05-21 11:36:27 +02:00
parent e43ef605c2
commit b7459c7311
5 changed files with 72 additions and 249 deletions

View File

@@ -389,7 +389,7 @@ public:
const double length = Length();
if (!Math::IsZero(length))
{
const double invLength = 1. / length;
const double invLength = 1.0 / length;
X *= invLength;
Y *= invLength;
}

View File

@@ -194,7 +194,7 @@ Double3 Double3::Normalize(const Double3& input)
const double length = input.Length();
if (!Math::IsZero(length))
{
const double inv = 1.0f / length;
const double inv = 1.0 / length;
output.X *= inv;
output.Y *= inv;
output.Z *= inv;
@@ -208,7 +208,7 @@ void Double3::Normalize(const Double3& input, Double3& result)
const double length = input.Length();
if (!Math::IsZero(length))
{
const double inv = 1.0f / length;
const double inv = 1.0 / length;
result.X *= inv;
result.Y *= inv;
result.Z *= inv;
@@ -330,62 +330,6 @@ void Double3::TransformNormal(const Double3& normal, const Matrix& transform, Do
normal.X * transform.M13 + normal.Y * transform.M23 + normal.Z * transform.M33);
}
Double3 Double3::Project(const Double3& vector, const Double3& onNormal)
{
const double sqrMag = Dot(onNormal, onNormal);
if (sqrMag < ZeroTolerance)
return Zero;
return onNormal * Dot(vector, onNormal) / sqrMag;
}
void Double3::Project(const Double3& vector, double x, double y, double width, double height, double minZ, double maxZ, const Matrix& worldViewProjection, Double3& result)
{
Double3 v;
TransformCoordinate(vector, worldViewProjection, v);
result = Double3((1.0 + v.X) * 0.5 * width + x, (1.0 - v.Y) * 0.5 * height + y, v.Z * (maxZ - minZ) + minZ);
}
void Double3::Unproject(const Double3& vector, double x, double y, double width, double height, double minZ, double maxZ, const Matrix& worldViewProjection, Double3& result)
{
Matrix matrix;
Matrix::Invert(worldViewProjection, matrix);
const Double3 v = Double3((vector.X - x) / width * 2.0 - 1.0, -((vector.Y - y) / height * 2.0 - 1.0), (vector.Z - minZ) / (maxZ - minZ));
TransformCoordinate(v, matrix, result);
}
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();
}
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;
}
double Double3::TriangleArea(const Double3& v0, const Double3& v1, const Double3& v2)
{
return (v2 - v0 ^ v1 - v0).Length() * 0.5;

View File

@@ -23,9 +23,8 @@ struct Matrix;
/// </summary>
API_STRUCT() struct FLAXENGINE_API Double3
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Double3);
DECLARE_SCRIPTING_TYPE_MINIMAL(Double3);
public:
union
{
struct
@@ -51,7 +50,6 @@ public:
};
public:
// Vector with all components equal 0
static const Double3 Zero;
@@ -69,7 +67,7 @@ public:
// Vector X=0, Y=0, Z=1
static const Double3 UnitZ;
// A unit vector designating up (0, 1, 0)
static const Double3 Up;
@@ -87,7 +85,7 @@ public:
// 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;
@@ -95,8 +93,6 @@ public:
static const Double3 Maximum;
public:
/// <summary>
/// Empty constructor.
/// </summary>
@@ -143,7 +139,7 @@ public:
// Init
// @param xy Vector2 value
explicit Double3(const Vector2& xy);
// Init
// @param xyz Vector3 value
Double3(const Vector3& xyz);
@@ -168,26 +164,24 @@ public:
// Init
// @param xy Double2 value
explicit Double3(const Double2& xy);
// Init
// @param xy Double2 value
// @param z Z component value
explicit Double3(const Double2& xy, double z);
// Init
// @param xyzw Double4 value
explicit Double3(const Double4& xyzw);
// Init
// @param color Color value
explicit Double3(const Color& color);
public:
String ToString() const;
public:
// Gets a value indicting whether this instance is normalized
bool IsNormalized() const
{
@@ -324,16 +318,15 @@ public:
}
public:
/// <summary>
/// Performs vector normalization (scales vector up to unit length)
/// </summary>
void Normalize()
{
const double length = Length();
if (!Math::IsZero(length))
const double length = Math::Sqrt(X * X + Y * Y + Z * Z);
if (Math::Abs(length) >= ZeroTolerance)
{
const double inv = 1.0f / length;
const double inv = 1.0 / length;
X *= inv;
Y *= inv;
Z *= inv;
@@ -345,7 +338,7 @@ public:
/// </summary>
void NormalizeFast()
{
const double inv = 1.0f / Length();
const double inv = 1.0 / Math::Sqrt(X * X + Y * Y + Z * Z);
X *= inv;
Y *= inv;
Z *= inv;
@@ -377,26 +370,25 @@ public:
void UnwindEuler();
public:
// Arithmetic operators with Double3
Double3 operator+(const Double3& b) const
{
return Add(*this, b);
return Double3(X + b.X, Y + b.Y, Z + b.Z);
}
Double3 operator-(const Double3& b) const
{
return Subtract(*this, b);
return Double3(X - b.X, Y - b.Y, Z - b.Z);
}
Double3 operator*(const Double3& b) const
{
return Multiply(*this, b);
return Double3(X * b.X, Y * b.Y, Z * b.Z);
}
Double3 operator/(const Double3& b) const
{
return Divide(*this, b);
return Double3(X / b.X, Y / b.Y, Z / b.Z);
}
Double3 operator-() const
@@ -417,47 +409,55 @@ public:
// op= operators with Vector3
Double3& operator+=(const Double3& b)
{
*this = Add(*this, b);
X += b.X;
Y += b.Y;
Z += b.Z;
return *this;
}
Double3& operator-=(const Double3& b)
{
*this = Subtract(*this, b);
X -= b.X;
Y -= b.Y;
Z -= b.Z;
return *this;
}
Double3& operator*=(const Double3& b)
{
*this = Multiply(*this, b);
X *= b.X;
Y *= b.Y;
Z *= b.Z;
return *this;
}
Double3& operator/=(const Double3& b)
{
*this = Divide(*this, b);
X /= b.X;
Y /= b.Y;
Z /= b.Z;
return *this;
}
// Arithmetic operators with double
Double3 operator+(double b) const
{
return Add(*this, b);
return Double3(X + b, Y + b, Z + b);
}
Double3 operator-(double b) const
{
return Subtract(*this, b);
return Double3(X - b, Y - b, Z - b);
}
Double3 operator*(double b) const
{
return Multiply(*this, b);
return Double3(X * b, Y * b, Z * b);
}
Double3 operator/(double b) const
{
return Divide(*this, b);
return Double3(X / b, Y / b, Z / b);
}
// op= operators with double
@@ -517,7 +517,6 @@ public:
}
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);
@@ -529,7 +528,6 @@ public:
}
public:
static void Add(const Double3& a, const Double3& b, Double3& result)
{
result.X = a.X + b.X;
@@ -597,7 +595,6 @@ public:
}
public:
// Restricts a value to be within a specified range
// @param value The value to clamp
// @param min The minimum value,
@@ -655,10 +652,7 @@ public:
// @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);
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
@@ -667,10 +661,7 @@ public:
// @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);
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
@@ -810,114 +801,14 @@ public:
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);
}
/// <summary>
/// Projects a vector onto another vector.
/// </summary>
/// <param name="vector">The vector to project.</param>
/// <param name="onNormal">The projection normal vector.</param>
/// <returns>The projected vector.</returns>
static Double3 Project(const Double3& vector, const Double3& onNormal);
/// <summary>
/// Projects a vector onto a plane defined by a normal orthogonal to the plane.
/// </summary>
/// <param name="vector">The vector to project.</param>
/// <param name="planeNormal">The plane normal vector.</param>
/// <returns>The projected vector.</returns>
static Double3 ProjectOnPlane(const Double3& vector, const Double3& planeNormal)
{
return vector - Project(vector, planeNormal);
}
// Projects a 3D vector from object space into screen space
// @param vector The vector to project
// @param x The X position of the viewport
// @param y The Y position of the viewport
// @param width The width of the viewport
// @param height The height of the viewport
// @param minZ The minimum depth of the viewport
// @param maxZ The maximum depth of the viewport
// @param worldViewProjection The combined world-view-projection matrix
// @param result When the method completes, contains the vector in screen space
static void Project(const Double3& vector, double x, double y, double width, double height, double minZ, double maxZ, const Matrix& worldViewProjection, Double3& result);
// Projects a 3D vector from object space into screen space
// @param vector The vector to project
// @param x The X position of the viewport
// @param y The Y position of the viewport
// @param width The width of the viewport
// @param height The height of the viewport
// @param minZ The minimum depth of the viewport
// @param maxZ The maximum depth of the viewport
// @param worldViewProjection The combined world-view-projection matrix
// @returns The vector in screen space
static Double3 Project(const Double3& vector, double x, double y, double width, double height, double minZ, double maxZ, const Matrix& worldViewProjection)
{
Double3 result;
Project(vector, x, y, width, height, minZ, maxZ, worldViewProjection, result);
return result;
}
// Projects a 3D vector from screen space into object space
// @param vector The vector to project
// @param x The X position of the viewport
// @param y The Y position of the viewport
// @param width The width of the viewport
// @param height The height of the viewport
// @param minZ The minimum depth of the viewport
// @param maxZ The maximum depth of the viewport
// @param worldViewProjection The combined world-view-projection matrix
// @param result When the method completes, contains the vector in object space
static void Unproject(const Double3& vector, double x, double y, double width, double height, double minZ, double maxZ, const Matrix& worldViewProjection, Double3& result);
// Projects a 3D vector from screen space into object space
// @param vector The vector to project
// @param x The X position of the viewport
// @param y The Y position of the viewport
// @param width The width of the viewport
// @param height The height of the viewport
// @param minZ The minimum depth of the viewport
// @param maxZ The maximum depth of the viewport
// @param worldViewProjection The combined world-view-projection matrix
// @returns The vector in object space
static Double3 Unproject(const Double3& vector, double x, double y, double width, double height, double minZ, double maxZ, const Matrix& worldViewProjection)
{
Double3 result;
Unproject(vector, x, y, width, height, minZ, maxZ, worldViewProjection, result);
return result;
}
/// <summary>
/// Creates an orthonormal basis from a basis with at least two orthogonal vectors.
/// </summary>
/// <param name="xAxis">The X axis.</param>
/// <param name="yAxis">The y axis.</param>
/// <param name="zAxis">The z axis.</param>
static void CreateOrthonormalBasis(Double3& xAxis, Double3& yAxis, Double3& zAxis);
/// <summary>
/// Finds the best arbitrary axis vectors to represent U and V axes of a plane, by using this vector as the normal of the plane.
/// </summary>
/// <param name="firstAxis">The reference to first axis.</param>
/// <param name="secondAxis">The reference to second axis.</param>
void FindBestAxisVectors(Double3& firstAxis, Double3& secondAxis) const;
static Double3 Round(const Double3& v)
{
return Double3(
Math::Round(v.X),
Math::Round(v.Y),
Math::Round(v.Z)
);
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)
);
return Double3(Math::Ceil(v.X), Math::Ceil(v.Y), Math::Ceil(v.Z));
}
static Double3 Abs(const Double3& v)
@@ -941,7 +832,6 @@ public:
/// <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)

View File

@@ -223,7 +223,7 @@ public:
/// <returns>Average arithmetic of all the components</returns>
double AverageArithmetic() const
{
return (X + Y + Z + W) * 0.25f;
return (X + Y + Z + W) * 0.25;
}
/// <summary>

View File

@@ -23,9 +23,8 @@ struct Int4;
/// </summary>
API_STRUCT() struct FLAXENGINE_API Vector3
{
DECLARE_SCRIPTING_TYPE_MINIMAL(Vector3);
DECLARE_SCRIPTING_TYPE_MINIMAL(Vector3);
public:
union
{
struct
@@ -51,7 +50,6 @@ public:
};
public:
// Vector with all components equal zero (0, 0, 0)
static const Vector3 Zero;
@@ -95,7 +93,6 @@ public:
static const Vector3 Maximum;
public:
/// <summary>
/// Empty constructor.
/// </summary>
@@ -146,7 +143,7 @@ public:
// Init
// @param xy Int22 with X and Y components values
// @param z Z component value
explicit Vector3(const Int2& xy, float z);
explicit Vector3(const Int2& xy, float z);
// Init
// @param xyz Int3 value
@@ -154,7 +151,7 @@ public:
// Init
// @param xyzw Int4 value
explicit Vector3(const Int4& xyzw);
explicit Vector3(const Int4& xyzw);
// Init
// @param xyz Vector4 value
@@ -163,7 +160,7 @@ public:
// Init
// @param xy Double2 with X and Y components values
// @param z Z component value
explicit Vector3(const Double2& xy, float z);
explicit Vector3(const Double2& xy, float z);
// Init
// @param xyz Double3 value
@@ -172,17 +169,15 @@ public:
// Init
// @param xyzw Double4 value
explicit Vector3(const Double4& xyzw);
// Init
// @param color Color value
explicit Vector3(const Color& color);
public:
String ToString() const;
public:
// Gets a value indicting whether this instance is normalized
bool IsNormalized() const
{
@@ -319,14 +314,13 @@ public:
}
public:
/// <summary>
/// Performs vector normalization (scales vector up to unit length)
/// </summary>
void Normalize()
{
const float length = Length();
if (!Math::IsZero(length))
const float length = Math::Sqrt(X * X + Y * Y + Z * Z);
if (Math::Abs(length) >= ZeroTolerance)
{
const float inv = 1.0f / length;
X *= inv;
@@ -340,7 +334,7 @@ public:
/// </summary>
void NormalizeFast()
{
const float inv = 1.0f / Length();
const float inv = 1.0f / Math::Sqrt(X * X + Y * Y + Z * Z);
X *= inv;
Y *= inv;
Z *= inv;
@@ -372,26 +366,25 @@ public:
void UnwindEuler();
public:
// Arithmetic operators with Vector3
Vector3 operator+(const Vector3& b) const
{
return Add(*this, b);
return Vector3(X + b.X, Y + b.Y, Z + b.Z);
}
Vector3 operator-(const Vector3& b) const
{
return Subtract(*this, b);
return Vector3(X - b.X, Y - b.Y, Z - b.Z);
}
Vector3 operator*(const Vector3& b) const
{
return Multiply(*this, b);
return Vector3(X * b.X, Y * b.Y, Z * b.Z);
}
Vector3 operator/(const Vector3& b) const
{
return Divide(*this, b);
return Vector3(X / b.X, Y / b.Y, Z / b.Z);
}
Vector3 operator-() const
@@ -412,47 +405,55 @@ public:
// op= operators with Vector3
Vector3& operator+=(const Vector3& b)
{
*this = Add(*this, b);
X += b.X;
Y += b.Y;
Z += b.Z;
return *this;
}
Vector3& operator-=(const Vector3& b)
{
*this = Subtract(*this, b);
X -= b.X;
Y -= b.Y;
Z -= b.Z;
return *this;
}
Vector3& operator*=(const Vector3& b)
{
*this = Multiply(*this, b);
X *= b.X;
Y *= b.Y;
Z *= b.Z;
return *this;
}
Vector3& operator/=(const Vector3& b)
{
*this = Divide(*this, b);
X /= b.X;
Y /= b.Y;
Z /= b.Z;
return *this;
}
// Arithmetic operators with float
Vector3 operator+(float b) const
{
return Add(*this, b);
return Vector3(X + b, Y + b, Z + b);
}
Vector3 operator-(float b) const
{
return Subtract(*this, b);
return Vector3(X - b, Y - b, Z - b);
}
Vector3 operator*(float b) const
{
return Multiply(*this, b);
return Vector3(X * b, Y * b, Z * b);
}
Vector3 operator/(float b) const
{
return Divide(*this, b);
return Vector3(X / b, Y / b, Z / b);
}
// op= operators with float
@@ -512,7 +513,6 @@ public:
}
public:
static bool NearEqual(const Vector3& a, const Vector3& b)
{
return Math::NearEqual(a.X, b.X) && Math::NearEqual(a.Y, b.Y) && Math::NearEqual(a.Z, b.Z);
@@ -524,7 +524,6 @@ public:
}
public:
static void Add(const Vector3& a, const Vector3& b, Vector3& result)
{
result.X = a.X + b.X;
@@ -587,7 +586,6 @@ public:
static Vector3 Frac(const Vector3& v);
public:
// Restricts a value to be within a specified range
// @param value The value to clamp
// @param min The minimum value,
@@ -662,7 +660,7 @@ public:
// @param inout Input vector to normalize
// @param output Output vector that is normalized (has unit length)
static FORCE_INLINE void Normalize(const Vector3& input, Vector3& result)
{
{
result = Normalize(input);
}
@@ -678,7 +676,7 @@ public:
// @param result When the method completes, contains the cross product of the two vectors
static void Cross(const Vector3& a, const Vector3& b, Vector3& result)
{
result = Vector3(a.Y * b.Z - a.Z * b.Y,a.Z * b.X - a.X * b.Z,a.X * b.Y - a.Y * b.X);
result = Vector3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
}
// Calculates the cross product of two vectors
@@ -687,7 +685,7 @@ public:
// @returns Cross product of the two vectors
static Vector3 Cross(const Vector3& a, const Vector3& b)
{
return Vector3(a.Y * b.Z - a.Z * b.Y,a.Z * b.X - a.X * b.Z,a.X * b.Y - a.Y * b.X);
return Vector3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
}
// Performs a linear interpolation between two vectors
@@ -921,20 +919,12 @@ public:
static Vector3 Round(const Vector3& v)
{
return Vector3(
Math::Round(v.X),
Math::Round(v.Y),
Math::Round(v.Z)
);
return Vector3(Math::Round(v.X), Math::Round(v.Y), Math::Round(v.Z));
}
static Vector3 Ceil(const Vector3& v)
{
return Vector3(
Math::Ceil(v.X),
Math::Ceil(v.Y),
Math::Ceil(v.Z)
);
return Vector3(Math::Ceil(v.X), Math::Ceil(v.Y), Math::Ceil(v.Z));
}
static Vector3 Abs(const Vector3& v)
@@ -958,7 +948,6 @@ public:
/// <param name="to">The second vector.</param>
/// <returns>The angle (in radians).</returns>
static float Angle(const Vector3& from, const Vector3& to);
};
inline Vector3 operator+(float a, const Vector3& b)