Add math unit tests for c++
This commit is contained in:
@@ -6,35 +6,65 @@
|
||||
#include "Vector4.h"
|
||||
#include "Color.h"
|
||||
|
||||
Float1010102::Float1010102(float x, float y, float z, float w)
|
||||
FloatR10G10B10A2::FloatR10G10B10A2(uint32 packed)
|
||||
: Value(packed)
|
||||
{
|
||||
x = Math::Clamp(x, 0.0f, 1.0f);
|
||||
y = Math::Clamp(y, 0.0f, 1.0f);
|
||||
z = Math::Clamp(z, 0.0f, 1.0f);
|
||||
w = Math::Clamp(w, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
FloatR10G10B10A2::FloatR10G10B10A2(float x, float y, float z, float w)
|
||||
{
|
||||
x = Math::Saturate(x);
|
||||
y = Math::Saturate(y);
|
||||
z = Math::Saturate(z);
|
||||
w = Math::Saturate(w);
|
||||
|
||||
x = Math::Round(x * 1023.0f);
|
||||
y = Math::Round(y * 1023.0f);
|
||||
z = Math::Round(z * 1023.0f);
|
||||
w = Math::Round(w * 3.0f);
|
||||
|
||||
Value = ((uint32)w << 30) |
|
||||
(((uint32)z & 0x3FF) << 20) |
|
||||
(((uint32)y & 0x3FF) << 10) |
|
||||
(((uint32)x & 0x3FF));
|
||||
Value = ((uint32)w << 30) | (((uint32)z & 0x3FF) << 20) | (((uint32)y & 0x3FF) << 10) | (((uint32)x & 0x3FF));
|
||||
}
|
||||
|
||||
Float1010102::Float1010102(const Vector3& v, float alpha)
|
||||
: Float1010102(v.X, v.Y, v.Z, alpha)
|
||||
FloatR10G10B10A2::FloatR10G10B10A2(const Vector3& v, float alpha)
|
||||
: FloatR10G10B10A2(v.X, v.Y, v.Z, alpha)
|
||||
{
|
||||
}
|
||||
|
||||
Float1010102::Float1010102(const float* values)
|
||||
: Float1010102(values[0], values[1], values[2], values[3])
|
||||
FloatR10G10B10A2::FloatR10G10B10A2(const Vector4& v)
|
||||
: FloatR10G10B10A2(v.X, v.Y, v.Z, v.W)
|
||||
{
|
||||
}
|
||||
|
||||
Float1010102::operator Vector4() const
|
||||
FloatR10G10B10A2::FloatR10G10B10A2(const float* values)
|
||||
: FloatR10G10B10A2(values[0], values[1], values[2], values[3])
|
||||
{
|
||||
}
|
||||
|
||||
FloatR10G10B10A2::operator Vector3() const
|
||||
{
|
||||
return ToVector3();
|
||||
}
|
||||
|
||||
FloatR10G10B10A2::operator Vector4() const
|
||||
{
|
||||
return ToVector4();
|
||||
}
|
||||
|
||||
Vector3 FloatR10G10B10A2::ToVector3() const
|
||||
{
|
||||
Vector3 vectorOut;
|
||||
uint32 tmp;
|
||||
tmp = Value & 0x3FF;
|
||||
vectorOut.X = (float)tmp / 1023.f;
|
||||
tmp = (Value >> 10) & 0x3FF;
|
||||
vectorOut.Y = (float)tmp / 1023.f;
|
||||
tmp = (Value >> 20) & 0x3FF;
|
||||
vectorOut.Z = (float)tmp / 1023.f;
|
||||
return vectorOut;
|
||||
}
|
||||
|
||||
Vector4 FloatR10G10B10A2::ToVector4() const
|
||||
{
|
||||
Vector4 vectorOut;
|
||||
uint32 tmp;
|
||||
@@ -48,19 +78,6 @@ Float1010102::operator Vector4() const
|
||||
return vectorOut;
|
||||
}
|
||||
|
||||
Vector3 Float1010102::ToVector3() const
|
||||
{
|
||||
Vector3 vectorOut;
|
||||
uint32 tmp;
|
||||
tmp = Value & 0x3FF;
|
||||
vectorOut.X = (float)tmp / 1023.f;
|
||||
tmp = (Value >> 10) & 0x3FF;
|
||||
vectorOut.Y = (float)tmp / 1023.f;
|
||||
tmp = (Value >> 20) & 0x3FF;
|
||||
vectorOut.Z = (float)tmp / 1023.f;
|
||||
return vectorOut;
|
||||
}
|
||||
|
||||
FloatR11G11B10::FloatR11G11B10(float x, float y, float z)
|
||||
{
|
||||
// Reference: https://github.com/microsoft/DirectXMath
|
||||
|
||||
@@ -13,7 +13,7 @@ typedef Half Float16;
|
||||
/// <summary>
|
||||
/// Packed vector, layout: R:10 bytes, G:10 bytes, B:10 bytes, A:2 bytes, all values are stored as floats in range [0;1].
|
||||
/// </summary>
|
||||
struct FLAXENGINE_API Float1010102
|
||||
struct FLAXENGINE_API FloatR10G10B10A2
|
||||
{
|
||||
union
|
||||
{
|
||||
@@ -28,41 +28,41 @@ struct FLAXENGINE_API Float1010102
|
||||
uint32 Value;
|
||||
};
|
||||
|
||||
Float1010102() = default;
|
||||
FloatR10G10B10A2() = default;
|
||||
|
||||
explicit Float1010102(uint32 packed)
|
||||
: Value(packed)
|
||||
{
|
||||
}
|
||||
|
||||
Float1010102(float x, float y, float z, float w);
|
||||
Float1010102(const Vector3& v, float alpha = 0);
|
||||
explicit Float1010102(const float* values);
|
||||
explicit FloatR10G10B10A2(uint32 packed);
|
||||
FloatR10G10B10A2(float x, float y, float z, float w);
|
||||
FloatR10G10B10A2(const Vector3& v, float alpha = 0);
|
||||
FloatR10G10B10A2(const Vector4& v);
|
||||
explicit FloatR10G10B10A2(const float* values);
|
||||
|
||||
operator uint32() const
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
operator Vector3() const;
|
||||
operator Vector4() const;
|
||||
|
||||
Float1010102& operator=(const Float1010102& other)
|
||||
FloatR10G10B10A2& operator=(const FloatR10G10B10A2& other)
|
||||
{
|
||||
Value = other.Value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Float1010102& operator=(uint32 packed)
|
||||
FloatR10G10B10A2& operator=(uint32 packed)
|
||||
{
|
||||
Value = packed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Vector3 ToVector3() const;
|
||||
Vector4 ToVector4() const;
|
||||
};
|
||||
|
||||
// [Deprecated on 14.01.2022, expires on 14.01.2024]
|
||||
typedef FloatR10G10B10A2 Float1010102;
|
||||
|
||||
// The 3D vector is packed into 32 bits with 11/11/10 bits per floating-point component.
|
||||
struct FLAXENGINE_API FloatR11G11B10
|
||||
{
|
||||
@@ -114,7 +114,6 @@ struct FLAXENGINE_API FloatR11G11B10
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Vector3 ToVector3() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -152,15 +152,9 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Quaternion" /> struct.
|
||||
/// </summary>
|
||||
/// <param name="values">
|
||||
/// The values to assign to the X, Y, Z, and W components of the quaternion. This must be an array
|
||||
/// with four elements.
|
||||
/// </param>
|
||||
/// <param name="values">The values to assign to the X, Y, Z, and W components of the quaternion. This must be an array with four elements.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="values" /> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when <paramref name="values" /> contains more or less than four
|
||||
/// elements.
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="values" /> contains more or less than four elements.</exception>
|
||||
public Quaternion(float[] values)
|
||||
{
|
||||
if (values == null)
|
||||
@@ -177,9 +171,6 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is equivalent to the identity quaternion.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is an identity quaternion; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsIdentity => Equals(Identity);
|
||||
|
||||
/// <summary>
|
||||
@@ -238,7 +229,6 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Gets the angle of the quaternion.
|
||||
/// </summary>
|
||||
/// <value>The angle.</value>
|
||||
public float Angle
|
||||
{
|
||||
get
|
||||
@@ -253,7 +243,6 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Gets the axis components of the quaternion.
|
||||
/// </summary>
|
||||
/// <value>The axis components of the quaternion.</value>
|
||||
public Vector3 Axis
|
||||
{
|
||||
get
|
||||
@@ -270,14 +259,9 @@ namespace FlaxEngine
|
||||
/// Gets or sets the component at the specified index.
|
||||
/// </summary>
|
||||
/// <value>The value of the X, Y, Z, or W component, depending on the index.</value>
|
||||
/// <param name="index">
|
||||
/// The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z
|
||||
/// component, and 3 for the W component.
|
||||
/// </param>
|
||||
/// <param name="index">The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component.</param>
|
||||
/// <returns>The value of the component at the specified index.</returns>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||
/// Thrown when the <paramref name="index" /> is out of the range [0, 3].
|
||||
/// </exception>
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="index" /> is out of the range [0, 3].</exception>
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
@@ -289,10 +273,8 @@ namespace FlaxEngine
|
||||
case 2: return Z;
|
||||
case 3: return W;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(index), "Indices for Quaternion run from 0 to 3, inclusive.");
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
switch (index)
|
||||
@@ -353,20 +335,14 @@ namespace FlaxEngine
|
||||
/// Calculates the length of the quaternion.
|
||||
/// </summary>
|
||||
/// <returns>The length of the quaternion.</returns>
|
||||
/// <remarks>
|
||||
/// <see cref="Quaternion.LengthSquared" /> may be preferred when only the relative length is needed
|
||||
/// and speed is of the essence.
|
||||
/// </remarks>
|
||||
/// <remarks><see cref="Quaternion.LengthSquared" /> may be preferred when only the relative length is needed and speed is of the essence.</remarks>
|
||||
public float Length => (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the squared length of the quaternion.
|
||||
/// </summary>
|
||||
/// <returns>The squared length of the quaternion.</returns>
|
||||
/// <remarks>
|
||||
/// This method may be preferred to <see cref="Quaternion.Length" /> when only a relative length is needed
|
||||
/// and speed is of the essence.
|
||||
/// </remarks>
|
||||
/// <remarks>This method may be preferred to <see cref="Quaternion.Length" /> when only a relative length is needed and speed is of the essence.</remarks>
|
||||
public float LengthSquared => X * X + Y * Y + Z * Z + W * W;
|
||||
|
||||
/// <summary>
|
||||
@@ -1238,8 +1214,7 @@ namespace FlaxEngine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a quaternion given a pitch, yaw and roll values.
|
||||
/// Angles are in degrees.
|
||||
/// Creates a quaternion given a pitch, yaw and roll values. Angles are in degrees.
|
||||
/// </summary>
|
||||
/// <param name="eulerAngles">The pitch, yaw and roll angles of rotation.</param>
|
||||
/// <returns>When the method completes, contains the newly created quaternion.</returns>
|
||||
@@ -1254,8 +1229,7 @@ namespace FlaxEngine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a quaternion given a pitch, yaw and roll values.
|
||||
/// Angles are in degrees.
|
||||
/// Creates a quaternion given a pitch, yaw and roll values. Angles are in degrees.
|
||||
/// </summary>
|
||||
/// <param name="eulerAngles">The pitch, yaw and roll angles of rotation.</param>
|
||||
/// <param name="result">When the method completes, contains the newly created quaternion.</param>
|
||||
@@ -1269,8 +1243,7 @@ namespace FlaxEngine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a quaternion given a pitch, yaw and roll values.
|
||||
/// Angles are in degrees.
|
||||
/// Creates a quaternion given a pitch, yaw and roll values. Angles are in degrees.
|
||||
/// </summary>
|
||||
/// <param name="x">The pitch of rotation (in degrees).</param>
|
||||
/// <param name="y">The yaw of rotation (in degrees).</param>
|
||||
@@ -1287,8 +1260,7 @@ namespace FlaxEngine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a quaternion given a pitch, yaw and roll values.
|
||||
/// Angles are in degrees.
|
||||
/// Creates a quaternion given a pitch, yaw and roll values. Angles are in degrees.
|
||||
/// </summary>
|
||||
/// <param name="x">The pitch of rotation (in degrees).</param>
|
||||
/// <param name="y">The yaw of rotation (in degrees).</param>
|
||||
@@ -1304,8 +1276,7 @@ namespace FlaxEngine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a quaternion given a yaw, pitch, and roll value.
|
||||
/// Angles are in radians. Use <see cref="Mathf.RadiansToDegrees"/> to convert degrees to radians.
|
||||
/// Creates a quaternion given a yaw, pitch, and roll value. Angles are in radians. Use <see cref="Mathf.RadiansToDegrees"/> to convert degrees to radians.
|
||||
/// </summary>
|
||||
/// <param name="yaw">The yaw of rotation (in radians).</param>
|
||||
/// <param name="pitch">The pitch of rotation (in radians).</param>
|
||||
@@ -1331,8 +1302,7 @@ namespace FlaxEngine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a quaternion given a yaw, pitch, and roll value.
|
||||
/// Angles are in radians.
|
||||
/// Creates a quaternion given a yaw, pitch, and roll value. Angles are in radians.
|
||||
/// </summary>
|
||||
/// <param name="yaw">The yaw of rotation (in radians).</param>
|
||||
/// <param name="pitch">The pitch of rotation (in radians).</param>
|
||||
@@ -1523,10 +1493,7 @@ namespace FlaxEngine
|
||||
/// </summary>
|
||||
/// <param name="left">The first value to compare.</param>
|
||||
/// <param name="right">The second value to compare.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if <paramref name="left" /> has the same value as <paramref name="right" />; otherwise,
|
||||
/// <c>false</c>.
|
||||
/// </returns>
|
||||
/// <returns><c>true</c> if <paramref name="left" /> has the same value as <paramref name="right" />; otherwise, <c>false</c>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Quaternion left, Quaternion right)
|
||||
{
|
||||
@@ -1538,10 +1505,7 @@ namespace FlaxEngine
|
||||
/// </summary>
|
||||
/// <param name="left">The first value to compare.</param>
|
||||
/// <param name="right">The second value to compare.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if <paramref name="left" /> has a different value than <paramref name="right" />; otherwise,
|
||||
/// <c>false</c>.
|
||||
/// </returns>
|
||||
/// <returns><c>true</c> if <paramref name="left" /> has a different value than <paramref name="right" />; otherwise, <c>false</c>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(Quaternion left, Quaternion right)
|
||||
{
|
||||
@@ -1551,9 +1515,7 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, _formatString, X, Y, Z, W);
|
||||
@@ -1563,9 +1525,7 @@ namespace FlaxEngine
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public string ToString(string format)
|
||||
{
|
||||
if (format == null)
|
||||
@@ -1579,9 +1539,7 @@ namespace FlaxEngine
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public string ToString(IFormatProvider formatProvider)
|
||||
{
|
||||
return string.Format(formatProvider, _formatString, X, Y, Z, W);
|
||||
@@ -1592,9 +1550,7 @@ namespace FlaxEngine
|
||||
/// </summary>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="formatProvider">The format provider.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public string ToString(string format, IFormatProvider formatProvider)
|
||||
{
|
||||
if (format == null)
|
||||
@@ -1607,9 +1563,7 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
|
||||
/// </returns>
|
||||
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
@@ -1651,9 +1605,7 @@ namespace FlaxEngine
|
||||
/// Determines whether the specified <see cref="Quaternion" /> is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="Quaternion" /> to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <see cref="Quaternion" /> is equal to this instance; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <returns><c>true</c> if the specified <see cref="Quaternion" /> is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(ref Quaternion other)
|
||||
{
|
||||
@@ -1665,9 +1617,7 @@ namespace FlaxEngine
|
||||
/// Determines whether the specified <see cref="Quaternion" /> is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="Quaternion" /> to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <see cref="Quaternion" /> is equal to this instance; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <returns><c>true</c> if the specified <see cref="Quaternion" /> is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(Quaternion other)
|
||||
{
|
||||
@@ -1678,9 +1628,7 @@ namespace FlaxEngine
|
||||
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="System.Object" /> to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object value)
|
||||
{
|
||||
if (!(value is Quaternion))
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// <summary>
|
||||
/// Very basic pseudo numbers generator.
|
||||
/// </summary>
|
||||
class RandomStream
|
||||
class FLAXENGINE_API RandomStream
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -102,7 +102,6 @@ public:
|
||||
uint32 GetUnsignedInt() const
|
||||
{
|
||||
MutateSeed();
|
||||
|
||||
return *(uint32*)&_seed;
|
||||
}
|
||||
|
||||
@@ -145,6 +144,15 @@ public:
|
||||
} while (l > 1.0f || l < ZeroTolerance);
|
||||
return Vector3::Normalize(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random <see cref="Vector3"/> with components in a range between [0;1].
|
||||
/// </summary>
|
||||
/// <returns>A random <see cref="Vector3"/>.</returns>
|
||||
Vector3 GetVector3() const
|
||||
{
|
||||
return Vector3(GetFraction(), GetFraction(), GetFraction());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for rand implementations.
|
||||
|
||||
201
Source/Engine/Tests/TestMath.cpp
Normal file
201
Source/Engine/Tests/TestMath.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Core/Math/Packed.h"
|
||||
#include "Engine/Core/Math/Vector3.h"
|
||||
#include "Engine/Core/Math/Vector4.h"
|
||||
#include "Engine/Core/Math/Quaternion.h"
|
||||
#include "Engine/Core/Math/Transform.h"
|
||||
#include "Engine/Core/RandomStream.h"
|
||||
#include <ThirdParty/catch2/catch.hpp>
|
||||
|
||||
static Quaternion RotationX(float angle)
|
||||
{
|
||||
const float halfAngle = angle * 0.5f;
|
||||
return Quaternion(Math::Sin(halfAngle), 0.0f, 0.0f, Math::Cos(halfAngle));
|
||||
}
|
||||
|
||||
TEST_CASE("FloatR10G10B10A2")
|
||||
{
|
||||
SECTION("Test Conversion")
|
||||
{
|
||||
CHECK(Vector4::NearEqual(Vector4::Zero, FloatR10G10B10A2(Vector4::Zero).ToVector4()));
|
||||
CHECK(Vector4::NearEqual(Vector4::One, FloatR10G10B10A2(Vector4::One).ToVector4()));
|
||||
CHECK(Vector4::NearEqual(Vector4(0.5004888f, 0.5004888f, 0.5004888f, 0.666667f), FloatR10G10B10A2(Vector4(0.5f)).ToVector4()));
|
||||
CHECK(Vector4::NearEqual(Vector4(1, 0, 0, 0), FloatR10G10B10A2(Vector4(1, 0, 0, 0)).ToVector4()));
|
||||
CHECK(Vector4::NearEqual(Vector4(0, 1, 0, 0), FloatR10G10B10A2(Vector4(0, 1, 0, 0)).ToVector4()));
|
||||
CHECK(Vector4::NearEqual(Vector4(0, 0, 1, 0), FloatR10G10B10A2(Vector4(0, 0, 1, 0)).ToVector4()));
|
||||
CHECK(Vector4::NearEqual(Vector4(0, 0, 0, 1), FloatR10G10B10A2(Vector4(0, 0, 0, 1)).ToVector4()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("FloatR11G11B10")
|
||||
{
|
||||
SECTION("Test Conversion")
|
||||
{
|
||||
CHECK(Vector3::NearEqual(Vector3::Zero, FloatR11G11B10(Vector3::Zero).ToVector3()));
|
||||
CHECK(Vector3::NearEqual(Vector3::One, FloatR11G11B10(Vector3::One).ToVector3()));
|
||||
CHECK(Vector3::NearEqual(Vector3(0.5f, 0.5f, 0.5f), FloatR11G11B10(Vector3(0.5f)).ToVector3()));
|
||||
CHECK(Vector3::NearEqual(Vector3(1, 0, 0), FloatR11G11B10(Vector3(1, 0, 0)).ToVector3()));
|
||||
CHECK(Vector3::NearEqual(Vector3(0, 1, 0), FloatR11G11B10(Vector3(0, 1, 0)).ToVector3()));
|
||||
CHECK(Vector3::NearEqual(Vector3(0, 0, 1), FloatR11G11B10(Vector3(0, 0, 1)).ToVector3()));
|
||||
CHECK(Vector3::NearEqual(Vector3(10, 11, 12), FloatR11G11B10(Vector3(10, 11, 12)).ToVector3()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Quaternion")
|
||||
{
|
||||
SECTION("Test Euler")
|
||||
{
|
||||
CHECK(Quaternion::NearEqual(Quaternion::Euler(90, 0, 0), Quaternion(0.7071068f, 0, 0, 0.7071068f)));
|
||||
CHECK(Quaternion::NearEqual(Quaternion::Euler(25, 0, 10), Quaternion(0.215616f, -0.018864f, 0.0850898f, 0.9725809f)));
|
||||
CHECK(Vector3::NearEqual(Vector3(25, 0, 10), Quaternion::Euler(25, 0, 10).GetEuler()));
|
||||
CHECK(Vector3::NearEqual(Vector3(25, -5, 10), Quaternion::Euler(25, -5, 10).GetEuler()));
|
||||
}
|
||||
SECTION("Test Multiply")
|
||||
{
|
||||
auto q = Quaternion::Identity;
|
||||
auto delta = Quaternion::Euler(0, 10, 0);
|
||||
for (int i = 0; i < 9; i++)
|
||||
q *= delta;
|
||||
CHECK(Quaternion::NearEqual(Quaternion::Euler(0, 90, 0), q, 0.00001f));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Transform")
|
||||
{
|
||||
SECTION("Test World Matrix")
|
||||
{
|
||||
Transform t1(Vector3(10, 1, 10), Quaternion::Euler(45, 0, -15), Vector3(1.5f, 0.5f, 0.1f));
|
||||
|
||||
Matrix a1 = t1.GetWorld();
|
||||
|
||||
Matrix a2;
|
||||
{
|
||||
Matrix m1, m2;
|
||||
Matrix::Scaling(t1.Scale, a2);
|
||||
Matrix::RotationQuaternion(t1.Orientation, m2);
|
||||
Matrix::Multiply(a2, m2, m1);
|
||||
Matrix::Translation(t1.Translation, m2);
|
||||
Matrix::Multiply(m1, m2, a2);
|
||||
}
|
||||
|
||||
Matrix a3;
|
||||
Matrix::Transformation(t1.Scale, t1.Orientation, t1.Translation, a3);
|
||||
|
||||
CHECK(a1 == a2);
|
||||
CHECK(a1 == a3);
|
||||
}
|
||||
SECTION("Test Local To World")
|
||||
{
|
||||
Transform t1(Vector3(10, 1, 10), Quaternion::Euler(45, 0, -15), Vector3(1.5f, 0.5f, 0.1f));
|
||||
Transform t2(Vector3(0, 20, 0), Quaternion::Euler(0, 0, 15), Vector3(1.0f, 2.0f, 1.0f));
|
||||
|
||||
Transform a1 = t1.LocalToWorld(t2);
|
||||
Vector3 a2 = t1.LocalToWorld(t2.Translation);
|
||||
|
||||
Vector3 a3;
|
||||
{
|
||||
Vector3 result;
|
||||
Matrix scale, rotation, scaleRotation;
|
||||
Matrix::Scaling(t1.Scale, scale);
|
||||
Matrix::RotationQuaternion(t1.Orientation, rotation);
|
||||
Matrix::Multiply(scale, rotation, scaleRotation);
|
||||
Vector3::Transform(t2.Translation, scaleRotation, result);
|
||||
a3 = result + t1.Translation;
|
||||
}
|
||||
|
||||
Vector3 a4T[1];
|
||||
Vector3 a4Ta[1] = { t2.Translation };
|
||||
t1.LocalToWorld(a4Ta, ARRAY_COUNT(a4Ta), a4T);
|
||||
Vector3 a4 = a4T[0];
|
||||
|
||||
CHECK(Vector3::NearEqual(a1.Translation, a2));
|
||||
CHECK(Vector3::NearEqual(a2, a3));
|
||||
CHECK(Vector3::NearEqual(a2, a4));
|
||||
}
|
||||
SECTION("Test World To Local")
|
||||
{
|
||||
Transform t1 = Transform(Vector3(10, 1, 10), Quaternion::Euler(45, 0, -15), Vector3(1.5f, 0.5f, 0.1f));
|
||||
Transform t2 = Transform(Vector3(0, 20, 0), Quaternion::Euler(0, 0, 15), Vector3(1.0f, 2.0f, 1.0f));
|
||||
|
||||
Transform a1 = t1.WorldToLocal(t2);
|
||||
Vector3 a2 = t1.WorldToLocal(t2.Translation);
|
||||
|
||||
Vector3 a3;
|
||||
{
|
||||
Matrix scale, rotation, scaleRotation;
|
||||
Matrix::Scaling(t1.Scale, scale);
|
||||
Matrix::RotationQuaternion(t1.Orientation, rotation);
|
||||
Matrix::Multiply(scale, rotation, scaleRotation);
|
||||
Matrix::Invert(scaleRotation, scale);
|
||||
a3 = t2.Translation - t1.Translation;
|
||||
Vector3::Transform(a3, scale, a3);
|
||||
}
|
||||
|
||||
Vector3 a4T[1];
|
||||
Vector3 a4Ta[1] = { t2.Translation };
|
||||
t1.WorldToLocal(a4Ta, ARRAY_COUNT(a4Ta), a4T);
|
||||
Vector3 a4 = a4T[0];
|
||||
|
||||
CHECK(Vector3::NearEqual(a1.Translation, a2));
|
||||
CHECK(Vector3::NearEqual(a2, a3, 0.0001f));
|
||||
CHECK(Vector3::NearEqual(a2, a4));
|
||||
}
|
||||
SECTION("Test World Local Space")
|
||||
{
|
||||
Transform trans = Transform(Vector3(1, 2, 3));
|
||||
|
||||
CHECK(Vector3::NearEqual(Vector3(1, 2, 3), trans.LocalToWorld(Vector3(0, 0, 0))));
|
||||
CHECK(Vector3::NearEqual(Vector3(4, 4, 4), trans.LocalToWorld(Vector3(3, 2, 1))));
|
||||
CHECK(Vector3::NearEqual(Vector3(-1, -2, -3), trans.WorldToLocal(Vector3(0, 0, 0))));
|
||||
CHECK(Vector3::NearEqual(Vector3(0, 0, 0), trans.WorldToLocal(Vector3(1, 2, 3))));
|
||||
|
||||
trans = Transform(Vector3::Zero, Quaternion::Euler(0, 90, 0));
|
||||
CHECK(Vector3::NearEqual(Vector3(0, 2, -1), trans.LocalToWorld(Vector3(1, 2, 0))));
|
||||
|
||||
trans.Translation = Vector3(1, 0, 0);
|
||||
trans.Orientation = RotationX(PI * 0.5f);
|
||||
trans.Scale = Vector3(2, 2, 2);
|
||||
CHECK(Vector3::NearEqual(Vector3(1, 0, 2), trans.LocalToWorld(Vector3(0, 1, 0))));
|
||||
|
||||
Transform t1 = trans.LocalToWorld(Transform::Identity);
|
||||
CHECK(Vector3::NearEqual(Vector3(1.0f, 0, 0), t1.Translation));
|
||||
CHECK(Quaternion::NearEqual(RotationX(PI * 0.5f), t1.Orientation));
|
||||
CHECK(Vector3::NearEqual(Vector3(2.0f, 2.0f, 2.0f), t1.Scale));
|
||||
|
||||
Transform t2 = trans.WorldToLocal(Transform::Identity);
|
||||
CHECK(Vector3::NearEqual(Vector3(-0.5f, 0, 0), t2.Translation));
|
||||
CHECK(Quaternion::NearEqual(RotationX(PI * -0.5f), t2.Orientation));
|
||||
CHECK(Vector3::NearEqual(Vector3(0.5f, 0.5f, 0.5f), t2.Scale));
|
||||
|
||||
RandomStream rand(10);
|
||||
for (int32 i = 0; i < 10; i++)
|
||||
{
|
||||
Transform a = Transform(rand.GetVector3(), Quaternion::Euler((float)i * 10, 0, (float)i), rand.GetVector3() * 10.0f);
|
||||
Transform b = Transform(rand.GetVector3(), Quaternion::Euler((float)i, 1, 22), rand.GetVector3() * 0.3f);
|
||||
|
||||
Transform ab = a.LocalToWorld(b);
|
||||
Transform ba = a.WorldToLocal(ab);
|
||||
|
||||
CHECK(Transform::NearEqual(b, ba, 0.00001f));
|
||||
}
|
||||
}
|
||||
SECTION("Test Add Subtract")
|
||||
{
|
||||
RandomStream rand(10);
|
||||
for (int32 i = 0; i < 10; i++)
|
||||
{
|
||||
Transform a = Transform(rand.GetVector3(), Quaternion::Euler((float)i * 10, 0, (float)i), rand.GetVector3() * 10.0f);
|
||||
Transform b = Transform(rand.GetVector3(), Quaternion::Euler((float)i, 1, 22), rand.GetVector3() * 0.3f);
|
||||
|
||||
Transform ab = a + b;
|
||||
Transform newA = ab - b;
|
||||
CHECK(Transform::NearEqual(a, newA, 0.00001f));
|
||||
|
||||
Transform ba = b + a;
|
||||
Transform newB = ba - a;
|
||||
CHECK(Transform::NearEqual(b, newB, 0.00001f));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user