Removed default Spherical type

This commit is contained in:
Pascal Serrarens 2024-12-26 11:02:35 +01:00
parent d3226fddc9
commit 585a3b0fe5
4 changed files with 49 additions and 424 deletions

View File

@ -276,228 +276,3 @@ SphericalOf<T> SphericalOf<T>::RotateVertical(const SphericalOf<T> &v,
template class SphericalOf<float>;
template class SphericalOf<signed short>;
//---------------------------------------
/*
Spherical::Spherical() {
this->distance = 0.0f;
this->horizontalAngle = 0.0f;
this->verticalAngle = 0.0f;
}
// Spherical::Spherical(Polar polar) {
// this->distance = polar.distance;
// this->horizontalAngle = polar.angle;
// this->verticalAngle = 0.0f;
// }
Spherical::Spherical(float distance,
Angle horizontalAngle,
Angle verticalAngle) {
if (distance < 0) {
this->distance = -distance;
this->horizontalAngle =
Angle::Normalize(horizontalAngle.ToFloat() - 180.0f);
this->verticalAngle = verticalAngle;
} else {
this->distance = distance;
this->horizontalAngle = Angle::Normalize(horizontalAngle);
this->verticalAngle = Angle::Normalize(verticalAngle);
}
}
Spherical::Spherical(Vector3 v) {
this->distance = v.magnitude();
if (distance == 0.0f) {
this->verticalAngle = 0.0f;
this->horizontalAngle = 0.0f;
} else {
this->verticalAngle = (90.0f - acosf(v.Up() / this->distance) *
Passer::LinearAlgebra::Rad2Deg);
this->horizontalAngle =
atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg;
}
}
const Spherical Spherical::zero = Spherical(0.0f, 0.0f, 0.0f);
const Spherical Spherical::forward = Spherical(1.0f, 0.0f, 0.0f);
const Spherical Spherical::back = Spherical(1.0f, 180.0f, 0.0f);
const Spherical Spherical::right = Spherical(1.0f, 90.0f, 0.0f);
const Spherical Spherical::left = Spherical(1.0f, -90.0f, 0.0f);
const Spherical Spherical::up = Spherical(1.0f, 0.0f, 90.0f);
const Spherical Spherical::down = Spherical(1.0f, 0.0f, -90.0f);
bool Spherical::operator==(const Spherical& v) const {
return (this->distance == v.distance &&
this->horizontalAngle.ToFloat() == v.horizontalAngle.ToFloat() &&
this->verticalAngle.ToFloat() == v.verticalAngle.ToFloat());
}
Spherical Spherical::Normalize(const Spherical& v) {
Spherical r = Spherical(1, v.horizontalAngle, v.verticalAngle);
return r;
}
Spherical Spherical::normalized() const {
Spherical r = Spherical(1, this->horizontalAngle, this->verticalAngle);
return r;
}
Spherical Spherical::operator-() const {
Spherical v =
Spherical(this->distance, this->horizontalAngle.ToFloat() + 180.0f,
this->verticalAngle.ToFloat() + 180.0f);
return v;
}
Spherical Spherical::operator-(const Spherical& s2) const {
// let's do it the easy way...
Vector3 v1 = Vector3(*this);
Vector3 v2 = Vector3(s2);
Vector3 v = v1 - v2;
Spherical r = Spherical(v);
return r;
}
Spherical Spherical::operator-=(const Spherical& v) {
*this = *this - v;
return *this;
}
Spherical Spherical::operator+(const Spherical& s2) const {
// let's do it the easy way...
Vector3 v1 = Vector3(*this);
Vector3 v2 = Vector3(s2);
Vector3 v = v1 + v2;
Spherical r = Spherical(v);
return r;
// This is the hard way...
// if (v2.distance <= 0)
// return Spherical(this->distance, this->horizontalAngle,
// this->verticalAngle);
// if (this->distance <= 0)
// return v2;
// float deltaHorizontalAngle =
// (float)Angle::Normalize(v2.horizontalAngle - this->horizontalAngle);
// float horizontalRotation = deltaHorizontalAngle < 0
// ? 180 + deltaHorizontalAngle
// : 180 - deltaHorizontalAngle;
// float deltaVerticalAngle =
// Angle::Normalize(v2.verticalAngle - this->verticalAngle);
// float verticalRotation = deltaVerticalAngle < 0 ? 180 + deltaVerticalAngle
// : 180 - deltaVerticalAngle;
// if (horizontalRotation == 180 && verticalRotation == 180)
// // angle is too small, take this angle and add the distances
// return Spherical(this->distance + v2.distance, this->horizontalAngle,
// this->verticalAngle);
// Angle rotation = AngleBetween(*this, v2);
// float newDistance =
// Angle::CosineRuleSide(v2.distance, this->distance, rotation);
// float angle =
// Angle::CosineRuleAngle(newDistance, this->distance, v2.distance);
// // Now we have to project the angle to the horizontal and vertical
planes...
// // The axis for the angle is the cross product of the two spherical vectors
// // (which function we do not have either...)
// float horizontalAngle = 0;
// float verticalAngle = 0;
// float newHorizontalAngle =
// deltaHorizontalAngle < 0
// ? Angle::Normalize(this->horizontalAngle - horizontalAngle)
// : Angle::Normalize(this->horizontalAngle + horizontalAngle);
// float newVerticalAngle =
// deltaVerticalAngle < 0
// ? Angle::Normalize(this->verticalAngle - verticalAngle)
// : Angle::Normalize(this->verticalAngle + verticalAngle);
// Spherical v = Spherical(newDistance, newHorizontalAngle, newVerticalAngle);
}
Spherical Spherical::operator+=(const Spherical& v) {
*this = *this + v;
return *this;
}
// Spherical Passer::LinearAlgebra::operator*(const Spherical &v, float f) {
// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle);
// }
// Spherical Passer::LinearAlgebra::operator*(float f, const Spherical &v) {
// return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle);
// }
Spherical Spherical::operator*=(float f) {
this->distance *= f;
return *this;
}
// Spherical Passer::LinearAlgebra::operator/(const Spherical &v, float f) {
// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle);
// }
// Spherical Passer::LinearAlgebra::operator/(float f, const Spherical &v) {
// return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle);
// }
Spherical Spherical::operator/=(float f) {
this->distance /= f;
return *this;
}
// float Spherical::GetSwing() {
// // Not sure if this is correct
// return sqrtf(horizontalAngle * horizontalAngle +
// verticalAngle * verticalAngle);
// }
// float Spherical::Distance(const Spherical &s1, const Spherical &s2) {
// float d = 0;
// return d;
// }
#include "AngleUsing.h"
#include "FloatSingle.h"
#include "Vector3.h"
const float epsilon = 1E-05f;
const float Rad2Deg = 57.29578F;
Angle Spherical::AngleBetween(const Spherical& v1, const Spherical& v2) {
// float denominator = sqrtf(v1_3.sqrMagnitude() * v2_3.sqrMagnitude());
float denominator =
v1.distance * v2.distance; // sqrtf(v1.distance * v1.distance *
// v2.distance * v2.distance);
if (denominator < epsilon)
return 0.0f;
Vector3 v1_3 = Vector3(v1);
Vector3 v2_3 = Vector3(v2);
float dot = Vector3::Dot(v1_3, v2_3);
float fraction = dot / denominator;
if (isnan(fraction))
return fraction; // short cut to returning NaN universally
float cdot = Float::Clamp(fraction, -1.0, 1.0);
float r = ((float)acos(cdot)) * Rad2Deg;
return r;
}
Spherical Spherical::Rotate(const Spherical& v,
Angle horizontalAngle,
Angle verticalAngle) {
Spherical r = Spherical(
v.distance, v.horizontalAngle.ToFloat() + horizontalAngle.ToFloat(),
v.verticalAngle.ToFloat() + verticalAngle.ToFloat());
return r;
}
Spherical Spherical::RotateHorizontal(const Spherical& v, Angle a) {
Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat() + a.ToFloat(),
v.verticalAngle.ToFloat());
return r;
}
Spherical Spherical::RotateVertical(const Spherical& v, Angle a) {
Spherical r = Spherical(v.distance, v.horizontalAngle.ToFloat(),
v.verticalAngle.ToFloat() + a.ToFloat());
return r;
}
*/

View File

@ -11,12 +11,10 @@ namespace Passer {
namespace LinearAlgebra {
struct Vector3;
template <typename T>
class PolarOf;
template <typename T> class PolarOf;
template <typename T>
class SphericalOf {
public:
template <typename T> class SphericalOf {
public:
/// @brief The distance in meters
/// @remark The distance should never be negative
float distance;
@ -63,23 +61,23 @@ class SphericalOf {
/// @brief Subtract a spherical vector from this vector
/// @param v The vector to subtract
/// @return The result of the subtraction
SphericalOf<T> operator-(const SphericalOf<T>& v) const;
SphericalOf<T> operator-=(const SphericalOf<T>& v);
SphericalOf<T> operator-(const SphericalOf<T> &v) const;
SphericalOf<T> operator-=(const SphericalOf<T> &v);
/// @brief Add a spherical vector to this vector
/// @param v The vector to add
/// @return The result of the addition
SphericalOf<T> operator+(const SphericalOf<T>& v) const;
SphericalOf<T> operator+=(const SphericalOf<T>& v);
SphericalOf<T> operator+(const SphericalOf<T> &v) const;
SphericalOf<T> operator+=(const SphericalOf<T> &v);
/// @brief Scale the vector uniformly up
/// @param f The scaling factor
/// @return The scaled vector
/// @remark This operation will scale the distance of the vector. The angle
/// will be unaffected.
friend SphericalOf<T> operator*(const SphericalOf<T>& v, float f) {
friend SphericalOf<T> operator*(const SphericalOf<T> &v, float f) {
return SphericalOf<T>(v.distance * f, v.direction);
}
friend SphericalOf<T> operator*(float f, const SphericalOf<T>& v) {
friend SphericalOf<T> operator*(float f, const SphericalOf<T> &v) {
return SphericalOf<T>(f * v.distance, v.direction);
}
SphericalOf<T> operator*=(float f);
@ -88,178 +86,35 @@ class SphericalOf {
/// @return The scaled factor
/// @remark This operation will scale the distance of the vector. The angle
/// will be unaffected.
friend SphericalOf<T> operator/(const SphericalOf<T>& v, float f) {
friend SphericalOf<T> operator/(const SphericalOf<T> &v, float f) {
return SphericalOf<T>(v.distance / f, v.direction);
}
friend SphericalOf<T> operator/(float f, const SphericalOf<T>& v) {
friend SphericalOf<T> operator/(float f, const SphericalOf<T> &v) {
return SphericalOf<T>(f / v.distance, v.direction);
}
SphericalOf<T> operator/=(float f);
/// <summary>
/// The distance between two vectors
/// </summary>
/// <param name="v1">The first vector</param>
/// <param name="v2">The second vector</param>
/// <returns>The distance between the two vectors</returns>
// static float Distance(const Spherical &s1, const Spherical &s2);
static float DistanceBetween(const SphericalOf<T> &v1,
const SphericalOf<T> &v2);
static AngleOf<T> AngleBetween(const SphericalOf<T> &v1,
const SphericalOf<T> &v2);
static AngleOf<T> SignedAngleBetween(const SphericalOf<T> &v1,
const SphericalOf<T> &v2,
const SphericalOf<T> &axis);
static float DistanceBetween(const SphericalOf<T>& v1,
const SphericalOf<T>& v2);
static AngleOf<T> AngleBetween(const SphericalOf<T>& v1,
const SphericalOf<T>& v2);
static AngleOf<T> SignedAngleBetween(const SphericalOf<T>& v1,
const SphericalOf<T>& v2,
const SphericalOf<T>& axis);
static SphericalOf<T> Rotate(const SphericalOf& v,
AngleOf<T> horizontalAngle,
static SphericalOf<T> Rotate(const SphericalOf &v, AngleOf<T> horizontalAngle,
AngleOf<T> verticalAngle);
static SphericalOf<T> RotateHorizontal(const SphericalOf<T>& v,
static SphericalOf<T> RotateHorizontal(const SphericalOf<T> &v,
AngleOf<T> angle);
static SphericalOf<T> RotateVertical(const SphericalOf<T>& v,
static SphericalOf<T> RotateVertical(const SphericalOf<T> &v,
AngleOf<T> angle);
};
using SphericalSingle = SphericalOf<float>;
using Spherical16 = SphericalOf<signed short>;
using Spherical = SphericalSingle;
/*
/// @brief A spherical vector
/// @details This is a vector in 3D space using a spherical coordinate system.
/// It consists of a distance and the polar and elevation angles from a
/// reference direction. The reference direction is typically thought of
/// as a forward direction.
struct Spherical {
public:
/// @brief The distance in meters
/// @remark The distance should never be negative
float distance;
/// @brief The angle in the horizontal plane in degrees, clockwise rotation
/// @details The angle is automatically normalized to -180 .. 180
Angle horizontalAngle;
/// @brief The angle in the vertical plane in degrees. Positive is upward.
/// @details The angle is automatically normalized to -180 .. 180
Angle verticalAngle;
/// @brief Create a new spherical vector with zero degrees and distance
Spherical();
/// @brief Create a new spherical vector
/// @param distance The distance in meters
/// @param horizontalAngle The angle in the horizontal plane in degrees,
/// clockwise rotation
/// @param verticalAngle The angle in the vertical plan in degrees,
/// zero is forward, positive is upward
Spherical(float distance, Angle horizontalAngle, Angle verticalAngle);
/// @brief Convert polar coordinates to spherical coordinates
/// @param polar The polar coordinate
// Spherical(Polar polar);
/// @brief Convert 3D carthesian coordinates to spherical coordinates
/// @param v Vector in 3D carthesian coordinates;
Spherical(Vector3 v);
/// @brief A spherical vector with zero degree angles and distance
const static Spherical zero;
/// @brief A normalized forward-oriented vector
const static Spherical forward;
/// @brief A normalized back-oriented vector
const static Spherical back;
/// @brief A normalized right-oriented vector
const static Spherical right;
/// @brief A normalized left-oriented vector
const static Spherical left;
/// @brief A normalized up-oriented vector
const static Spherical up;
/// @brief A normalized down-oriented vector
const static Spherical down;
/// @brief Equality test to another vector
/// @param v The vector to check against
/// @return true: if it is identical to the given vector
/// @note This uses float comparison to check equality which may have strange
/// effects. Equality on floats should be avoided.
bool operator==(const Spherical& v) const;
/// @brief The vector length
/// @param v The vector for which you need the length
/// @return The vector length;
inline static float Magnitude(const Spherical& v) { return v.distance; }
/// @brief The vector length
/// @return The vector length
inline float magnitude() const { return this->distance; }
/// @brief Convert the vector to a length of 1
/// @param v The vector to convert
/// @return The vector normalized to a length of 1
static Spherical Normalize(const Spherical& v);
/// @brief Convert the vector to a length of a
/// @return The vector normalized to a length of 1
Spherical normalized() const;
/// @brief Negate the vector
/// @return The negated vector
/// This will rotate the vector by 180 degrees horizontally and
/// vertically. Distance will stay the same.
Spherical operator-() const;
/// @brief Subtract a spherical vector from this vector
/// @param v The vector to subtract
/// @return The result of the subtraction
Spherical operator-(const Spherical& v) const;
Spherical operator-=(const Spherical& v);
/// @brief Add a spherical vector to this vector
/// @param v The vector to add
/// @return The result of the addition
Spherical operator+(const Spherical& v) const;
Spherical operator+=(const Spherical& v);
/// @brief Scale the vector uniformly up
/// @param f The scaling factor
/// @return The scaled vector
/// @remark This operation will scale the distance of the vector. The angle
/// will be unaffected.
friend Spherical operator*(const Spherical& v, float f) {
return Spherical(v.distance * f, v.horizontalAngle, v.verticalAngle);
}
friend Spherical operator*(float f, const Spherical& v) {
return Spherical(v.distance * f, v.horizontalAngle,
v.verticalAngle); // not correct, should be f * v.distance
}
Spherical operator*=(float f);
/// @brief Scale the vector uniformly down
/// @param f The scaling factor
/// @return The scaled factor
/// @remark This operation will scale the distance of the vector. The angle
/// will be unaffected.
friend Spherical operator/(const Spherical& v, float f) {
return Spherical(v.distance / f, v.horizontalAngle, v.verticalAngle);
}
friend Spherical operator/(float f, const Spherical& v) {
return Spherical(v.distance / f, v.horizontalAngle,
v.verticalAngle); // not correct, should be f / v.distance
}
Spherical operator/=(float f);
/// <summary>
/// The distance between two vectors
/// </summary>
/// <param name="v1">The first vector</param>
/// <param name="v2">The second vector</param>
/// <returns>The distance between the two vectors</returns>
// static float Distance(const Spherical &s1, const Spherical &s2);
static Angle AngleBetween(const Spherical& v1, const Spherical& v2);
static Spherical Rotate(const Spherical& v,
Angle horizontalAngle,
Angle verticalAngle);
static Spherical RotateHorizontal(const Spherical& v, Angle angle);
static Spherical RotateVertical(const Spherical& v, Angle angle);
};
*/
} // namespace LinearAlgebra
} // namespace Passer
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#include "Polar.h"

View File

@ -30,7 +30,7 @@ Vector3::Vector3(Vector2 v) {
this->z = v.y;
}
Vector3::Vector3(Spherical s) {
Vector3::Vector3(SphericalOf<float> s) {
float verticalRad = (90.0f - s.direction.vertical.InDegrees()) *
Passer::LinearAlgebra::Deg2Rad;
float horizontalRad =
@ -67,21 +67,17 @@ const Vector3 Vector3::back = Vector3(0, 0, -1);
// return Vector3(v.x, 0, v.y);
// }
float Vector3::Magnitude(const Vector3& v) {
float Vector3::Magnitude(const Vector3 &v) {
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}
float Vector3::magnitude() const {
return (float)sqrtf(x * x + y * y + z * z);
}
float Vector3::magnitude() const { return (float)sqrtf(x * x + y * y + z * z); }
float Vector3::SqrMagnitude(const Vector3& v) {
float Vector3::SqrMagnitude(const Vector3 &v) {
return v.x * v.x + v.y * v.y + v.z * v.z;
}
float Vector3::sqrMagnitude() const {
return (x * x + y * y + z * z);
}
float Vector3::sqrMagnitude() const { return (x * x + y * y + z * z); }
Vector3 Vector3::Normalize(const Vector3& v) {
Vector3 Vector3::Normalize(const Vector3 &v) {
float num = Vector3::Magnitude(v);
Vector3 result = Vector3::zero;
if (num > epsilon) {
@ -102,26 +98,26 @@ Vector3 Vector3::operator-() const {
return Vector3(-this->x, -this->y, -this->z);
}
Vector3 Vector3::operator-(const Vector3& v) const {
Vector3 Vector3::operator-(const Vector3 &v) const {
return Vector3(this->x - v.x, this->y - v.y, this->z - v.z);
}
Vector3 Vector3::operator-=(const Vector3& v) {
Vector3 Vector3::operator-=(const Vector3 &v) {
this->x -= v.x;
this->y -= v.y;
this->z -= v.z;
return *this;
}
Vector3 Vector3::operator+(const Vector3& v) const {
Vector3 Vector3::operator+(const Vector3 &v) const {
return Vector3(this->x + v.x, this->y + v.y, this->z + v.z);
}
Vector3 Vector3::operator+=(const Vector3& v) {
Vector3 Vector3::operator+=(const Vector3 &v) {
this->x += v.x;
this->y += v.y;
this->z += v.z;
return *this;
}
Vector3 Vector3::Scale(const Vector3& v1, const Vector3& v2) {
Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) {
return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
}
// Vector3 Passer::LinearAlgebra::operator*(const Vector3 &v, float f) {
@ -149,24 +145,24 @@ Vector3 Vector3::operator/=(float f) {
return *this;
}
float Vector3::Dot(const Vector3& v1, const Vector3& v2) {
float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
bool Vector3::operator==(const Vector3& v) const {
bool Vector3::operator==(const Vector3 &v) const {
return (this->x == v.x && this->y == v.y && this->z == v.z);
}
float Vector3::Distance(const Vector3& v1, const Vector3& v2) {
float Vector3::Distance(const Vector3 &v1, const Vector3 &v2) {
return Magnitude(v1 - v2);
}
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) {
Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) {
return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z,
v1.x * v2.y - v1.y * v2.x);
}
Vector3 Vector3::Project(const Vector3& v, const Vector3& n) {
Vector3 Vector3::Project(const Vector3 &v, const Vector3 &n) {
float sqrMagnitude = Dot(n, n);
if (sqrMagnitude < epsilon)
return Vector3::zero;
@ -177,7 +173,7 @@ Vector3 Vector3::Project(const Vector3& v, const Vector3& n) {
}
}
Vector3 Vector3::ProjectOnPlane(const Vector3& v, const Vector3& n) {
Vector3 Vector3::ProjectOnPlane(const Vector3 &v, const Vector3 &n) {
Vector3 r = v - Project(v, n);
return r;
}
@ -188,7 +184,7 @@ float clamp(float x, float lower, float upper) {
return upperClamp;
}
AngleOf<float> Vector3::Angle(const Vector3& v1, const Vector3& v2) {
AngleOf<float> Vector3::Angle(const Vector3 &v1, const Vector3 &v2) {
float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude());
if (denominator < epsilon)
return AngleOf<float>();
@ -197,16 +193,15 @@ AngleOf<float> Vector3::Angle(const Vector3& v1, const Vector3& v2) {
float fraction = dot / denominator;
if (isnan(fraction))
return AngleOf<float>::Degrees(
fraction); // short cut to returning NaN universally
fraction); // short cut to returning NaN universally
float cdot = clamp(fraction, -1.0, 1.0);
float r = ((float)acos(cdot));
return AngleOf<float>::Radians(r);
}
AngleOf<float> Vector3::SignedAngle(const Vector3& v1,
const Vector3& v2,
const Vector3& axis) {
AngleOf<float> Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2,
const Vector3 &axis) {
// angle in [0,180]
AngleOf<float> angle = Vector3::Angle(v1, v2);
@ -220,7 +215,7 @@ AngleOf<float> Vector3::SignedAngle(const Vector3& v1,
return AngleOf<float>(signed_angle);
}
Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) {
Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float f) {
Vector3 v = v1 + (v2 - v1) * f;
return v;
}

View File

@ -1,7 +1,7 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include <math.h>
#include "Vector3.h"
@ -9,7 +9,7 @@
TEST(Vector3, FromSpherical) {
Vector3 v = Vector3(0, 0, 1);
Spherical s = Spherical::FromVector3(v);
SphericalOf<float> s = SphericalOf<float>::FromVector3(v);
Vector3 r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1";
@ -17,7 +17,7 @@ TEST(Vector3, FromSpherical) {
EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1";
v = Vector3(0, 1, 0);
s = Spherical::FromVector3(v);
s = SphericalOf<float>::FromVector3(v);
r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0";
@ -25,7 +25,7 @@ TEST(Vector3, FromSpherical) {
EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0";
v = Vector3(1, 0, 0);
s = Spherical::FromVector3(v);
s = SphericalOf<float>::FromVector3(v);
r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0";