Added linear algebra subtree

This commit is contained in:
Pascal Serrarens 2024-09-02 11:09:43 +02:00
parent 0779554313
commit 60f160fbd6
55 changed files with 10449 additions and 5 deletions

4
.gitmodules vendored
View File

@ -1,7 +1,3 @@
[submodule "LinearAlgebra"]
path = LinearAlgebra
url = ../linear-algebra.git
brnach = main
[submodule "float16"]
path = float16
url = ../float16.git

@ -1 +0,0 @@
Subproject commit 6b3bcfc39195230fd37773b7c1047fd3ca9e3bc9

2
LinearAlgebra/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build
.vscode

View File

@ -0,0 +1,32 @@
# You can override the included template(s) by including variable overrides
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
#
# Specify the docker image to use (only used if using docker runners)
# See http://doc.gitlab.com/ee/ci/docker/using_docker_images.html)
default:
image: rikorose/gcc-cmake
stages:
- test
unit-test-job:
stage: test
script:
- mkdir build
- cd build
- cmake ..
- cmake --build .
- export GTEST_OUTPUT="xml:report.xml"
- ls -la
- "./LinearAlgebraTest"
artifacts:
when: always
reports:
junit: build/report.xml
sast:
stage: test
include:
- template: Security/SAST.gitlab-ci.yml

210
LinearAlgebra/Angle.cpp Normal file
View File

@ -0,0 +1,210 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Angle.h"
#include <math.h>
#include "FloatSingle.h"
const float Rad2Deg = 57.29578F;
const float Deg2Rad = 0.0174532924F;
/*
float Angle::Normalize(float angle) {
if (!isfinite(angle))
return angle;
while (angle <= -180)
angle += 360;
while (angle > 180)
angle -= 360;
return angle;
}
float Angle::Clamp(float angle, float min, float max) {
float normalizedAngle = Normalize(angle);
float r = Float::Clamp(normalizedAngle, min, max);
return r;
}
float Angle::Difference(float a, float b) {
float r = Normalize(b - a);
return r;
}
float Angle::MoveTowards(float fromAngle, float toAngle, float maxAngle) {
float d = toAngle - fromAngle;
float sign = signbit(d) ? -1 : 1;
d = sign * Float::Clamp(fabs(d), 0, maxAngle);
return fromAngle + d;
}
float Angle::CosineRuleSide(float a, float b, float gamma) {
float a2 = a * a;
float b2 = b * b;
float d = a2 + b2 - 2 * a * b * cos(gamma * Angle::Deg2Rad);
// Catch edge cases where float inacuracies lead tot nans
if (d < 0)
return 0;
float c = sqrtf(d);
return c;
}
float Angle::CosineRuleAngle(float a, float b, float c) {
float a2 = a * a;
float b2 = b * b;
float c2 = c * c;
float d = (a2 + b2 - c2) / (2 * a * b);
// Catch edge cases where float inacuracies lead tot nans
if (d >= 1)
return 0;
if (d <= -1)
return 180;
float gamma = acos(d) * Angle::Rad2Deg;
return gamma;
}
float Angle::SineRuleAngle(float a, float beta, float b) {
float alpha = asin(a * sin(beta * Angle::Deg2Rad) / b);
return alpha;
}
*/
//----------------------
template <>
AngleOf<float>::AngleOf(int angle) : value((float)angle) {}
template <>
AngleOf<float>::AngleOf(float angle) : value(angle) {}
// template <>
// AngleOf<float>::operator float() const {
// return value;
// }
template <>
float AngleOf<float>::ToFloat() const {
return value;
}
// template <>
// AngleOf<float> AngleOf<float>::pi = 3.1415927410125732421875F;
// template <>
// AngleOf<float> AngleOf<float>::Rad2Deg = 360.0f / (pi * 2);
// template <>
// AngleOf<float> AngleOf<float>::Deg2Rad = (pi * 2) / 360.0f;
template <>
bool AngleOf<float>::operator==(AngleOf<float> a) {
return this->ToFloat() == a.ToFloat();
}
template <>
AngleOf<float> AngleOf<float>::operator-() const {
AngleOf<float> angle = AngleOf(-this->value);
return angle;
}
template <>
AngleOf<float> AngleOf<float>::operator-(const AngleOf<float>& a) const {
AngleOf<float> angle = AngleOf();
angle.value = this->value - a.value;
return angle;
}
template <>
AngleOf<float> AngleOf<float>::operator+(const AngleOf<float>& a) const {
AngleOf<float> angle = AngleOf();
angle.value = this->value + a.value;
return angle;
}
template <typename T>
AngleOf<T> AngleOf<T>::operator+=(const AngleOf<T>& a) {
this->value += a.value;
return *this;
}
template <typename T>
AngleOf<T> AngleOf<T>::Normalize(AngleOf<T> angle) {
float angleValue = angle.ToFloat();
if (!isfinite(angleValue))
return angle;
while (angleValue <= -180)
angleValue += 360;
while (angleValue > 180)
angleValue -= 360;
return AngleOf(angleValue);
}
template <>
AngleOf<float> AngleOf<float>::Clamp(AngleOf<float> angle,
AngleOf<float> min,
AngleOf<float> max) {
float normalizedAngle = Normalize(angle).ToFloat();
float r = Float::Clamp(normalizedAngle, min.ToFloat(), max.ToFloat());
return r;
}
// template <typename T>
// Angle2<T> Angle2<T>::Difference(Angle2<T> a, Angle2<T> b) {
// Angle2<T> r = Normalize(b - a);
// return r;
// }
template <>
AngleOf<float> AngleOf<float>::MoveTowards(AngleOf<float> fromAngle,
AngleOf<float> toAngle,
AngleOf<float> maxAngle) {
float d = toAngle.ToFloat() - fromAngle.ToFloat();
int sign = signbit(d) ? -1 : 1;
d = sign * Float::Clamp(fabsf(d), 0, maxAngle.ToFloat());
return fromAngle.ToFloat() + d;
}
template <>
AngleOf<float> AngleOf<float>::CosineRuleSide(float a,
float b,
AngleOf<float> gamma) {
float a2 = a * a;
float b2 = b * b;
float d = a2 + b2 -
2 * a * b * cosf(gamma.ToFloat() * Passer::LinearAlgebra::Deg2Rad);
// Catch edge cases where float inacuracies lead tot nans
if (d < 0)
return 0.0f;
float c = sqrtf(d);
return c;
}
template <>
AngleOf<float> AngleOf<float>::CosineRuleAngle(float a, float b, float c) {
float a2 = a * a;
float b2 = b * b;
float c2 = c * c;
float d = (a2 + b2 - c2) / (2 * a * b);
// Catch edge cases where float inacuracies lead tot nans
if (d >= 1)
return 0.0f;
if (d <= -1)
return 180.0f;
float gamma = acosf(d) * Rad2Deg;
return gamma;
}
template <>
AngleOf<float> AngleOf<float>::SineRuleAngle(float a,
AngleOf<float> beta,
float b) {
float deg2rad = Deg2Rad;
float alpha = asinf(a * sinf(beta.ToFloat() * deg2rad) / b);
return alpha;
}
template class AngleOf<float>;
template class AngleOf<signed short>;

70
LinearAlgebra/Angle.h Normal file
View File

@ -0,0 +1,70 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef ANGLE_H
#define ANGLE_H
namespace Passer {
namespace LinearAlgebra {
static float pi = 3.1415927410125732421875F;
static float Rad2Deg = 360.0f / (pi * 2);
static float Deg2Rad = (pi * 2) / 360.0f;
template <typename T>
class AngleOf {
public:
AngleOf() {};
AngleOf(int f);
AngleOf(float f);
// operator float() const;
float ToFloat() const;
inline T GetBinary() const { return this->value; }
static AngleOf<T> pi;
bool operator==(AngleOf<T> a);
AngleOf<T> operator-() const;
AngleOf<T> operator-(const AngleOf<T>& a) const;
AngleOf<T> operator+(const AngleOf<T>& a) const;
AngleOf<T> operator+=(const AngleOf<T>& a);
friend AngleOf<T> operator*(const AngleOf<T>& a, float f) {
return AngleOf((float)a.ToFloat() * f);
}
friend AngleOf<T> operator*(float f, const AngleOf<T>& a) {
return AngleOf((float)f * a.ToFloat());
}
static AngleOf<T> Normalize(AngleOf<T> a);
static AngleOf<T> Clamp(AngleOf<T> a, AngleOf<T> min, AngleOf<T> max);
static AngleOf<T> Difference(AngleOf<T> a, AngleOf<T> b) {
AngleOf<T> r = Normalize(b.ToFloat() - a.ToFloat());
return r;
};
static AngleOf<T> MoveTowards(AngleOf<T> fromAngle,
AngleOf<T> toAngle,
AngleOf<T> maxAngle);
static AngleOf<T> CosineRuleSide(float a, float b, AngleOf<T> gamma);
static AngleOf<T> CosineRuleAngle(float a, float b, float c);
static AngleOf<T> SineRuleAngle(float a, AngleOf<T> beta, float c);
private:
T value;
};
using Angle = AngleOf<float>;
// using Angle = AngleOf<signed short>;
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

96
LinearAlgebra/Angle16.cpp Normal file
View File

@ -0,0 +1,96 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include <math.h>
#include <stdlib.h>
#include "Angle.h"
template <>
AngleOf<signed short>::AngleOf(int angle) {
signed long long_angle = (signed short)angle * 65536;
this->value = (signed short)(long_angle / 360);
}
template <>
AngleOf<signed short>::AngleOf(float angle) {
if (!isfinite(angle)) {
value = 0;
return;
}
// map float [-180..180) to integer [-32768..32767]
this->value = (signed short)(angle / 360.0F * 65536.0F);
}
// template <>
// AngleOf<signed short>::operator float() const {
// float f = ((this->value * 180) / 32768.0F);
// return f;
// }
template <>
float AngleOf<signed short>::ToFloat() const {
float f = ((this->value * 180) / 32768.0F);
return f;
}
template <>
AngleOf<signed short> AngleOf<signed short>::operator-() const {
AngleOf<signed short> angle = AngleOf();
angle.value = -this->value;
return angle;
}
template <>
AngleOf<signed short> AngleOf<signed short>::operator-(
const AngleOf<signed short>& a) const {
AngleOf<signed short> angle = AngleOf();
angle.value = this->value - a.value;
return angle;
}
template <>
AngleOf<signed short> AngleOf<signed short>::operator+(
const AngleOf<signed short>& a) const {
AngleOf<signed short> angle = AngleOf();
angle.value = this->value + a.value;
return angle;
}
// Not correct!!! just for syntactical compilation ATM
template <>
AngleOf<signed short> AngleOf<signed short>::CosineRuleSide(
float a,
float b,
AngleOf<signed short> gamma) {
float a2 = a * a;
float b2 = b * b;
float d = a2 + b2 -
2 * a * b * cosf(gamma.ToFloat() * Passer::LinearAlgebra::Deg2Rad);
// Catch edge cases where float inacuracies lead tot nans
if (d < 0)
return 0.0f;
float c = sqrtf(d);
return c;
}
// Not correct!!! just for syntactical compilation ATM
template <>
AngleOf<signed short> AngleOf<signed short>::CosineRuleAngle(float a,
float b,
float c) {
float a2 = a * a;
float b2 = b * b;
float c2 = c * c;
float d = (a2 + b2 - c2) / (2 * a * b);
// Catch edge cases where float inacuracies lead tot nans
if (d >= 1)
return 0.0f;
if (d <= -1)
return 180.0f;
float gamma = acosf(d) * Passer::LinearAlgebra::Rad2Deg;
return gamma;
}

40
LinearAlgebra/Angle16.h Normal file
View File

@ -0,0 +1,40 @@
// #include "AngleUsing.h"
#include <math.h>
#include <stdlib.h>
#include "Angle.h"
namespace Passer {
namespace LinearAlgebra {
typedef AngleOf<signed short> Angle16;
// template <>
// inline static Angle16 Angle16::Degrees(short angle) {
// long long_angle = angle * 65535;
// long_angle = div(long_angle, (long)360);
// return Angle16(long_angle); //(long_angle / 360);
// }
// template <>
// inline static Angle16 Angle16::Degrees(float angle) {
// return (angle / 360.0F * 65536.0F);
// }
// template <> Angle16::AngleOf(float angle) {
// if (!isfinite(angle)) {
// value = 0;
// return;
// }
// // map float [-180..180) to integer [-32768..32767]
// this->value = (signed short)((angle / 360.0F) * 65536.0F);
// }
// template <> float Angle16::ToFloat() const {
// float f = ((this->value * 180) / 32768.0F);
// return f;
// }
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;

30
LinearAlgebra/Angle32.h Normal file
View File

@ -0,0 +1,30 @@
// #include "AngleUsing.h"
#include <math.h>
#include "Angle.h"
namespace Passer {
namespace LinearAlgebra {
typedef AngleOf<signed long> Angle32;
// template <>
// Angle32::AngleOf(float angle) {
// if (!isfinite(angle)) {
// value = 0;
// return;
// }
// // map float [-180..180) to integer [-2147483648..2147483647]
// this->value = (signed long)((angle / 360.0F) * 4294967295.0F);
// }
// template <>
// float Angle32::ToFloat() const {
// float f = ((this->value * 180) / 2147483648.0F);
// return f;
// }
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;

59
LinearAlgebra/Angle8.cpp Normal file
View File

@ -0,0 +1,59 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include <math.h>
#include "Angle.h"
template <>
AngleOf<signed char>::AngleOf(int angle) {
signed short short_angle = (signed char)angle * 256;
this->value = (signed char)(short_angle / 360);
}
template <>
AngleOf<signed char>::AngleOf(float angle) {
if (!isfinite(angle)) {
value = 0;
return;
}
// map float [-180..180) to integer [-128..127]
float f = angle / 360.0F;
this->value = (signed char)(f * 256.0F);
}
// template <>
// AngleOf<signed char>::operator float() const {
// float f = (this->value * 180) / 128.0F;
// return f;
// }
template <>
float AngleOf<signed char>::ToFloat() const {
float f = (this->value * 180) / 128.0F;
return f;
}
template <>
AngleOf<signed char> AngleOf<signed char>::operator-() const {
AngleOf<signed char> angle = AngleOf();
angle.value = -this->value;
return angle;
}
template <>
AngleOf<signed char> AngleOf<signed char>::operator-(
const AngleOf<signed char>& a) const {
AngleOf<signed char> angle = AngleOf();
angle.value = this->value - a.value;
return angle;
}
template <>
AngleOf<signed char> AngleOf<signed char>::operator+(
const AngleOf<signed char>& a) const {
AngleOf<signed char> angle = AngleOf();
angle.value = this->value + a.value;
return angle;
}

34
LinearAlgebra/Angle8.h Normal file
View File

@ -0,0 +1,34 @@
// #include "AngleUsing.h"
#include <math.h>
#include "Angle.h"
namespace Passer {
namespace LinearAlgebra {
typedef AngleOf<signed char> Angle8;
// template <>
// inline static Angle8 Angle8::Degrees(float angle) {
// return (angle / 360.0F * 256.0F);
// }
// template <> Angle8::AngleOf(float angle) {
// if (!isfinite(angle)) {
// value = 0;
// return;
// }
// // map float [-180..180) to integer [-128..127]
// float f = angle / 360.0F;
// this->value = (signed char)(f * 256.0F);
// }
// template <> float Angle8::ToFloat() const {
// float f = (this->value * 180) / 128.0F;
// return f;
// }
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;

View File

@ -0,0 +1,48 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "AngleAxis.h"
template <typename T>
AngleAxis<T>::AngleAxis() {
this->angle = AngleOf<T>();
this->axis = Direction<T>();
}
template <typename T>
AngleAxis<T>::AngleAxis(AngleOf<T> angle, Direction<T> axis) {
this->angle = angle;
this->axis = axis;
}
template <typename T>
AngleAxis<T>::AngleAxis(float angle, Vector3 axis) {
this->angle = AngleOf<T>(angle);
this->axis = Direction<T>(axis);
}
template <typename T>
AngleAxis<T>::AngleAxis(Quaternion q) {
float angle;
Vector3 axis;
q.ToAngleAxis(&angle, &axis);
this->angle = AngleOf<T>(angle);
this->axis = Direction<T>(axis);
}
template <typename T>
Quaternion AngleAxis<T>::ToQuaternion() {
Vector3 axisVector = this->axis.ToVector3();
float angleFloat = this->angle.ToFloat();
Quaternion q = Quaternion::AngleAxis(angleFloat, axisVector);
return q;
}
template <typename T>
Direction<T> AngleAxis<T>::GetSwing() {
return this->axis;
}
template class AngleAxis<float>;
template class AngleAxis<signed short>;

35
LinearAlgebra/AngleAxis.h Normal file
View File

@ -0,0 +1,35 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef ANGLEAXIS_H
#define ANGLEAXIS_H
#include "Angle.h"
#include "Direction.h"
#include "Quaternion.h"
namespace Passer {
namespace LinearAlgebra {
template <typename T>
class AngleAxis {
public:
AngleOf<T> angle;
Direction<T> axis;
AngleAxis();
AngleAxis(AngleOf<T> angle, Direction<T> axis);
AngleAxis(Quaternion q);
AngleAxis(float angle, Vector3 axis);
Quaternion ToQuaternion();
Direction<T> GetSwing();
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

View File

@ -0,0 +1,52 @@
/*
#ifndef DISCRETEANGLE_H
#define DISCRETEANGLE_H
#include "Angle.h"
#include "Range.h"
namespace Passer {
namespace LinearAlgebra {
// A fixed angle between (-180..180]
template <typename T>
class AngleUsing {
public:
AngleUsing(T sourceValue) { this->value = sourceValue; }
AngleUsing(float f);
float ToFloat() const;
inline T GetValue() const { return this->value; }
AngleUsing<T> operator+(const AngleUsing<T> a) {
AngleUsing<T> r = AngleUsing((float)this->value + a.value);
return r;
}
inline AngleUsing<T> operator+=(const AngleUsing<T> a) {
return this->value + a.value;
}
inline AngleUsing<T> operator-(const AngleUsing<T> a) {
return this->value - a.value;
}
inline AngleUsing<T> operator-() {
this->value = -this->value;
return *this;
}
inline bool operator==(const AngleUsing<T> a) {
return this->value == a.value;
}
// protected:
T value;
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif
*/

40
LinearAlgebra/Axis.cpp Normal file
View File

@ -0,0 +1,40 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Axis.h"
#include "Quaternion.h"
#include "Vector3.h"
#include <math.h>
Axis::Axis() {
horizontalAngle = 0.0f;
verticalAngle = 0.0f;
}
Axis::Axis(Angle horizontal, Angle vertical) {
this->horizontalAngle = horizontal;
this->verticalAngle = vertical;
};
Axis::Axis(Vector3 v) {
this->horizontalAngle =
atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg;
this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg;
}
const Axis Axis::forward = Axis(0.0f, 0.0f);
const Axis Axis::back = Axis(180.0f, 0.0f);
const Axis Axis::up = Axis(0.0f, 90.0f);
const Axis Axis::down = Axis(0.0f, -90.0f);
const Axis Axis::left = Axis(-90.0f, 0.0f);
const Axis Axis::right = Axis(90.0f, 0.0f);
Vector3 Axis::ToVector3() {
Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()),
this->horizontalAngle.ToFloat(), 0) *
Vector3::forward;
return v;
}

38
LinearAlgebra/Axis.h Normal file
View File

@ -0,0 +1,38 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef AXIS_H
#define AXIS_H
#include "Angle.h"
namespace Passer {
namespace LinearAlgebra {
struct Vector3;
class Axis {
public:
Angle horizontalAngle;
Angle verticalAngle;
Axis();
Axis(Angle horizontal, Angle vertical);
Axis(Vector3 v);
const static Axis forward;
const static Axis back;
const static Axis up;
const static Axis down;
const static Axis left;
const static Axis right;
Vector3 ToVector3();
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

View File

@ -0,0 +1,74 @@
cmake_minimum_required(VERSION 3.13) # CMake version check
if(ESP_PLATFORM)
idf_component_register(
SRC_DIRS "."
INCLUDE_DIRS "."
)
else()
project(LinearAlgebra)
set(CMAKE_CXX_STANDARD 11) # Enable c++11 standard
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_definitions(GTEST)
include(FetchContent)
FetchContent_Declare(
googletest
DOWNLOAD_EXTRACT_TIMESTAMP
URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
include_directories(.)
add_library(LinearAlgebra STATIC
"FloatSingle.cpp"
"Angle.cpp"
"Angle8.cpp"
"Angle16.cpp"
"Vector2.cpp"
"Vector3.cpp"
"Quaternion.cpp"
"Polar.cpp"
"Spherical.cpp"
"Spherical16.cpp"
"Matrix.cpp"
"Axis.cpp"
"AngleAxis.cpp"
"Direction.cpp"
)
enable_testing()
add_executable(
LinearAlgebraTest
"test/Angle_test.cc"
"test/FloatSingle_test.cc"
"test/Vector2_test.cc"
"test/Vector3_test.cc"
"test/Quaternion_test.cc"
"test/Matrix_test.cc"
"test/Polar_test.cc"
"test/Spherical_test.cc"
"test/Spherical16_test.cc"
"test/DiscreteAngle_test.cc"
)
target_link_libraries(
LinearAlgebraTest
gtest_main
LinearAlgebra
)
if(MSVC)
target_compile_options(LinearAlgebraTest PRIVATE /W4 /WX)
else()
target_compile_options(LinearAlgebraTest PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()
include(GoogleTest)
gtest_discover_tests(LinearAlgebraTest)
endif()

View File

@ -0,0 +1,54 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Direction.h"
#include "Quaternion.h"
#include "Vector3.h"
#include <math.h>
template <typename T>
Direction<T>::Direction() {
this->horizontalAngle = AngleOf<T>(0.0f);
this->verticalAngle = AngleOf<T>(0.0f);
}
template <typename T>
Direction<T>::Direction(AngleOf<T> horizontal, AngleOf<T> vertical) {
this->horizontalAngle = horizontal;
this->verticalAngle = vertical;
};
template <typename T>
Direction<T>::Direction(Vector3 v) {
this->horizontalAngle =
atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg;
this->verticalAngle = 90 - acosf(v.Up()) * Passer::LinearAlgebra::Rad2Deg;
}
template <typename T>
const Direction<T> Direction<T>::forward = Direction<T>(0.0f, 0.0f);
template <typename T>
const Direction<T> Direction<T>::back = Direction<T>(180.0f, 0.0f);
template <typename T>
const Direction<T> Direction<T>::up = Direction<T>(0.0f, 90.0f);
template <typename T>
const Direction<T> Direction<T>::down = Direction<T>(0.0f, -90.0f);
template <typename T>
const Direction<T> Direction<T>::left = Direction<T>(-90.0f, 0.0f);
template <typename T>
const Direction<T> Direction<T>::right = Direction<T>(90.0f, 0.0f);
template <typename T>
Vector3 Direction<T>::ToVector3() {
Vector3 v = Quaternion::Euler(-(this->verticalAngle.ToFloat()),
this->horizontalAngle.ToFloat(), 0) *
Vector3::forward;
return v;
}
template class Direction<float>;
template class Direction<signed short>;
template class Direction<signed char>;

39
LinearAlgebra/Direction.h Normal file
View File

@ -0,0 +1,39 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef DIRECTION_H
#define DIRECTION_H
#include "Angle.h"
namespace Passer {
namespace LinearAlgebra {
struct Vector3;
template <typename T>
class Direction {
public:
AngleOf<T> horizontalAngle;
AngleOf<T> verticalAngle;
Direction();
Direction(AngleOf<T> horizontal, AngleOf<T> vertical);
Direction(Vector3 v);
const static Direction forward;
const static Direction back;
const static Direction up;
const static Direction down;
const static Direction left;
const static Direction right;
Vector3 ToVector3();
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

View File

@ -0,0 +1,420 @@
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_for_dummies.md:566: warning: multiple use of section label 'OrderedCalls' while adding section, (first occurrence: D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md, line 1674)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:411: warning: multiple use of section label 'DefaultValue' while adding section, (first occurrence: D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md, line 2088)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-message.h:62: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:158: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-output-test_.cc:47: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest-typed-test_test.cc:43: warning: Found ';' while parsing initializer list! (doxygen could be confused by a macro call without semicolon)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-matchers.h:256: warning: found documented #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ but ignoring it because ENABLE_PREPROCESSING is NO.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class testing::internal::FindFirstPrinter< T, E, Printers... >!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class FindFirstPrinter< T, E, Printers... >!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class testing::internal::FindFirstPrinter< T, E, Printers... >!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h:288: warning: Detected potential recursive class relation between class testing::internal::FindFirstPrinter and base class FindFirstPrinter< T, E, Printers... >!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-cardinalities.cc:129: warning: documented symbol 'void testing::Cardinality::DescribeActualCallCountTo' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:248: warning: documented symbol 'bool testing::internal::MatchMatrix::NextGraph' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:262: warning: documented symbol 'void testing::internal::MatchMatrix::Randomize' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:271: warning: no uniquely matching class member found for
std::string testing::internal::MatchMatrix::DebugString() const
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:284: warning: documented symbol 'void testing::internal::UnorderedElementsAreMatcherImplBase::DescribeToImpl' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:325: warning: documented symbol 'void testing::internal::UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:371: warning: documented symbol 'bool testing::internal::UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-matchers.cc:421: warning: documented symbol 'bool testing::internal::UnorderedElementsAreMatcherImplBase::FindPairing' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:82: warning: documented symbol 'testing::internal::ExpectationBase::ExpectationBase' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:98: warning: documented symbol 'testing::internal::ExpectationBase::~ExpectationBase' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:102: warning: documented symbol 'void testing::internal::ExpectationBase::SpecifyCardinality' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:108: warning: documented symbol 'void testing::internal::ExpectationBase::RetireAllPreRequisites' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:135: warning: documented symbol 'bool testing::internal::ExpectationBase::AllPrerequisitesAreSatisfied' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:155: warning: documented symbol 'void testing::internal::ExpectationBase::FindUnsatisfiedPrerequisites' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:186: warning: documented symbol 'void testing::internal::ExpectationBase::DescribeCallCountTo' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:209: warning: documented symbol 'void testing::internal::ExpectationBase::CheckActionCountIfNotDone' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:261: warning: documented symbol 'void testing::internal::ExpectationBase::UntypedTimes' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:308: warning: documented symbol 'testing::internal::UntypedFunctionMockerBase::UntypedFunctionMockerBase' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:311: warning: documented symbol 'testing::internal::UntypedFunctionMockerBase::~UntypedFunctionMockerBase' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:317: warning: documented symbol 'void testing::internal::UntypedFunctionMockerBase::RegisterOwner' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:329: warning: documented symbol 'void testing::internal::UntypedFunctionMockerBase::SetOwnerAndName' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:341: warning: documented symbol 'const void * testing::internal::UntypedFunctionMockerBase::MockObject' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:358: warning: documented symbol 'const char * testing::internal::UntypedFunctionMockerBase::Name' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:376: warning: documented symbol 'UntypedActionResultHolderBase * testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:505: warning: documented symbol 'Expectation testing::internal::UntypedFunctionMockerBase::GetHandleOf' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:525: warning: documented symbol 'bool testing::internal::UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:685: warning: documented symbol 'void Mock::AllowUninterestingCalls' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:692: warning: documented symbol 'void Mock::WarnUninterestingCalls' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:699: warning: documented symbol 'void Mock::FailUninterestingCalls' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:706: warning: documented symbol 'void Mock::UnregisterCallReaction' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:714: warning: documented symbol 'internal::CallReaction Mock::GetReactionOnUninterestingCalls' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:726: warning: documented symbol 'void Mock::AllowLeak' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:735: warning: documented symbol 'bool Mock::VerifyAndClearExpectations' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:744: warning: documented symbol 'bool Mock::VerifyAndClear' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:754: warning: documented symbol 'bool Mock::VerifyAndClearExpectationsLocked' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:779: warning: documented symbol 'bool Mock::IsNaggy' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:783: warning: documented symbol 'bool Mock::IsNice' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:787: warning: documented symbol 'bool Mock::IsStrict' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:793: warning: no uniquely matching class member found for
void Mock::Register(const void *mock_obj, internal::UntypedFunctionMockerBase *mocker)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:803: warning: documented symbol 'void Mock::RegisterUseByOnCallOrExpectCall' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:824: warning: documented symbol 'void Mock::UnregisterLocked' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:842: warning: documented symbol 'void Mock::ClearDefaultActionsLocked' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:864: warning: documented symbol 'testing::Expectation::Expectation' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:866: warning: documented symbol 'testing::Expectation::Expectation' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:870: warning: documented symbol 'testing::Expectation::~Expectation' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:873: warning: documented symbol 'void testing::Sequence::AddExpectation' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:884: warning: documented symbol 'testing::InSequence::InSequence' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc:895: warning: documented symbol 'testing::InSequence::~InSequence' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:111: warning: no matching file member found for
std::string testing::PrintToString(const T &value)
Possible candidates:
'::std::string PrintToString(const T &value)' at line 1037 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-printers.h
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:160: warning: no matching file member found for
testing::internal::GTEST_DISABLE_MSC_WARNINGS_PUSH_
Possible candidates:
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 48 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-cardinalities.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 GMOCK_MAYBE_5046_) namespace testing' at line 283 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-matchers.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 84 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googlemock/include/gmock/gmock-spec-builders.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 GTEST_MAYBE_5046_) namespace testing' at line 59 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-matchers.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 38 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-spi.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 42 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest-test-part.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) GTEST_DECLARE_bool_(also_run_disabled_tests)' at line 72 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/gtest.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) class GTEST_API_ DeathTest' at line 60 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-death-test-internal.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) namespace testing' at line 47 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/include/gtest/internal/gtest-filepath.h
'GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \) GTEST_DECLARE_bool_(death_test_use_fork)' at line 64 of file D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-internal-inl.h
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-assertion-result.cc:59: warning: documented symbol 'AssertionResult testing::AssertionResult::operator!' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:373: warning: documented symbol 'testing::internal::DeathTest::DeathTest' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:383: warning: no matching class member found for
bool testing::internal::DeathTest::Create(const char *statement, Matcher< const std::string & > matcher, const char *file, int line, DeathTest **test)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:390: warning: documented symbol 'const char * testing::internal::DeathTest::LastMessage' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:394: warning: documented symbol 'void testing::internal::DeathTest::set_last_death_test_message' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-death-test.cc:398: warning: documented symbol 'std::string testing::internal::DeathTest::last_death_test_message_' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:94: warning: documented symbol 'FilePath testing::internal::FilePath::GetCurrentDir' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:121: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveExtension' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:133: warning: documented symbol 'const char * testing::internal::FilePath::FindLastPathSeparator' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:152: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveDirectoryName' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:163: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveFileName' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:180: warning: documented symbol 'FilePath testing::internal::FilePath::MakeFileName' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:196: warning: documented symbol 'FilePath testing::internal::FilePath::ConcatPaths' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:206: warning: documented symbol 'bool testing::internal::FilePath::FileOrDirectoryExists' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:220: warning: documented symbol 'bool testing::internal::FilePath::DirectoryExists' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:250: warning: documented symbol 'bool testing::internal::FilePath::IsRootDirectory' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:259: warning: documented symbol 'bool testing::internal::FilePath::IsAbsolutePath' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:280: warning: documented symbol 'FilePath testing::internal::FilePath::GenerateUniqueFileName' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:294: warning: documented symbol 'bool testing::internal::FilePath::IsDirectory' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:302: warning: documented symbol 'bool testing::internal::FilePath::CreateDirectoriesRecursively' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:319: warning: documented symbol 'bool testing::internal::FilePath::CreateFolder' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:343: warning: documented symbol 'FilePath testing::internal::FilePath::RemoveTrailingPathSeparator' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-filepath.cc:352: warning: no uniquely matching class member found for
void testing::internal::FilePath::Normalize()
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:45: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:49: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:55: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:59: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:64: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:70: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:76: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:82: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:86: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-matchers.cc:92: warning: documented symbol 'testing::Matcher< typename >::Matcher' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-port.cc:301: warning: no matching class member found for
void testing::internal::AutoHandle::Reset(HANDLE handle)
Possible candidates:
'void testing::internal::AutoHandle::Reset()'
'void testing::internal::AutoHandle::Reset(Handle handle)'
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:44: warning: documented symbol 'std::string testing::TestPartResult::ExtractSummary' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:66: warning: no uniquely matching class member found for
void testing::TestPartResultArray::Append(const TestPartResult &result)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:71: warning: no matching class member found for
const TestPartResult & testing::TestPartResultArray::GetTestPartResult(int index) const
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:81: warning: no uniquely matching class member found for
int testing::TestPartResultArray::size() const
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:87: warning: documented symbol 'testing::internal::HasNewFatalFailureHelper::HasNewFatalFailureHelper' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:94: warning: documented symbol 'testing::internal::HasNewFatalFailureHelper::~HasNewFatalFailureHelper' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-test-part.cc:99: warning: no uniquely matching class member found for
void testing::internal::HasNewFatalFailureHelper::ReportTestPartResult(const TestPartResult &result)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest-typed-test.cc:58: warning: documented symbol 'const char * testing::internal::TypedTestSuitePState::VerifyRegisteredTestNames' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:858: warning: documented symbol 'testing::ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:868: warning: documented symbol 'testing::ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:875: warning: no uniquely matching class member found for
void testing::ScopedFakeTestPartResultReporter::Init()
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:888: warning: documented symbol 'testing::ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:899: warning: no uniquely matching class member found for
void testing::ScopedFakeTestPartResultReporter::ReportTestPartResult(const TestPartResult &result)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:965: warning: documented symbol 'testing::internal::SingleFailureChecker::SingleFailureChecker' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:974: warning: documented symbol 'testing::internal::SingleFailureChecker::~SingleFailureChecker' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/src/gtest.cc:2602: warning: documented symbol 'testing::internal::GoogleTestFailureException::GoogleTestFailureException' was not declared or defined.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:52: warning: explicit link request to 'testing::AssertionResult' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:229: warning: explicit link request to 'Bar()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:283: warning: explicit link request to 'testing::Environment' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:283: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:376: warning: explicit link request to 'testing::PrintToString(x)' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:786: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:813: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:850: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:953: warning: explicit link request to 'testing::Environment' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:970: warning: explicit link request to 'testing::AddGlobalTestEnvironment()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1243: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1364: warning: explicit link request to 'testing::Types' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1397: warning: explicit link request to 'including' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1496: warning: explicit link request to 'including' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1538: warning: explicit link request to 'testing::RegisterTest' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1764: warning: explicit link request to 'testing::InitGoogleTest()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1813: warning: found </em> at different nesting level (5) than expected (2)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1822: warning: found </tt> tag while expecting </em>
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1823: warning: found </tt> tag while expecting </em>
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1824: warning: found </tt> tag while expecting </em>
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1986: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1986: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1987: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1987: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1988: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1988: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1989: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1989: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1990: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1990: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1991: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1991: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1992: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1992: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1994: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1994: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1996: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1996: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1997: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1997: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1998: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1998: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1999: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:1999: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:2000: warning: Unsupported xml/html tag <font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:2000: warning: Unsupported xml/html tag </font> found
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/advanced.md:2380: warning: end of comment block while expecting command </em>
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/faq.md:658: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cheat_sheet.md:6: warning: found subsection command (id: 'MockClass') outside of section context!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:9: warning: explicit link request to 'testing::Foo' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:186: warning: found subsection command (id: 'MockingNonVirtualMethods') outside of section context!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:1540: warning: explicit link request to 'Set()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:1950: warning: explicit link request to 'testing::ActionInterface' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2045: warning: explicit link request to 'testing::InSequence' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2098: warning: explicit link request to 'testing::DefaultValue' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2223: warning: explicit link request to 'testing::Invoke' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:2309: warning: explicit link request to 'testing::InvokeWithoutArgs' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_cook_book.md:4107: warning: explicit link request to 'testing::ActionInterface' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/gmock_for_dummies.md:524: warning: found subsection command (id: 'MultiExpectations') outside of section context!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/primer.md:213: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/primer.md:457: warning: explicit link request to 'testing::InitGoogleTest()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/actions.md:5: warning: explicit link request to 'testing' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/assertions.md:529: warning: explicit link request to 'testing::GTEST_FLAG(death_test_style)' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/matchers.md:20: warning: explicit link request to 'testing' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/matchers.md:145: warning: explicit link request to 'std::tuple' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:92: warning: explicit link request to 'EXPECT_CALL.With' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:122: warning: explicit link request to 'EXPECT_CALL.Times' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:129: warning: explicit link request to 'testing' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:151: warning: explicit link request to 'EXPECT_CALL.InSequence' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:181: warning: explicit link request to 'EXPECT_CALL.After' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:222: warning: explicit link request to 'EXPECT_CALL.WillOnce' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:253: warning: explicit link request to 'EXPECT_CALL.WillRepeatedly' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:286: warning: explicit link request to 'EXPECT_CALL.RetiresOnSaturation' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:347: warning: explicit link request to 'ON_CALL.With' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:378: warning: explicit link request to 'ON_CALL.WillByDefault' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:413: warning: explicit link request to 'testing::DefaultValue' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:437: warning: explicit link request to 'testing::NiceMock' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:468: warning: explicit link request to 'testing::NaggyMock' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:495: warning: explicit link request to 'testing::StrictMock' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:527: warning: explicit link request to 'testing::Sequence' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:534: warning: explicit link request to 'testing::InSequence' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:559: warning: explicit link request to 'testing::Expectation' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/mocking.md:574: warning: explicit link request to 'testing::ExpectationSet' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:13: warning: found subsection command (id: 'TEST') outside of section context!
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:100: warning: explicit link request to 'testing' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:389: warning: explicit link request to 'testing::AssertionResult' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:403: warning: explicit link request to 'testing::AssertionException' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:410: warning: explicit link request to 'testing::EmptyTestEventListener' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:418: warning: explicit link request to 'testing::Environment' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:425: warning: explicit link request to 'Environment::SetUp' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:431: warning: explicit link request to 'Environment::TearDown' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:439: warning: explicit link request to 'testing::ScopedTrace' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:466: warning: explicit link request to 'testing::Test' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:472: warning: explicit link request to 'Test::SetUpTestSuite' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:479: warning: explicit link request to 'Test::TearDownTestSuite' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:486: warning: explicit link request to 'Test::HasFatalFailure' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:492: warning: explicit link request to 'Test::HasNonfatalFailure' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:498: warning: explicit link request to 'Test::HasFailure' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:505: warning: explicit link request to 'Test::IsSkipped' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:511: warning: explicit link request to 'Test::RecordProperty' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:538: warning: explicit link request to 'Test::SetUp' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:545: warning: explicit link request to 'Test::TearDown' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:554: warning: explicit link request to 'testing::TestWithParam' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:565: warning: explicit link request to 'TestSuite::name' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:571: warning: explicit link request to 'TestSuite::type_param' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:579: warning: explicit link request to 'TestSuite::should_run' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:585: warning: explicit link request to 'TestSuite::successful_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:591: warning: explicit link request to 'TestSuite::skipped_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:597: warning: explicit link request to 'TestSuite::failed_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:603: warning: explicit link request to 'TestSuite::reportable_disabled_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:609: warning: explicit link request to 'TestSuite::disabled_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:615: warning: explicit link request to 'TestSuite::reportable_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:621: warning: explicit link request to 'TestSuite::test_to_run_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:627: warning: explicit link request to 'TestSuite::total_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:633: warning: explicit link request to 'TestSuite::Passed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:639: warning: explicit link request to 'TestSuite::Failed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:645: warning: explicit link request to 'TestSuite::elapsed_time' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:651: warning: explicit link request to 'TestSuite::start_timestamp' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:657: warning: explicit link request to 'TestSuite::GetTestInfo' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:665: warning: explicit link request to 'TestSuite::ad_hoc_test_result' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:674: warning: explicit link request to 'testing::TestInfo' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:680: warning: explicit link request to 'TestInfo::test_suite_name' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:686: warning: explicit link request to 'TestInfo::name' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:692: warning: explicit link request to 'TestInfo::type_param' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:700: warning: explicit link request to 'TestInfo::value_param' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:708: warning: explicit link request to 'TestInfo::file' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:714: warning: explicit link request to 'TestInfo::line' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:720: warning: explicit link request to 'TestInfo::is_in_another_shard' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:726: warning: explicit link request to 'TestInfo::should_run' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:739: warning: explicit link request to 'TestInfo::is_reportable' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:745: warning: explicit link request to 'TestInfo::result' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:753: warning: explicit link request to 'testing::TestParamInfo' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:763: warning: explicit link request to 'testing::UnitTest' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:774: warning: explicit link request to 'UnitTest::GetInstance' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:782: warning: explicit link request to 'UnitTest::original_working_dir' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:789: warning: explicit link request to 'UnitTest::current_test_suite' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:796: warning: explicit link request to 'UnitTest::current_test_info' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:803: warning: explicit link request to 'UnitTest::random_seed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:809: warning: explicit link request to 'UnitTest::successful_test_suite_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:815: warning: explicit link request to 'UnitTest::failed_test_suite_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:821: warning: explicit link request to 'UnitTest::total_test_suite_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:827: warning: explicit link request to 'UnitTest::test_suite_to_run_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:834: warning: explicit link request to 'UnitTest::successful_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:840: warning: explicit link request to 'UnitTest::skipped_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:846: warning: explicit link request to 'UnitTest::failed_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:852: warning: explicit link request to 'UnitTest::reportable_disabled_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:858: warning: explicit link request to 'UnitTest::disabled_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:864: warning: explicit link request to 'UnitTest::reportable_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:870: warning: explicit link request to 'UnitTest::total_test_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:876: warning: explicit link request to 'UnitTest::test_to_run_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:882: warning: explicit link request to 'UnitTest::start_timestamp' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:888: warning: explicit link request to 'UnitTest::elapsed_time' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:894: warning: explicit link request to 'UnitTest::Passed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:900: warning: explicit link request to 'UnitTest::Failed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:907: warning: explicit link request to 'UnitTest::GetTestSuite' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:915: warning: explicit link request to 'UnitTest::ad_hoc_test_result' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:922: warning: explicit link request to 'UnitTest::listeners' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:931: warning: explicit link request to 'testing::TestEventListener' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:938: warning: explicit link request to 'TestEventListener::OnTestProgramStart' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:944: warning: explicit link request to 'TestEventListener::OnTestIterationStart' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:953: warning: explicit link request to 'TestEventListener::OnEnvironmentsSetUpStart' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:960: warning: explicit link request to 'TestEventListener::OnEnvironmentsSetUpEnd' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:967: warning: explicit link request to 'TestEventListener::OnTestSuiteStart' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:973: warning: explicit link request to 'TestEventListener::OnTestStart' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:979: warning: explicit link request to 'TestEventListener::OnTestPartResult' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:988: warning: explicit link request to 'TestEventListener::OnTestEnd' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:994: warning: explicit link request to 'TestEventListener::OnTestSuiteEnd' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1000: warning: explicit link request to 'TestEventListener::OnEnvironmentsTearDownStart' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1007: warning: explicit link request to 'TestEventListener::OnEnvironmentsTearDownEnd' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1014: warning: explicit link request to 'TestEventListener::OnTestIterationEnd' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1021: warning: explicit link request to 'TestEventListener::OnTestProgramEnd' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1029: warning: explicit link request to 'testing::TestEventListeners' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1035: warning: explicit link request to 'TestEventListeners::Append' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1043: warning: explicit link request to 'TestEventListeners::Release' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1051: warning: explicit link request to 'TestEventListeners::default_result_printer' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1061: warning: explicit link request to 'TestEventListeners::default_xml_generator' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1074: warning: explicit link request to 'testing::TestPartResult' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1081: warning: explicit link request to 'TestPartResult::type' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1098: warning: explicit link request to 'TestPartResult::file_name' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1105: warning: explicit link request to 'TestPartResult::line_number' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1112: warning: explicit link request to 'TestPartResult::summary' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1118: warning: explicit link request to 'TestPartResult::message' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1124: warning: explicit link request to 'TestPartResult::skipped' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1130: warning: explicit link request to 'TestPartResult::passed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1136: warning: explicit link request to 'TestPartResult::nonfatally_failed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1142: warning: explicit link request to 'TestPartResult::fatally_failed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1148: warning: explicit link request to 'TestPartResult::failed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1156: warning: explicit link request to 'testing::TestProperty' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1183: warning: explicit link request to 'testing::TestResult' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1191: warning: explicit link request to 'TestResult::total_part_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1198: warning: explicit link request to 'TestResult::test_property_count' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1204: warning: explicit link request to 'TestResult::Passed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1210: warning: explicit link request to 'TestResult::Skipped' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1216: warning: explicit link request to 'TestResult::Failed' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1222: warning: explicit link request to 'TestResult::HasFatalFailure' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1228: warning: explicit link request to 'TestResult::HasNonfatalFailure' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1234: warning: explicit link request to 'TestResult::elapsed_time' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1240: warning: explicit link request to 'TestResult::start_timestamp' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1246: warning: explicit link request to 'TestResult::GetTestPartResult' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1254: warning: explicit link request to 'TestResult::GetTestProperty' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1264: warning: explicit link request to 'testing::TimeInMillis' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1270: warning: explicit link request to 'testing::Types' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1286: warning: explicit link request to 'testing::WithParamInterface' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1312: warning: explicit link request to 'testing::InitGoogleTest(int* argc, char** argv)' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1313: warning: explicit link request to 'testing::InitGoogleTest(int* argc, wchar_t** argv)' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1314: warning: explicit link request to 'testing::InitGoogleTest()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1331: warning: explicit link request to 'testing::AddGlobalTestEnvironment(Environment* env)' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1383: warning: explicit link request to 'testing::AssertionSuccess()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1390: warning: explicit link request to 'testing::AssertionFailure()' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1403: warning: explicit link request to 'testing::StaticAssertTypeEq' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1412: warning: explicit link request to 'testing::PrintToString(x)' could not be resolved
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/docs/reference/testing.md:1422: warning: explicit link request to 'testing::PrintToStringParamName' could not be resolved
D:/C/VectorAlgebra/include/Vector2.h:233: warning: Member ToFactor(Vector2 a, Vector2 b) (function) of struct Vector2 is not documented.
D:/C/VectorAlgebra/include/Vector2.h:205: warning: argument 'axis' of command @param is not found in the argument list of Vector2::SignedAngle(Vector2 from, Vector2 to)
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:119: warning: Member testCatchesCxxExceptionsInFixtureConstructor(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:133: warning: Member testCatchesCxxExceptionsInFixtureDestructor(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:143: warning: Member testCatchesCxxExceptionsInSetUpTestCase(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:166: warning: Member testCatchesCxxExceptionsInTearDownTestCase(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:171: warning: Member testCatchesCxxExceptionsInSetUp(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:189: warning: Member testCatchesCxxExceptionsInTearDown(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:200: warning: Member testCatchesCxxExceptionsInTestBody(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:214: warning: Member testCatchesNonStdCxxExceptions(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:219: warning: Member testUnhandledCxxExceptionsAbortTheProgram(self) (function) of class googletest-catch-exceptions-test::CatchCxxExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:85: warning: Member TestSehExceptions(self, test_output) (function) of class googletest-catch-exceptions-test::CatchSehExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:103: warning: Member testCatchesSehExceptionsWithCxxExceptionsEnabled(self) (function) of class googletest-catch-exceptions-test::CatchSehExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test.py:106: warning: Member testCatchesSehExceptionsWithCxxExceptionsDisabled(self) (function) of class googletest-catch-exceptions-test::CatchSehExceptionsTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:122: warning: Member testGoogletestFlag(self) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:187: warning: Member testEventListener(self) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:214: warning: Member assertXmlResultCount(self, result, count, xml) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-failfast-unittest.py:220: warning: Member assertXmlStatusCount(self, status, count, xml) (function) of class googletest-failfast-unittest::GTestFailFastUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-filter-unittest.py:517: warning: Member testNegativeFilters(self) (function) of class googletest-filter-unittest::GTestFilterUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:134: warning: Member setUp(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:142: warning: Member tearDown(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:145: warning: Member DeleteFilesAndDir(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:159: warning: Member testOutfile1(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:162: warning: Member testOutfile2(self) (function) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-json-outfiles-test.py:138: warning: Member output_dir_ (variable) of class googletest-json-outfiles-test::GTestJsonOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:170: warning: Member setUp(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:173: warning: Member testShufflePreservesNumberOfTests(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:179: warning: Member testShuffleChangesTestOrder(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:187: warning: Member testShuffleChangesTestCaseOrder(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:200: warning: Member testShuffleDoesNotRepeatTest(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:214: warning: Member testShuffleDoesNotCreateNewTest(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:224: warning: Member testShuffleIncludesAllTests(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:234: warning: Member testShuffleLeavesDeathTestsAtFront(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:253: warning: Member testShuffleDoesNotInterleaveTestCases(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:259: warning: Member testShuffleRestoresOrderAfterEachIteration(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:291: warning: Member testShuffleGeneratesNewOrderInEachIteration(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/googletest-shuffle-test.py:303: warning: Member testShuffleShardedTestsPreservesPartition(self) (function) of class googletest-shuffle-test::GTestShuffleUnitTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:140: warning: Member testPrintsHelpWithFullFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:143: warning: Member testPrintsHelpWithShortFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:146: warning: Member testPrintsHelpWithQuestionFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:149: warning: Member testPrintsHelpWithWindowsStyleQuestionFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:152: warning: Member testPrintsHelpWithUnrecognizedGoogleTestFlag(self) (function) of class gtest_help_test::GTestHelpTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_help_test.py:155: warning: Member testPrintsHelpWithIncorrectFlagStyle(self) (function) of class gtest_help_test::GTestHelpTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:75: warning: Member setUp(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:83: warning: Member tearDown(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:86: warning: Member DeleteFilesAndDir(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:100: warning: Member testOutfile1(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:103: warning: Member testOutfile2(self) (function) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_outfiles_test.py:79: warning: Member output_dir_ (variable) of class gtest_xml_outfiles_test::GTestXMLOutFilesTest is not documented.
D:/C/VectorAlgebra/out/build/x64-Debug/_deps/googletest-src/googletest/test/gtest_xml_test_utils.py:103: warning: Member identifying_attribute (variable) of class gtest_xml_test_utils::GTestXMLTestCase is not documented.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.18 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="modules" visible="yes" title="" intro=""/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="interfaces" visible="yes" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="structs" visible="yes" title="">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
<tab type="exceptions" visible="yes" title="">
<tab type="exceptionlist" visible="yes" title="" intro=""/>
<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="no"/>
<detaileddescription title=""/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

View File

@ -0,0 +1,12 @@
/* Custom PasserVR CSS for DoxyGen */
a {
color: #e77505;
}
.contents a:visited {
color: #e77505;
}
a:hover {
color: #10659C;
}

View File

@ -0,0 +1,17 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include <math.h>
#include "FloatSingle.h"
const float Float::epsilon = 1e-05f;
const float Float::sqrEpsilon = 1e-10f;
float Float::Clamp(float f, float min, float max) {
if (f < min)
return min;
if (f > max)
return max;
return f;
}

View File

@ -0,0 +1,23 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef FLOAT_H
#define FLOAT_H
namespace Passer {
namespace LinearAlgebra {
class Float {
public:
static const float epsilon;
static const float sqrEpsilon;
static float Clamp(float f, float min, float max);
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

373
LinearAlgebra/LICENSE Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

62
LinearAlgebra/Matrix.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "Matrix.h"
template <> MatrixOf<float>::MatrixOf(unsigned int rows, unsigned int cols) {
if (rows <= 0 || cols <= 0) {
this->rows = 0;
this->cols = 0;
this->data = nullptr;
return;
}
this->rows = rows;
this->cols = cols;
unsigned int matrixSize = this->cols * this->rows;
this->data = new float[matrixSize]{0.0f};
}
template <> MatrixOf<float>::MatrixOf(Vector3 v) : MatrixOf(3, 1) {
Set(0, 0, v.Right());
Set(1, 0, v.Up());
Set(2, 0, v.Forward());
}
template <>
void MatrixOf<float>::Multiply(const MatrixOf<float> *m1,
const MatrixOf<float> *m2, MatrixOf<float> *r) {
for (unsigned int rowIx1 = 0; rowIx1 < m1->rows; rowIx1++) {
for (unsigned int colIx2 = 0; colIx2 < m2->cols; colIx2++) {
unsigned int rDataIx = colIx2 * m2->cols + rowIx1;
r->data[rDataIx] = 0.0F;
for (unsigned int kIx = 0; kIx < m2->rows; kIx++) {
unsigned int dataIx1 = rowIx1 * m1->cols + kIx;
unsigned int dataIx2 = kIx * m2->cols + colIx2;
r->data[rDataIx] += m1->data[dataIx1] * m2->data[dataIx2];
}
}
}
}
template <>
Vector3 MatrixOf<float>::Multiply(const MatrixOf<float> *m, Vector3 v) {
MatrixOf<float> v_m = MatrixOf<float>(v);
MatrixOf<float> r_m = MatrixOf<float>(3, 1);
Multiply(m, &v_m, &r_m);
Vector3 r = Vector3(r_m.data[0], r_m.data[1], r_m.data[2]);
return r;
}
template <typename T> Vector3 MatrixOf<T>::operator*(const Vector3 v) const {
float *vData = new float[3]{v.x, v.y, v.z};
MatrixOf<float> v_m = MatrixOf<float>(3, 1, vData);
float *rData = new float[3]{};
MatrixOf<float> r_m = MatrixOf<float>(3, 1, rData);
Multiply(this, &v_m, &r_m);
Vector3 r = Vector3(r_m.data[0], r_m.data[1], r_m.data[2]);
delete[] vData;
delete[] rData;
return r;
}

121
LinearAlgebra/Matrix.h Normal file
View File

@ -0,0 +1,121 @@
#ifndef MATRIX_H
#define MATRIX_H
#include "Vector3.h"
namespace Passer {
namespace LinearAlgebra {
/// @brief Single precision float matrix
template <typename T> class MatrixOf {
public:
MatrixOf(unsigned int rows, unsigned int cols);
MatrixOf(unsigned int rows, unsigned int cols, const T *source)
: MatrixOf(rows, cols) {
Set(source);
}
MatrixOf(Vector3 v); // creates a 3,1 matrix
~MatrixOf() {
if (this->data == nullptr)
return;
delete[] this->data;
}
/// @brief Transpose with result in matrix m
/// @param r The matrix in which the transposed matrix is stored
void Transpose(MatrixOf<T> *r) const {
// Check dimensions first
// We dont care about the rows and cols (we overwrite them)
// but the data size should be equal to avoid problems
// We cannot check the data size directly, but the row*col should be equal
unsigned int matrixSize = this->cols * this->rows;
unsigned int resultSize = r->rows * r->cols;
if (matrixSize != resultSize) {
// Return a null matrix;
// We dont set data to nullptr because it is allocated memory
// Instead we write all zeros
for (unsigned int dataIx = 0; dataIx < resultSize; dataIx++)
r->data[dataIx] = 0.0f;
r->rows = 0;
r->cols = 0;
return;
}
r->cols = this->rows;
r->rows = this->cols;
for (unsigned int rDataIx = 0; rDataIx < matrixSize; rDataIx++) {
unsigned int rowIx = rDataIx / this->rows;
unsigned int colIx = rDataIx % this->rows;
unsigned int mDataIx = this->cols * colIx + rowIx;
r->data[rDataIx] = this->data[mDataIx];
}
}
static void Multiply(const MatrixOf<T> *m1, const MatrixOf<T> *m2,
MatrixOf<T> *r);
void Multiply(const MatrixOf<T> *m, MatrixOf<T> *r) const {
Multiply(this, m, r);
}
static Vector3 Multiply(const MatrixOf<T> *m, Vector3 v);
Vector3 operator*(const Vector3 v) const;
T Get(unsigned int rowIx, unsigned int colIx) const {
unsigned int dataIx = rowIx * this->cols + colIx;
return this->data[dataIx];
}
void Set(unsigned int rowIx, unsigned int colIx, T value) {
unsigned int dataIx = rowIx * this->cols + colIx;
this->data[dataIx] = value;
}
// This function does not check on source size!
void Set(const T *source) {
unsigned int matrixSize = this->cols * this->rows;
for (unsigned int dataIx = 0; dataIx < matrixSize; dataIx++)
this->data[dataIx] = source[dataIx];
}
// This function does not check on source size!
void SetRow(unsigned int rowIx, const T *source) {
unsigned int dataIx = rowIx * this->cols;
for (unsigned int sourceIx = 0; sourceIx < this->cols; dataIx++, sourceIx++)
this->data[dataIx] = source[sourceIx];
}
// This function does not check on source size!
void SetCol(unsigned int colIx, const T *source) {
unsigned int dataIx = colIx;
for (unsigned int sourceIx = 0; sourceIx < this->cols;
dataIx += this->cols, sourceIx++)
this->data[dataIx] = source[sourceIx];
}
void CopyFrom(const MatrixOf<T> *m) {
unsigned int thisMatrixSize = this->cols * this->rows;
unsigned int mMatrixSize = m->cols * m->rows;
if (mMatrixSize != thisMatrixSize)
return;
for (unsigned int dataIx = 0; dataIx < thisMatrixSize; dataIx++)
this->data[dataIx] = m->data[dataIx];
}
unsigned int RowCount() const { return rows; }
unsigned int ColCount() const { return cols; }
private:
unsigned int rows;
unsigned int cols;
T *data;
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

281
LinearAlgebra/Polar.cpp Normal file
View File

@ -0,0 +1,281 @@
#include <math.h>
#include "Polar.h"
template <typename T>
PolarOf<T>::PolarOf() {
this->distance = 0.0f;
this->angle = 0.0f;
}
template <typename T>
PolarOf<T>::PolarOf(float distance, AngleOf<T> angle) {
// distance should always be 0 or greater
if (distance < 0.0f) {
this->distance = -distance;
this->angle = AngleOf<T>::Normalize(angle.ToFloat() - 180.0f);
} else {
this->distance = distance;
if (this->distance == 0.0f)
// angle is always 0 if distance is 0
this->angle = 0.0f;
else
this->angle = AngleOf<T>::Normalize(angle);
}
}
template <typename T>
PolarOf<T> PolarOf<T>::FromVector2(Vector2 v) {
float distance = v.magnitude();
AngleOf<T> angle = Vector2::SignedAngle(Vector2::forward, v);
PolarOf<T> p = PolarOf(distance, angle);
return p;
}
template <typename T>
PolarOf<T> PolarOf<T>::FromSpherical(SphericalOf<T> v) {
float distance =
v.distance * cosf(v.vertical.ToFloat() * Passer::LinearAlgebra::Deg2Rad);
AngleOf<T> angle = v.horizontal;
PolarOf<T> p = PolarOf(distance, angle);
return p;
}
template <typename T>
const PolarOf<T> PolarOf<T>::zero = PolarOf(0.0f, 0.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::forward = PolarOf(1.0f, 0.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::back = PolarOf(1.0, 180.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::right = PolarOf(1.0, 90.0f);
template <typename T>
const PolarOf<T> PolarOf<T>::left = PolarOf(1.0, -90.0f);
template <typename T>
bool PolarOf<T>::operator==(const PolarOf& v) const {
return (this->distance == v.distance &&
this->angle.ToFloat() == v.angle.ToFloat());
}
template <typename T>
PolarOf<T> PolarOf<T>::Normalize(const PolarOf& v) {
PolarOf<T> r = PolarOf(1, v.angle);
return r;
}
template <typename T>
PolarOf<T> PolarOf<T>::normalized() const {
PolarOf<T> r = PolarOf(1, this->angle);
return r;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator-() const {
PolarOf<T> v = PolarOf(this->distance, this->angle + AngleOf<T>(180));
return v;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator-(const PolarOf& v) const {
PolarOf<T> r = -v;
return *this + r;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator-=(const PolarOf& v) {
*this = *this - v;
return *this;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator+(const PolarOf& v) const {
if (v.distance == 0)
return PolarOf(this->distance, this->angle);
if (this->distance == 0.0f)
return v;
float deltaAngle =
Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat();
float rotation =
deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle;
if (rotation == 180.0f && v.distance > 0.0f) {
// angle is too small, take this angle and add the distances
return PolarOf(this->distance + v.distance, this->angle);
}
float newDistance =
Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat();
float angle =
Angle::CosineRuleAngle(newDistance, this->distance, v.distance).ToFloat();
float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle
: this->angle.ToFloat() + angle;
newAngle = Angle::Normalize(newAngle).ToFloat();
PolarOf vector = PolarOf(newDistance, newAngle);
return vector;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator+=(const PolarOf& v) {
*this = *this + v;
return *this;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator*=(float f) {
this->distance *= f;
return *this;
}
template <typename T>
PolarOf<T> PolarOf<T>::operator/=(float f) {
this->distance /= f;
return *this;
}
template <typename T>
float PolarOf<T>::Distance(const PolarOf& v1, const PolarOf& v2) {
float d = Angle::CosineRuleSide(v1.distance, v2.distance,
v2.angle.ToFloat() - v1.angle.ToFloat())
.ToFloat();
return d;
}
template <typename T>
PolarOf<T> PolarOf<T>::Rotate(const PolarOf& v, AngleOf<T> angle) {
AngleOf<T> a = AngleOf<T>::Normalize(v.angle + angle);
PolarOf<T> r = PolarOf(v.distance, a);
return r;
}
template class PolarOf<float>;
template class PolarOf<signed short>;
//=====================================
/*
Polar::Polar() {
this->distance = 0.0f;
this->angle = 0.0f;
}
Polar::Polar(float distance, Angle angle) {
// distance should always be 0 or greater
if (distance < 0.0f) {
this->distance = -distance;
this->angle = Angle::Normalize(angle.ToFloat() - 180.0f);
} else {
this->distance = distance;
if (this->distance == 0.0f)
// angle is always 0 if distance is 0
this->angle = 0.0f;
else
this->angle = Angle::Normalize(angle);
}
}
Polar::Polar(Vector2 v) {
this->distance = v.magnitude();
this->angle = Vector2::SignedAngle(Vector2::forward, v);
}
Polar::Polar(Spherical v) {
this->distance = v.distance * cosf(v.verticalAngle.ToFloat() *
Passer::LinearAlgebra::Deg2Rad);
this->angle = v.horizontalAngle;
}
const Polar Polar::zero = Polar(0.0f, 0.0f);
const Polar Polar::forward = Polar(1.0f, 0.0f);
const Polar Polar::back = Polar(1.0, 180.0f);
const Polar Polar::right = Polar(1.0, 90.0f);
const Polar Polar::left = Polar(1.0, -90.0f);
bool Polar::operator==(const Polar& v) const {
return (this->distance == v.distance &&
this->angle.ToFloat() == v.angle.ToFloat());
}
Polar Polar::Normalize(const Polar& v) {
Polar r = Polar(1, v.angle);
return r;
}
Polar Polar::normalized() const {
Polar r = Polar(1, this->angle);
return r;
}
Polar Polar::operator-() const {
Polar v = Polar(this->distance, this->angle.ToFloat() + 180.0f);
return v;
}
Polar Polar::operator-(const Polar& v) const {
Polar r = -v;
return *this + r;
}
Polar Polar::operator-=(const Polar& v) {
*this = *this - v;
return *this;
}
Polar Polar::operator+(const Polar& v) const {
if (v.distance == 0)
return Polar(this->distance, this->angle);
if (this->distance == 0.0f)
return v;
float deltaAngle =
Angle::Normalize(v.angle.ToFloat() - this->angle.ToFloat()).ToFloat();
float rotation =
deltaAngle < 0.0f ? 180.0f + deltaAngle : 180.0f - deltaAngle;
if (rotation == 180.0f && v.distance > 0.0f) {
// angle is too small, take this angle and add the distances
return Polar(this->distance + v.distance, this->angle);
}
float newDistance =
Angle::CosineRuleSide(v.distance, this->distance, rotation).ToFloat();
float angle =
Angle::CosineRuleAngle(newDistance, this->distance,
v.distance).ToFloat();
float newAngle = deltaAngle < 0.0f ? this->angle.ToFloat() - angle
: this->angle.ToFloat() + angle;
newAngle = Angle::Normalize(newAngle).ToFloat();
Polar vector = Polar(newDistance, newAngle);
return vector;
}
Polar Polar::operator+=(const Polar& v) {
*this = *this + v;
return *this;
}
// Polar Passer::LinearAlgebra::operator*(const Polar &v, float f) {
// return Polar(v.distance * f, v.angle);
// }
// Polar Passer::LinearAlgebra::operator*(float f, const Polar &v) {
// return Polar(v.distance * f, v.angle);
// }
Polar Polar::operator*=(float f) {
this->distance *= f;
return *this;
}
// Polar Passer::LinearAlgebra::operator/(const Polar& v, float f) {
// return Polar(v.distance / f, v.angle);
// }
// Polar Passer::LinearAlgebra::operator/(float f, const Polar& v) {
// return Polar(v.distance / f, v.angle);
// }
Polar Polar::operator/=(float f) {
this->distance /= f;
return *this;
}
float Polar::Distance(const Polar& v1, const Polar& v2) {
float d = Angle::CosineRuleSide(v1.distance, v2.distance,
v2.angle.ToFloat() - v1.angle.ToFloat())
.ToFloat();
return d;
}
Polar Polar::Rotate(const Polar& v, Angle angle) {
Angle a = Angle::Normalize(v.angle.ToFloat() + angle.ToFloat());
Polar r = Polar(v.distance, a);
return r;
}
*/

264
LinearAlgebra/Polar.h Normal file
View File

@ -0,0 +1,264 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef POLAR_H
#define POLAR_H
#include "Angle.h"
namespace Passer {
namespace LinearAlgebra {
struct Vector2;
template <typename T>
class SphericalOf;
template <typename T>
class PolarOf {
public:
/// @brief The distance in meters
/// @remark The distance shall never be negative
float distance;
/// @brief The angle in degrees clockwise rotation
/// @remark The angle shall be between -180 .. 180
AngleOf<T> angle;
/// @brief A new vector with polar coordinates with zero degrees and
/// distance
PolarOf();
/// @brief A new vector with polar coordinates
/// @param distance The distance in meters
/// @param angle The angle in degrees, clockwise rotation
/// @note The distance is automatically converted to a positive value.
/// @note The angle is automatically normalized to -180 .. 180
PolarOf(float distance, AngleOf<T> angle);
/// @brief Convert a vector from 2D carthesian coordinates to polar
/// coordinates
/// @param v The vector to convert
static PolarOf<T> FromVector2(Vector2 v);
/// @brief Convert a vector from spherical coordinates to polar coordinates
/// @param s The vector to convert
/// @note The resulting vector will be projected on the horizontal plane
static PolarOf<T> FromSpherical(SphericalOf<T> v);
/// @brief A polar vector with zero degrees and distance
const static PolarOf zero;
/// @brief A normalized forward-oriented vector
const static PolarOf forward;
/// @brief A normalized back-oriented vector
const static PolarOf back;
/// @brief A normalized right-oriented vector
const static PolarOf right;
/// @brief A normalized left-oriented vector
const static PolarOf left;
/// @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 PolarOf& 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 PolarOf& 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 PolarOf Normalize(const PolarOf& v);
/// @brief Convert the vector to a length of a
/// @return The vector normalized to a length of 1
PolarOf normalized() const;
/// @brief Negate the vector
/// @return The negated vector
/// This will rotate the vector by 180 degrees. Distance will stay the same.
PolarOf operator-() const;
/// @brief Subtract a polar vector from this vector
/// @param v The vector to subtract
/// @return The result of the subtraction
PolarOf operator-(const PolarOf& v) const;
PolarOf operator-=(const PolarOf& v);
/// @brief Add a polar vector to this vector
/// @param v The vector to add
/// @return The result of the addition
PolarOf operator+(const PolarOf& v) const;
PolarOf operator+=(const PolarOf& 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 PolarOf operator*(const PolarOf& v, float f) {
return PolarOf(v.distance * f, v.angle);
}
friend PolarOf operator*(float f, const PolarOf& v) {
return PolarOf(f * v.distance, v.angle);
}
PolarOf 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 PolarOf operator/(const PolarOf& v, float f) {
return PolarOf(v.distance / f, v.angle);
}
friend PolarOf operator/(float f, const PolarOf& v) {
return PolarOf(f / v.distance, v.angle);
}
PolarOf operator/=(float f);
/// @brief The distance between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The distance between the two vectors
static float Distance(const PolarOf& v1, const PolarOf& v2);
/// @brief Rotate a vector
/// @param v The vector to rotate
/// @param a The angle in degreesto rotate
/// @return The rotated vector
static PolarOf Rotate(const PolarOf& v, AngleOf<T> a);
};
using PolarSingle = PolarOf<float>;
using Polar16 = PolarOf<signed short>;
using Polar = PolarSingle;
/*
/// @brief A polar vector
/// @details This will use the polar coordinate system consisting of a angle
/// from a reference direction and a distance.
struct Polar {
public:
/// @brief The distance in meters
/// @remark The distance shall never be negative
float distance;
/// @brief The angle in degrees clockwise rotation
/// @remark The angle shall be between -180 .. 180
Angle angle;
/// @brief A new vector with polar coordinates with zero degrees and
/// distance
Polar();
/// @brief A new vector with polar coordinates
/// @param distance The distance in meters
/// @param angle The angle in degrees, clockwise rotation
/// @note The distance is automatically converted to a positive value.
/// @note The angle is automatically normalized to -180 .. 180
Polar(float distance, Angle angle);
/// @brief Convert a vector from 2D carthesian coordinates to polar
/// coordinates
/// @param v The vector to convert
Polar(Vector2 v);
/// @brief Convert a vector from spherical coordinates to polar coordinates
/// @param s The vector to convert
/// @note The resulting vector will be projected on the horizontal plane
Polar(Spherical s);
/// @brief A polar vector with zero degrees and distance
const static Polar zero;
/// @brief A normalized forward-oriented vector
const static Polar forward;
/// @brief A normalized back-oriented vector
const static Polar back;
/// @brief A normalized right-oriented vector
const static Polar right;
/// @brief A normalized left-oriented vector
const static Polar left;
/// @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 Polar& 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 Polar& 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 Polar Normalize(const Polar& v);
/// @brief Convert the vector to a length of a
/// @return The vector normalized to a length of 1
Polar normalized() const;
/// @brief Negate the vector
/// @return The negated vector
/// This will rotate the vector by 180 degrees. Distance will stay the same.
Polar operator-() const;
/// @brief Subtract a polar vector from this vector
/// @param v The vector to subtract
/// @return The result of the subtraction
Polar operator-(const Polar& v) const;
Polar operator-=(const Polar& v);
/// @brief Add a polar vector to this vector
/// @param v The vector to add
/// @return The result of the addition
Polar operator+(const Polar& v) const;
Polar operator+=(const Polar& 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 Polar operator*(const Polar& v, float f) {
return Polar(v.distance * f, v.angle);
}
friend Polar operator*(float f, const Polar& v) {
return Polar(f * v.distance, v.angle);
}
Polar 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 Polar operator/(const Polar& v, float f) {
return Polar(v.distance / f, v.angle);
}
friend Polar operator/(float f, const Polar& v) {
return Polar(f / v.distance, v.angle);
}
Polar operator/=(float f);
/// @brief The distance between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The distance between the two vectors
static float Distance(const Polar& v1, const Polar& v2);
/// @brief Rotate a vector
/// @param v The vector to rotate
/// @param a The angle in degreesto rotate
/// @return The rotated vector
static Polar Rotate(const Polar& v, Angle a);
};
*/
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#include "Spherical.h"
#include "Vector2.h"
#endif

View File

@ -0,0 +1,418 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Quaternion.h"
#include <float.h>
#include <math.h>
#include "Angle.h"
#include "Vector3.h"
void CopyQuat(const Quat& q1, Quat& q2) {
q2.x = q1.x;
q2.y = q1.y;
q2.z = q1.z;
q2.w = q1.w;
}
const float Deg2Rad = 0.0174532924F;
const float Rad2Deg = 57.29578F;
Quaternion::Quaternion() {
x = 0;
y = 0;
z = 0;
w = 1;
}
Quaternion::Quaternion(float _x, float _y, float _z, float _w) {
x = _x;
y = _y;
z = _z;
w = _w;
}
Quaternion::Quaternion(Quat q) {
x = q.x;
y = q.y;
z = q.z;
w = q.w;
}
Quaternion::~Quaternion() {}
const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1);
Vector3 Quaternion::xyz() const {
return Vector3(x, y, z);
}
float Quaternion::GetLength() const {
return sqrtf(x * x + y * y + z * z + w * w);
}
float Quaternion::GetLengthSquared() const {
return x * x + y * y + z * z + w * w;
}
float Quaternion::GetLengthSquared(const Quaternion& q) {
return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
}
void Quaternion::Normalize() {
float length = GetLength();
x /= length;
y /= length;
z /= length;
w /= length;
}
Quaternion Quaternion::Normalize(const Quaternion& q) {
Quaternion result;
float length = q.GetLength();
result = Quaternion(q.x / length, q.y / length, q.z / length, q.w / length);
return result;
};
float Quaternion::Dot(Quaternion a, Quaternion b) {
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
Vector3 Quaternion::ToAngles(const Quaternion& q1) {
float test = q1.x * q1.y + q1.z * q1.w;
if (test > 0.499f) { // singularity at north pole
return Vector3(0, 2 * (float)atan2(q1.x, q1.w) * Rad2Deg, 90);
} else if (test < -0.499f) { // singularity at south pole
return Vector3(0, -2 * (float)atan2(q1.x, q1.w) * Rad2Deg, -90);
} else {
float sqx = q1.x * q1.x;
float sqy = q1.y * q1.y;
float sqz = q1.z * q1.z;
return Vector3(
atan2f(2 * q1.x * q1.w - 2 * q1.y * q1.z, 1 - 2 * sqx - 2 * sqz) *
Rad2Deg,
atan2f(2 * q1.y * q1.w - 2 * q1.x * q1.z, 1 - 2 * sqy - 2 * sqz) *
Rad2Deg,
asinf(2 * test) * Rad2Deg);
}
}
Quaternion Quaternion::operator*(const Quaternion& r2) const {
return Quaternion(
this->x * r2.w + this->y * r2.z - this->z * r2.y + this->w * r2.x,
-this->x * r2.z + this->y * r2.w + this->z * r2.x + this->w * r2.y,
this->x * r2.y - this->y * r2.x + this->z * r2.w + this->w * r2.z,
-this->x * r2.x - this->y * r2.y - this->z * r2.z + this->w * r2.w);
};
Vector3 Quaternion::operator*(const Vector3& p) const {
float num = this->x * 2;
float num2 = this->y * 2;
float num3 = this->z * 2;
float num4 = this->x * num;
float num5 = this->y * num2;
float num6 = this->z * num3;
float num7 = this->x * num2;
float num8 = this->x * num3;
float num9 = this->y * num3;
float num10 = this->w * num;
float num11 = this->w * num2;
float num12 = this->w * num3;
float px = p.Right();
float py = p.Up();
float pz = p.Forward();
// Vector3 result = Vector3::zero;
// result.x =
float rx =
(1 - (num5 + num6)) * px + (num7 - num12) * py + (num8 + num11) * pz;
// result.y =
float ry =
(num7 + num12) * px + (1 - (num4 + num6)) * py + (num9 - num10) * pz;
// result.z =
float rz =
(num8 - num11) * px + (num9 + num10) * py + (1 - (num4 + num5)) * pz;
Vector3 result = Vector3(rx, ry, rz);
return result;
}
bool Quaternion::operator==(const Quaternion& q) {
return (this->x == q.x && this->y == q.y && this->z == q.z && this->w == q.w);
}
Quaternion Quaternion::Inverse(Quaternion r) {
float n = sqrtf(r.x * r.x + r.y * r.y + r.z * r.z + r.w * r.w);
return Quaternion(-r.x / n, -r.y / n, -r.z / n, r.w / n);
}
Quaternion Quaternion::LookRotation(const Vector3& forward) {
Vector3 up = Vector3(0, 1, 0);
return LookRotation(forward, up);
}
Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) {
Vector3 nForward = Vector3::Normalize(forward);
Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward));
Vector3 nUp = Vector3::Cross(nForward, nRight);
float m00 = nRight.Right(); // x;
float m01 = nRight.Up(); // y;
float m02 = nRight.Forward(); // z;
float m10 = nUp.Right(); // x;
float m11 = nUp.Up(); // y;
float m12 = nUp.Forward(); // z;
float m20 = nForward.Right(); // x;
float m21 = nForward.Up(); // y;
float m22 = nForward.Forward(); // z;
float num8 = (m00 + m11) + m22;
Quaternion quaternion = Quaternion();
if (num8 > 0) {
float num = sqrtf(num8 + 1);
quaternion.w = num * 0.5f;
num = 0.5f / num;
quaternion.x = (m12 - m21) * num;
quaternion.y = (m20 - m02) * num;
quaternion.z = (m01 - m10) * num;
return quaternion;
}
if ((m00 >= m11) && (m00 >= m22)) {
float num7 = sqrtf(((1 + m00) - m11) - m22);
float num4 = 0.5F / num7;
quaternion.x = 0.5f * num7;
quaternion.y = (m01 + m10) * num4;
quaternion.z = (m02 + m20) * num4;
quaternion.w = (m12 - m21) * num4;
return quaternion;
}
if (m11 > m22) {
float num6 = sqrtf(((1 + m11) - m00) - m22);
float num3 = 0.5F / num6;
quaternion.x = (m10 + m01) * num3;
quaternion.y = 0.5F * num6;
quaternion.z = (m21 + m12) * num3;
quaternion.w = (m20 - m02) * num3;
return quaternion;
}
float num5 = sqrtf(((1 + m22) - m00) - m11);
float num2 = 0.5F / num5;
quaternion.x = (m20 + m02) * num2;
quaternion.y = (m21 + m12) * num2;
quaternion.z = 0.5F * num5;
quaternion.w = (m01 - m10) * num2;
return quaternion;
}
Quaternion Quaternion::FromToRotation(Vector3 fromDirection,
Vector3 toDirection) {
Vector3 axis = Vector3::Cross(fromDirection, toDirection);
axis = Vector3::Normalize(axis);
AngleOf<float> angle = Vector3::SignedAngle(fromDirection, toDirection, axis);
Quaternion rotation = Quaternion::AngleAxis(angle.ToFloat(), axis);
return rotation;
}
Quaternion Quaternion::RotateTowards(const Quaternion& from,
const Quaternion& to,
float maxDegreesDelta) {
float num = Quaternion::Angle(from, to);
if (num == 0) {
return to;
}
float t = (float)fmin(1, maxDegreesDelta / num);
return SlerpUnclamped(from, to, t);
}
Quaternion Quaternion::AngleAxis(float angle, const Vector3& axis) {
if (Vector3::SqrMagnitude(axis) == 0.0f)
return Quaternion();
Quaternion result = Quaternion();
float radians = angle * Deg2Rad;
radians *= 0.5f;
Vector3 axis2 = axis * (float)sin(radians);
result.x = axis2.Right(); // x;
result.y = axis2.Up(); // y;
result.z = axis2.Forward(); // z;
result.w = (float)cos(radians);
return Quaternion::Normalize(result);
}
float Quaternion::Angle(Quaternion a, Quaternion b) {
float f = Quaternion::Dot(a, b);
return (float)acos(fmin(fabs(f), 1)) * 2 * Rad2Deg;
}
void Quaternion::ToAngleAxis(float* angle, Vector3* axis) {
Quaternion::ToAxisAngleRad(*this, axis, angle);
*angle *= Rad2Deg;
}
void Quaternion::ToAxisAngleRad(const Quaternion& q,
Vector3* const axis,
float* angle) {
Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q;
*angle = 2.0f * acosf(q1.w); // angle
float den = sqrtf(1.0F - q1.w * q1.w);
if (den > 0.0001f) {
*axis = Vector3::Normalize(q1.xyz() / den);
} else {
// This occurs when the angle is zero.
// Not a problem: just set an arbitrary normalized axis.
*axis = Vector3(1, 0, 0);
}
}
Quaternion Quaternion::SlerpUnclamped(const Quaternion& a,
const Quaternion& b,
float t) {
// if either input is zero, return the other.
if (Quaternion::GetLengthSquared(a) == 0.0f) {
if (Quaternion::GetLengthSquared(b) == 0.0f) {
return Quaternion();
}
return b;
} else if (Quaternion::GetLengthSquared(b) == 0.0f) {
return a;
}
const Vector3 axyz = a.xyz();
const Vector3 bxyz = b.xyz();
float cosHalfAngle = a.w * b.w + Vector3::Dot(axyz, bxyz);
Quaternion b2 = b;
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f) {
// angle = 0.0f, so just return one input.
return a;
} else if (cosHalfAngle < 0.0f) {
b2.x = -b.x;
b2.y = -b.y;
b2.z = -b.z;
b2.w = -b.w;
cosHalfAngle = -cosHalfAngle;
}
float blendA;
float blendB;
if (cosHalfAngle < 0.99f) {
// do proper slerp for big angles
float halfAngle = acosf(cosHalfAngle);
float sinHalfAngle = sinf(halfAngle);
float oneOverSinHalfAngle = 1.0F / sinHalfAngle;
blendA = sinf(halfAngle * (1.0F - t)) * oneOverSinHalfAngle;
blendB = sinf(halfAngle * t) * oneOverSinHalfAngle;
} else {
// do lerp if angle is really small.
blendA = 1.0f - t;
blendB = t;
}
Vector3 v = axyz * blendA + b2.xyz() * blendB;
Quaternion result =
Quaternion(v.Right(), v.Up(), v.Forward(), blendA * a.w + blendB * b2.w);
if (result.GetLengthSquared() > 0.0f)
return Quaternion::Normalize(result);
else
return Quaternion();
}
Quaternion Quaternion::Slerp(const Quaternion& a,
const Quaternion& b,
float t) {
if (t > 1)
t = 1;
if (t < 0)
t = 0;
return Quaternion::SlerpUnclamped(a, b, t);
}
Quaternion Quaternion::Euler(float x, float y, float z) {
return Quaternion::Euler(Vector3(x, y, z));
}
Quaternion Quaternion::Euler(Vector3 euler) {
return Quaternion::FromEulerRad(euler * Deg2Rad);
}
Quaternion Quaternion::FromEulerRad(Vector3 euler) {
float yaw = euler.Right();
float pitch = euler.Up();
float roll = euler.Forward();
float rollOver2 = roll * 0.5f;
float sinRollOver2 = (float)sin((float)rollOver2);
float cosRollOver2 = (float)cos((float)rollOver2);
float pitchOver2 = pitch * 0.5f;
float sinPitchOver2 = (float)sin((float)pitchOver2);
float cosPitchOver2 = (float)cos((float)pitchOver2);
float yawOver2 = yaw * 0.5f;
float sinYawOver2 = (float)sin((float)yawOver2);
float cosYawOver2 = (float)cos((float)yawOver2);
Quaternion result;
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 +
sinYawOver2 * sinPitchOver2 * sinRollOver2;
result.x = sinYawOver2 * cosPitchOver2 * cosRollOver2 +
cosYawOver2 * sinPitchOver2 * sinRollOver2;
result.y = cosYawOver2 * sinPitchOver2 * cosRollOver2 -
sinYawOver2 * cosPitchOver2 * sinRollOver2;
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 -
sinYawOver2 * sinPitchOver2 * cosRollOver2;
return result;
}
Quaternion Quaternion::EulerXYZ(float x, float y, float z) {
return Quaternion::EulerXYZ(Vector3(x, y, z));
}
Quaternion Quaternion::EulerXYZ(Vector3 euler) {
return Quaternion::FromEulerRadXYZ(euler * Deg2Rad);
}
Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) {
float yaw = euler.Right(); // x;
float pitch = euler.Up(); // y;
float roll = euler.Forward(); // z;
float rollOver2 = roll * 0.5f;
float sinRollOver2 = (float)sin((float)rollOver2);
float cosRollOver2 = (float)cos((float)rollOver2);
float pitchOver2 = pitch * 0.5f;
float sinPitchOver2 = (float)sin((float)pitchOver2);
float cosPitchOver2 = (float)cos((float)pitchOver2);
float yawOver2 = yaw * 0.5f;
float sinYawOver2 = (float)sin((float)yawOver2);
float cosYawOver2 = (float)cos((float)yawOver2);
Quaternion result;
result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 +
sinYawOver2 * sinPitchOver2 * sinRollOver2;
result.x = sinYawOver2 * cosPitchOver2 * cosRollOver2 -
cosYawOver2 * sinPitchOver2 * sinRollOver2;
result.y = cosYawOver2 * sinPitchOver2 * cosRollOver2 +
sinYawOver2 * cosPitchOver2 * sinRollOver2;
result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 -
sinYawOver2 * sinPitchOver2 * cosRollOver2;
return result;
}
float Quaternion::GetAngleAround(Vector3 axis, Quaternion rotation) {
Quaternion secondaryRotation = GetRotationAround(axis, rotation);
float rotationAngle;
Vector3 rotationAxis;
secondaryRotation.ToAngleAxis(&rotationAngle, &rotationAxis);
// Do the axis point in opposite directions?
if (Vector3::Dot(axis, rotationAxis) < 0)
rotationAngle = -rotationAngle;
return rotationAngle;
}
Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) {
Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis
Vector3 p = Vector3::Project(
ra, axis); // return projection ra on to axis (parallel component)
Quaternion twist = Quaternion(p.Right(), p.Up(), p.Forward(), rotation.w);
twist = Quaternion::Normalize(twist);
return twist;
}
void Quaternion::GetSwingTwist(Vector3 axis,
Quaternion rotation,
Quaternion* swing,
Quaternion* twist) {
*twist = GetRotationAround(axis, rotation);
*swing = rotation * Quaternion::Inverse(*twist);
}

290
LinearAlgebra/Quaternion.h Normal file
View File

@ -0,0 +1,290 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef QUATERNION_H
#define QUATERNION_H
#include "Vector3.h"
namespace Passer {
namespace LinearAlgebra {
extern "C" {
/// <summary>
/// A quaternion
/// </summary>
/// This is a C-style implementation
typedef struct Quat {
/// <summary>
/// The x component
/// </summary>
float x;
/// <summary>
/// The y component
/// </summary>
float y;
/// <summary>
/// The z component
/// </summary>
float z;
/// <summary>
/// The w component
/// </summary>
float w;
} Quat;
}
/// <summary>
/// A quaternion
/// </summary>
struct Quaternion : Quat {
public:
/// <summary>
/// Create a new identity quaternion
/// </summary>
Quaternion();
/// <summary>
/// create a new quaternion with the given values
/// </summary>
/// <param name="_x">x component</param>
/// <param name="_y">y component</param>
/// <param name="_z">z component</param>
/// <param name="_w">w component</param>
Quaternion(float _x, float _y, float _z, float _w);
/// <summary>
/// Create a quaternion from C-style Quat
/// </summary>
/// <param name="q"></param>
Quaternion(Quat q);
/// <summary>
/// Quaternion destructor
/// </summary>
~Quaternion();
/// <summary>
/// An identity quaternion
/// </summary>
const static Quaternion identity;
/// <summary>
/// Convert to unit quaternion
/// </summary>
/// This will preserve the orientation,
/// but ensures that it is a unit quaternion.
void Normalize();
/// <summary>
/// Convert to unity quaternion
/// </summary>
/// <param name="q">The quaternion to convert</param>
/// <returns>A unit quaternion</returns>
/// This will preserve the orientation,
/// but ensures that it is a unit quaternion.
static Quaternion Normalize(const Quaternion &q);
/// <summary>
/// Convert to euler angles
/// </summary>
/// <param name="q">The quaternion to convert</param>
/// <returns>A vector containing euler angles</returns>
/// The euler angles performed in the order: Z, X, Y
static Vector3 ToAngles(const Quaternion &q);
/// <summary>
/// Rotate a vector using this quaterion
/// </summary>
/// <param name="vector">The vector to rotate</param>
/// <returns>The rotated vector</returns>
Vector3 operator*(const Vector3 &vector) const;
/// <summary>
/// Multiply this quaternion with another quaternion
/// </summary>
/// <param name="rotation">The quaternion to multiply with</param>
/// <returns>The resulting rotation</returns>
/// The result will be this quaternion rotated according to
/// the give rotation.
Quaternion operator*(const Quaternion &rotation) const;
/// <summary>
/// Check the equality of two quaternions
/// </summary>
/// <param name="quaternion">The quaternion to compare to</param>
/// <returns>True when the components of the quaternions are
/// identical</returns> Note that this does not compare the rotations
/// themselves. Two quaternions with the same rotational effect may have
/// different components. Use Quaternion::Angle to check if the rotations are
/// the same.
bool operator==(const Quaternion &quaternion);
/// <summary>
/// The inverse of quaterion
/// </summary>
/// <param name="quaternion">The quaternion for which the inverse is
/// needed</param> <returns>The inverted quaternion</returns>
static Quaternion Inverse(Quaternion quaternion);
/// <summary>
/// A rotation which looks in the given direction
/// </summary>
/// <param name="forward">The look direction</param>
/// <param name="upwards">The up direction</param>
/// <returns>The look rotation</returns>
static Quaternion LookRotation(const Vector3 &forward,
const Vector3 &upwards);
/// <summary>
/// Creates a quaternion with the given forward direction with up =
/// Vector3::up
/// </summary>
/// <param name="forward">The look direction</param>
/// <returns>The rotation for this direction</returns>
/// For the rotation, Vector::up is used for the up direction.
/// Note: if the forward direction == Vector3::up, the result is
/// Quaternion::identity
static Quaternion LookRotation(const Vector3 &forward);
/// <summary>
/// Calculat the rotation from on vector to another
/// </summary>
/// <param name="fromDirection">The from direction</param>
/// <param name="toDirection">The to direction</param>
/// <returns>The rotation from the first to the second vector</returns>
static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
/// <summary>
/// Rotate form one orientation to anther with a maximum amount of degrees
/// </summary>
/// <param name="from">The from rotation</param>
/// <param name="to">The destination rotation</param>
/// <param name="maxDegreesDelta">The maximum amount of degrees to
/// rotate</param> <returns>The possibly limited rotation</returns>
static Quaternion RotateTowards(const Quaternion &from, const Quaternion &to,
float maxDegreesDelta);
/// <summary>
/// Convert an angle/axis representation to a quaternion
/// </summary>
/// <param name="angle">The angle</param>
/// <param name="axis">The axis</param>
/// <returns>The resulting quaternion</returns>
static Quaternion AngleAxis(float angle, const Vector3 &axis);
/// <summary>
/// Convert this quaternion to angle/axis representation
/// </summary>
/// <param name="angle">A pointer to the angle for the result</param>
/// <param name="axis">A pointer to the axis for the result</param>
void ToAngleAxis(float *angle, Vector3 *axis);
/// <summary>
/// Get the angle between two orientations
/// </summary>
/// <param name="orientation1">The first orientation</param>
/// <param name="orientation2">The second orientation</param>
/// <returns>The smallest angle in degrees between the two
/// orientations</returns>
static float Angle(Quaternion orientation1, Quaternion orientation2);
/// <summary>
/// Sherical lerp between two rotations
/// </summary>
/// <param name="rotation1">The first rotation</param>
/// <param name="rotation2">The second rotation</param>
/// <param name="factor">The factor between 0 and 1.</param>
/// <returns>The resulting rotation</returns>
/// A factor 0 returns rotation1, factor1 returns rotation2.
static Quaternion Slerp(const Quaternion &rotation1,
const Quaternion &rotation2, float factor);
/// <summary>
/// Unclamped sherical lerp between two rotations
/// </summary>
/// <param name="rotation1">The first rotation</param>
/// <param name="rotation2">The second rotation</param>
/// <param name="factor">The factor</param>
/// <returns>The resulting rotation</returns>
/// A factor 0 returns rotation1, factor1 returns rotation2.
/// Values outside the 0..1 range will result in extrapolated rotations
static Quaternion SlerpUnclamped(const Quaternion &rotation1,
const Quaternion &rotation2, float factor);
/// <summary>
/// Create a rotation from euler angles
/// </summary>
/// <param name="x">The angle around the right axis</param>
/// <param name="y">The angle around the upward axis</param>
/// <param name="z">The angle around the forward axis</param>
/// <returns>The resulting quaternion</returns>
/// Rotation are appied in the order Z, X, Y.
static Quaternion Euler(float x, float y, float z);
/// <summary>
/// Create a rotation from a vector containing euler angles
/// </summary>
/// <param name="eulerAngles">Vector with the euler angles</param>
/// <returns>The resulting quaternion</returns>
/// Rotation are appied in the order Z, X, Y.
static Quaternion Euler(Vector3 eulerAngles);
/// <summary>
/// Create a rotation from euler angles
/// </summary>
/// <param name="x">The angle around the right axis</param>
/// <param name="y">The angle around the upward axis</param>
/// <param name="z">The angle around the forward axis</param>
/// <returns>The resulting quaternion</returns>
/// Rotation are appied in the order X, Y, Z.
static Quaternion EulerXYZ(float x, float y, float z);
/// <summary>
/// Create a rotation from a vector containing euler angles
/// </summary>
/// <param name="eulerAngles">Vector with the euler angles</param>
/// <returns>The resulting quaternion</returns>
/// Rotation are appied in the order X, Y, Z.
static Quaternion EulerXYZ(Vector3 eulerAngles);
/// <summary>
/// Returns the angle of around the give axis for a rotation
/// </summary>
/// <param name="axis">The axis around which the angle should be
/// computed</param> <param name="rotation">The source rotation</param>
/// <returns>The signed angle around the axis</returns>
static float GetAngleAround(Vector3 axis, Quaternion rotation);
/// <summary>
/// Returns the rotation limited around the given axis
/// </summary>
/// <param name="axis">The axis which which the rotation should be
/// limited</param> <param name="rotation">The source rotation</param>
/// <returns>The rotation around the given axis</returns>
static Quaternion GetRotationAround(Vector3 axis, Quaternion rotation);
/// <summary>
/// Swing-twist decomposition of a rotation
/// </summary>
/// <param name="axis">The base direction for the decomposition</param>
/// <param name="rotation">The source rotation</param>
/// <param name="swing">A pointer to the quaternion for the swing
/// result</param> <param name="twist">A pointer to the quaternion for the
/// twist result</param>
static void GetSwingTwist(Vector3 axis, Quaternion rotation,
Quaternion *swing, Quaternion *twist);
/// <summary>
/// Calculate the dot product of two quaternions
/// </summary>
/// <param name="rotation1">The first rotation</param>
/// <param name="rotation2">The second rotation</param>
/// <returns></returns>
static float Dot(Quaternion rotation1, Quaternion rotation2);
private:
float GetLength() const;
float GetLengthSquared() const;
static float GetLengthSquared(const Quaternion &q);
void ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, float *angle);
static Quaternion FromEulerRad(Vector3 euler);
static Quaternion FromEulerRadXYZ(Vector3 euler);
Vector3 xyz() const;
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

12
LinearAlgebra/README.md Normal file
View File

@ -0,0 +1,12 @@
\mainpage Vector Algebra
Vector algebra library
Main components
---------------
* [Vector3](https://passervr.com/apis/VectorAlgebra/struct_vector3.html)
* [Quaternion](https://passervr.com/apis/VectorAlgebra/struct_quaternion.html)
* [Vector2](https://passervr.com/apis/VectorAlgebra/struct_vector2.html)
* [Polar](https://passervr.com/apis/VectorAlgebra/struct_polar.html)

48
LinearAlgebra/Range.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "Range.h"
/*
Range16::Range16() { this->range = 0; }
Range16::Range16(float f) {
// clamp the float range to -1..1
if (f < -1.0F)
f = -1.0F;
else if (f > 1.0F)
f = 1.0F;
// map -1..1 to 0..65535
this->range = (unsigned short)((f + 1.0F) * 65535.0F);
}
Range16::Range16(short s) {
// clamp the range to -32767..32767
// This is needed because the representation can support +/-32768 (like 2s
// complement)
if (s < -32767)
s = -32767;
else if (s > 32767)
s = 32767;
this->range = (unsigned short)(s + 32767);
}
Range16 Range16::operator-(Range16 a) { this->range - a.range; };
Range16 Range16::operator+(Range16 a) { this->range + a.range; };
Range16 &Range16::operator-() { -this->range; }
bool Range16::operator==(Range16 a) { this->range == a.range; }
bool Range16::operator!=(Range16 a) { return (this->range != a.range); }
bool Range16::operator<(Range16 a) { return (this->range < a.range); }
bool Range16::operator>(Range16 a) { return (this->range > a.range); }
bool Range16::operator<=(Range16 a) { return (this->range <= a.range); }
bool Range16::operator>=(Range16 a) { return (this->range >= a.range); }
*/
template <> RangeUsing<unsigned char>::RangeUsing(float f) {
this->value = (unsigned char)((f + 1.0f) * 127.0F);
}
template <> RangeUsing<unsigned short>::RangeUsing(float f) {
this->value = (unsigned short)((f + 1.0F) * 32767.0F);
}

50
LinearAlgebra/Range.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef RANGE_H
#define RANGE_H
namespace Passer {
namespace LinearAlgebra {
/*
/// @brief Signed range. May be renamed to SignedRange later
class Range16 {
public:
Range16();
Range16(float range); // range -1..1
Range16(short range); // range -32768..32767
inline Range16 operator-(Range16 a);
inline Range16 operator+(Range16 a);
inline virtual Range16 &operator-();
inline bool operator==(Range16 a);
inline bool operator!=(Range16 a);
inline bool operator<(Range16 a);
inline bool operator>(Range16 a);
inline bool operator<=(Range16 a);
inline bool operator>=(Range16 a);
protected:
// How do we make sure we have 16 bit range on every platform?
// uint16_t range; // 16-bit range
unsigned short range; // 16-bit range
};
*/
template <typename T> class RangeUsing {
public:
RangeUsing<T>(float range); // range -1..1
inline RangeUsing<T> operator-(RangeUsing<T> a) { this->value - a.value; }
inline RangeUsing<T> operator+(RangeUsing<T> a) { this->value + a.value; }
inline RangeUsing<T> operator-() { this->value = -this.value; }
inline T GetValue() { return value; }
T value;
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#endif

478
LinearAlgebra/Spherical.cpp Normal file
View File

@ -0,0 +1,478 @@
#include "Spherical.h"
#include "Angle.h"
#include "Quaternion.h"
#include <math.h>
template <typename T>
SphericalOf<T>::SphericalOf() {
this->distance = 0.0f;
this->horizontal = AngleOf<T>(0);
this->vertical = AngleOf<T>(0);
}
// template <>
// SphericalOf<signed short>::SphericalOf() {
// this->distance = 0.0f;
// this->horizontal = AngleOf<signed short>(0);
// this->vertical = AngleOf<signed short>(0);
// }
template <typename T>
SphericalOf<T>::SphericalOf(float distance,
AngleOf<T> horizontal,
AngleOf<T> vertical) {
this->distance = distance;
this->horizontal = horizontal;
this->vertical = vertical;
}
// template <>
// SphericalOf<float>::SphericalOf(float distance,
// AngleOf<float> horizontal,
// AngleOf<float> vertical) {
// this->distance = distance;
// this->horizontal = horizontal;
// this->vertical = vertical;
// }
// template <>
// SphericalOf<signed short>::SphericalOf(float distance,
// AngleOf<signed short> horizontal,
// AngleOf<signed short> vertical) {
// this->distance = distance;
// this->horizontal = horizontal;
// this->vertical = vertical;
// }
template <typename T>
SphericalOf<T> SphericalOf<T>::FromPolar(PolarOf<T> polar) {
AngleOf<T> horizontal = polar.angle;
AngleOf<T> vertical = AngleOf<T>(0);
SphericalOf<T> r = SphericalOf(polar.distance, horizontal, vertical);
return r;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::FromVector3(Vector3 v) {
float distance = v.magnitude();
if (distance == 0.0f) {
return SphericalOf(distance, 0, 0);
} else {
float verticalAngle =
(90.0f - acosf(v.Up() / distance) * Passer::LinearAlgebra::Rad2Deg);
float horizontalAngle =
atan2f(v.Right(), v.Forward()) * Passer::LinearAlgebra::Rad2Deg;
return SphericalOf(distance, horizontalAngle, verticalAngle);
}
}
template <typename T>
Vector3 SphericalOf<T>::ToVector3() const {
float verticalRad =
(90.0f - this->vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad;
float horizontalRad =
this->horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
float cosVertical = cosf(verticalRad);
float sinVertical = sinf(verticalRad);
float cosHorizontal = cosf(horizontalRad);
float sinHorizontal = sinf(horizontalRad);
float x = this->distance * sinVertical * sinHorizontal;
float y = this->distance * cosVertical;
float z = this->distance * sinVertical * cosHorizontal;
Vector3 v = Vector3(x, y, z);
return v;
}
template <typename T>
const SphericalOf<T> SphericalOf<T>::zero =
SphericalOf<T>(0.0f, AngleOf<T>(0), AngleOf<T>(0));
template <typename T>
const SphericalOf<T> SphericalOf<T>::forward = SphericalOf<T>(1.0f, 0.0f, 0.0f);
template <typename T>
const SphericalOf<T> SphericalOf<T>::back = SphericalOf<T>(1.0f, 180.0f, 0.0f);
template <typename T>
const SphericalOf<T> SphericalOf<T>::right = SphericalOf<T>(1.0f, 90.0f, 0.0f);
template <typename T>
const SphericalOf<T> SphericalOf<T>::left = SphericalOf<T>(1.0f, -90.0f, 0.0f);
template <typename T>
const SphericalOf<T> SphericalOf<T>::up = SphericalOf<T>(1.0f, 0.0f, 90.0f);
template <typename T>
const SphericalOf<T> SphericalOf<T>::down = SphericalOf<T>(1.0f, 0.0f, -90.0f);
template <>
const SphericalOf<signed short> SphericalOf<signed short>::zero =
SphericalOf(0.0f, AngleOf<signed short>(0), AngleOf<signed short>(0));
template <typename T>
SphericalOf<T> SphericalOf<T>::operator-() const {
SphericalOf<T> v =
SphericalOf<T>(this->distance, this->horizontal.ToFloat() + 180.0f,
this->vertical.ToFloat() + 180.0f);
return v;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::operator-(const SphericalOf<T>& s2) const {
// let's do it the easy way...
Vector3 v1 = this->ToVector3();
Vector3 v2 = s2.ToVector3();
Vector3 v = v1 - v2;
SphericalOf<T> r = SphericalOf<T>::FromVector3(v);
return r;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::operator-=(const SphericalOf<T>& v) {
*this = *this - v;
return *this;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::operator+(const SphericalOf<T>& s2) const {
// let's do it the easy way...
Vector3 v1 = this->ToVector3();
Vector3 v2 = s2.ToVector3();
Vector3 v = v1 + v2;
SphericalOf<T> r = SphericalOf<T>::FromVector3(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);
*/
}
template <typename T>
SphericalOf<T> SphericalOf<T>::operator+=(const SphericalOf<T>& v) {
*this = *this + v;
return *this;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::operator*=(float f) {
this->distance *= f;
return *this;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::operator/=(float f) {
this->distance /= f;
return *this;
}
#include "FloatSingle.h"
#include "Vector3.h"
const float epsilon = 1E-05f;
template <typename T>
AngleOf<T> SphericalOf<T>::AngleBetween(const SphericalOf& v1,
const SphericalOf& v2) {
// float denominator = v1.distance * v2.distance;
// if (denominator < epsilon)
// return 0.0f;
Vector3 v1_3 = v1.ToVector3();
Vector3 v2_3 = v2.ToVector3();
// 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;
Angle r = Vector3::Angle(v1_3, v2_3);
return AngleOf<T>(r.ToFloat());
}
template <typename T>
SphericalOf<T> SphericalOf<T>::Rotate(const SphericalOf<T>& v,
AngleOf<T> horizontalAngle,
AngleOf<T> verticalAngle) {
SphericalOf<T> r = SphericalOf(v.distance, v.horizontal + horizontalAngle,
v.vertical + verticalAngle);
return r;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::RotateHorizontal(const SphericalOf<T>& v,
AngleOf<T> a) {
SphericalOf<T> r = SphericalOf(v.distance, v.horizontal + a, v.vertical);
return r;
}
template <typename T>
SphericalOf<T> SphericalOf<T>::RotateVertical(const SphericalOf<T>& v,
AngleOf<T> a) {
SphericalOf<T> r = SphericalOf(v.distance, v.horizontal, v.vertical + a);
return r;
}
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;
}
*/

262
LinearAlgebra/Spherical.h Normal file
View File

@ -0,0 +1,262 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef SPHERICAL_H
#define SPHERICAL_H
#include "Angle.h"
// #include "Polar.h"
namespace Passer {
namespace LinearAlgebra {
struct Vector3;
template <typename T>
class PolarOf;
template <typename T>
class SphericalOf {
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
AngleOf<T> horizontal;
/// @brief The angle in the vertical plane in degrees. Positive is upward.
/// @details The angle is automatically normalized to -180 .. 180
AngleOf<T> vertical;
SphericalOf<T>();
SphericalOf<T>(float distance, AngleOf<T> horizontal, AngleOf<T> vertical);
static SphericalOf<T> FromPolar(PolarOf<T> v);
static SphericalOf<T> FromVector3(Vector3 v);
Vector3 ToVector3() const;
/// @brief A spherical vector with zero degree angles and distance
const static SphericalOf<T> zero;
/// @brief A normalized forward-oriented vector
const static SphericalOf<T> forward;
/// @brief A normalized back-oriented vector
const static SphericalOf<T> back;
/// @brief A normalized right-oriented vector
const static SphericalOf<T> right;
/// @brief A normalized left-oriented vector
const static SphericalOf<T> left;
/// @brief A normalized up-oriented vector
const static SphericalOf<T> up;
/// @brief A normalized down-oriented vector
const static SphericalOf<T> down;
/// @brief Negate the vector
/// @return The negated vector
/// This will rotate the vector by 180 degrees horizontally and
/// vertically. Distance will stay the same.
SphericalOf<T> operator-() const;
/// @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);
/// @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);
/// @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) {
return SphericalOf<T>(v.distance * f, v.horizontal, v.vertical);
}
friend SphericalOf<T> operator*(float f, const SphericalOf<T>& v) {
return SphericalOf<T>(v.distance * f, v.horizontal,
v.vertical); // not correct, should be f * v.distance
}
SphericalOf<T> 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 SphericalOf<T> operator/(const SphericalOf<T>& v, float f) {
return SphericalOf<T>(v.distance / f, v.horizontal, v.vertical);
}
friend SphericalOf<T> operator/(float f, const SphericalOf<T>& v) {
return SphericalOf<T>(v.distance / f, v.horizontal,
v.vertical); // not correct, should be f / v.distance
}
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 AngleOf<T> AngleBetween(const SphericalOf<T>& v1,
const SphericalOf<T>& v2);
static SphericalOf<T> Rotate(const SphericalOf& v,
AngleOf<T> horizontalAngle,
AngleOf<T> verticalAngle);
static SphericalOf<T> RotateHorizontal(const SphericalOf<T>& v,
AngleOf<T> angle);
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
using namespace Passer::LinearAlgebra;
#include "Polar.h"
#include "Vector3.h"
#endif

View File

@ -0,0 +1,257 @@
/*
#include "Spherical16.h"
#include "Quaternion.h"
#include "Spherical.h"
#include <math.h>
Spherical16::Spherical16() {
this->distance = 0.0f;
this->horizontalAngle = Angle16(0);
this->verticalAngle = Angle16(0);
}
Spherical16::Spherical16(Polar polar) {
this->distance = polar.distance;
this->horizontalAngle = Angle16(polar.angle.ToFloat());
this->verticalAngle = Angle16(0);
}
Spherical16::Spherical16(float distance,
Angle16 horizontalAngle,
Angle16 verticalAngle) {
if (distance < 0) {
this->distance = -distance;
this->horizontalAngle = horizontalAngle.ToFloat() - Angle16(180).ToFloat();
this->verticalAngle = verticalAngle;
} else {
this->distance = distance;
this->horizontalAngle = horizontalAngle;
this->verticalAngle = verticalAngle;
}
}
Spherical16::Spherical16(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;
}
}
Vector3 Passer::LinearAlgebra::Spherical16::ToVector3() {
float verticalRad =
(90.0f - this->verticalAngle.ToFloat()) * Passer::LinearAlgebra::Deg2Rad;
float horizontalRad =
this->horizontalAngle.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
float cosVertical = cosf(verticalRad);
float sinVertical = sinf(verticalRad);
float cosHorizontal = cosf(horizontalRad);
float sinHorizontal = sinf(horizontalRad);
float x = this->distance * sinVertical * sinHorizontal;
float y = this->distance * cosVertical;
float z = this->distance * sinVertical * cosHorizontal;
Vector3 v = Vector3(x, y, z);
return Vector3();
}
const Spherical16 Spherical16::zero = Spherical16(0.0f, 0.0f, 0.0f);
const Spherical16 Spherical16::forward = Spherical16(1.0f, 0.0f, 0.0f);
const Spherical16 Spherical16::back = Spherical16(1.0f, 180.0f, 0.0f);
const Spherical16 Spherical16::right = Spherical16(1.0f, 90.0f, 0.0f);
const Spherical16 Spherical16::left = Spherical16(1.0f, -90.0f, 0.0f);
const Spherical16 Spherical16::up = Spherical16(1.0f, 0.0f, 90.0f);
const Spherical16 Spherical16::down = Spherical16(1.0f, 0.0f, -90.0f);
bool Spherical16::operator==(const Spherical16& v) const {
return (this->distance == v.distance &&
this->horizontalAngle.ToFloat() == v.horizontalAngle.ToFloat() &&
this->verticalAngle.ToFloat() == v.verticalAngle.ToFloat());
}
Spherical16 Spherical16::Normalize(const Spherical16& v) {
Spherical16 r = Spherical16(1, v.horizontalAngle, v.verticalAngle);
return r;
}
Spherical16 Spherical16::normalized() const {
Spherical16 r = Spherical16(1, this->horizontalAngle, this->verticalAngle);
return r;
}
Spherical16 Spherical16::operator-() const {
Spherical16 v =
Spherical16(this->distance, this->horizontalAngle.ToFloat() + 180.0f,
this->verticalAngle.ToFloat() + 180.0f);
return v;
}
Spherical16 Spherical16::operator-(const Spherical16& s2) const {
Spherical thisSpherical =
Spherical(this->distance, this->horizontalAngle.ToFloat(),
this->verticalAngle.ToFloat());
Spherical spherical2 = Spherical(s2.distance, s2.horizontalAngle.ToFloat(),
s2.verticalAngle.ToFloat());
// let's do it the easy way...
Vector3 v1 = Vector3(thisSpherical);
Vector3 v2 = Vector3(spherical2);
Vector3 v = v1 - v2;
Spherical16 r = Spherical16(v);
return r;
}
Spherical16 Spherical16::operator-=(const Spherical16& v) {
*this = *this - v;
return *this;
}
Spherical16 Spherical16::operator+(const Spherical16& s2) const {
// let's do it the easy way...
Vector3 v1 =
Vector3(Spherical(this->distance, this->horizontalAngle.ToFloat(),
this->verticalAngle.ToFloat()));
Vector3 v2 = Vector3(Spherical(s2.distance, s2.horizontalAngle.ToFloat(),
s2.verticalAngle.ToFloat()));
Vector3 v = v1 + v2;
Spherical16 r = Spherical16(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);
}
Spherical16 Spherical16::operator+=(const Spherical16& 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);
// }
Spherical16 Spherical16::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);
// }
Spherical16 Spherical16::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 Spherical16::AngleBetween(const Spherical16& v1, const Spherical16& 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(Spherical(v1.distance, v1.horizontalAngle.ToFloat(),
v1.verticalAngle.ToFloat()));
Vector3 v2_3 = Vector3(Spherical(v2.distance, v2.horizontalAngle.ToFloat(),
v2.verticalAngle.ToFloat()));
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;
}
Spherical16 Spherical16::Rotate(const Spherical16& v,
Angle horizontalAngle,
Angle verticalAngle) {
Spherical16 r = Spherical16(
v.distance, v.horizontalAngle.ToFloat() + horizontalAngle.ToFloat(),
v.verticalAngle.ToFloat() + verticalAngle.ToFloat());
return r;
}
Spherical16 Spherical16::RotateHorizontal(const Spherical16& v, Angle a) {
Spherical16 r = Spherical16(
v.distance, v.horizontalAngle.ToFloat() + a.ToFloat(), v.verticalAngle);
return r;
}
Spherical16 Spherical16::RotateVertical(const Spherical16& v, Angle a) {
Spherical16 r = Spherical16(v.distance, v.horizontalAngle,
v.verticalAngle.ToFloat() + a.ToFloat());
return r;
}
*/

162
LinearAlgebra/Spherical16.h Normal file
View File

@ -0,0 +1,162 @@
/*
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef SPHERICAL16_H
#define SPHERICAL16_H
#include "Angle16.h"
#include "Polar.h"
namespace Passer {
namespace LinearAlgebra {
struct Vector3;
/// @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.
/// In contrast to the normal Spherical type, this version uses 16 bit integers
/// for the angles
struct Spherical16 {
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
Angle16 horizontalAngle;
/// @brief The angle in the vertical plane in degrees. Positive is upward.
/// @details The angle is automatically normalized to -180 .. 180
Angle16 verticalAngle;
/// @brief Create a new spherical vector with zero degrees and distance
Spherical16();
/// @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
Spherical16(float distance, Angle16 horizontalAngle, Angle16 verticalAngle);
/// @brief Convert polar coordinates to spherical coordinates
/// @param polar The polar coordinate
Spherical16(Polar polar);
/// @brief Convert 3D carthesian coordinates to spherical coordinates
/// @param v Vector in 3D carthesian coordinates;
Spherical16(Vector3 v);
Vector3 ToVector3();
/// @brief A spherical vector with zero degree angles and distance
const static Spherical16 zero;
/// @brief A normalized forward-oriented vector
const static Spherical16 forward;
/// @brief A normalized back-oriented vector
const static Spherical16 back;
/// @brief A normalized right-oriented vector
const static Spherical16 right;
/// @brief A normalized left-oriented vector
const static Spherical16 left;
/// @brief A normalized up-oriented vector
const static Spherical16 up;
/// @brief A normalized down-oriented vector
const static Spherical16 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 Spherical16& 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 Spherical16& 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 Spherical16 Normalize(const Spherical16& v);
/// @brief Convert the vector to a length of a
/// @return The vector normalized to a length of 1
Spherical16 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.
Spherical16 operator-() const;
/// @brief Subtract a spherical vector from this vector
/// @param v The vector to subtract
/// @return The result of the subtraction
Spherical16 operator-(const Spherical16& v) const;
Spherical16 operator-=(const Spherical16& v);
/// @brief Add a spherical vector to this vector
/// @param v The vector to add
/// @return The result of the addition
Spherical16 operator+(const Spherical16& v) const;
Spherical16 operator+=(const Spherical16& 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 Spherical16 operator*(const Spherical16& v, float f) {
return Spherical16(v.distance * f, v.horizontalAngle, v.verticalAngle);
}
friend Spherical16 operator*(float f, const Spherical16& v) {
return Spherical16(
v.distance * f, v.horizontalAngle,
v.verticalAngle); // not correct, should be f * v.distance
}
Spherical16 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 Spherical16 operator/(const Spherical16& v, float f) {
return Spherical16(v.distance / f, v.horizontalAngle, v.verticalAngle);
}
friend Spherical16 operator/(float f, const Spherical16& v) {
return Spherical16(
v.distance / f, v.horizontalAngle,
v.verticalAngle); // not correct, should be f / v.distance
}
Spherical16 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 Spherical16 &s1, const Spherical16 &s2);
static Angle AngleBetween(const Spherical16& v1, const Spherical16& v2);
static Spherical16 Rotate(const Spherical16& v,
Angle horizontalAngle,
Angle verticalAngle);
static Spherical16 RotateHorizontal(const Spherical16& v, Angle angle);
static Spherical16 RotateVertical(const Spherical16& v, Angle angle);
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#include "Vector3.h"
#endif
*/

182
LinearAlgebra/Vector2.cpp Normal file
View File

@ -0,0 +1,182 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Vector2.h"
#include "Angle.h"
#include "FloatSingle.h"
#include "Vector3.h"
#if defined(AVR)
#include <Arduino.h>
#else
#include <math.h>
#endif
Vector2::Vector2() {
x = 0;
y = 0;
}
Vector2::Vector2(float _x, float _y) {
x = _x;
y = _y;
}
// Vector2::Vector2(Vec2 v) {
// x = v.x;
// y = v.y;
// }
Vector2::Vector2(Vector3 v) {
x = v.Right(); // x;
y = v.Forward(); // z;
}
Vector2::Vector2(Polar p) {
float horizontalRad = p.angle.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
float cosHorizontal = cosf(horizontalRad);
float sinHorizontal = sinf(horizontalRad);
x = p.distance * sinHorizontal;
y = p.distance * cosHorizontal;
}
Vector2::~Vector2() {}
const Vector2 Vector2::zero = Vector2(0, 0);
const Vector2 Vector2::one = Vector2(1, 1);
const Vector2 Vector2::right = Vector2(1, 0);
const Vector2 Vector2::left = Vector2(-1, 0);
const Vector2 Vector2::up = Vector2(0, 1);
const Vector2 Vector2::down = Vector2(0, -1);
const Vector2 Vector2::forward = Vector2(0, 1);
const Vector2 Vector2::back = Vector2(0, -1);
bool Vector2::operator==(const Vector2& v) {
return (this->x == v.x && this->y == v.y);
}
float Vector2::Magnitude(const Vector2& v) {
return sqrtf(v.x * v.x + v.y * v.y);
}
float Vector2::magnitude() const {
return (float)sqrtf(x * x + y * y);
}
float Vector2::SqrMagnitude(const Vector2& v) {
return v.x * v.x + v.y * v.y;
}
float Vector2::sqrMagnitude() const {
return (x * x + y * y);
}
Vector2 Vector2::Normalize(const Vector2& v) {
float num = Vector2::Magnitude(v);
Vector2 result = Vector2::zero;
if (num > Float::epsilon) {
result = v / num;
}
return result;
}
Vector2 Vector2::normalized() const {
float num = this->magnitude();
Vector2 result = Vector2::zero;
if (num > Float::epsilon) {
result = ((Vector2) * this) / num;
}
return result;
}
Vector2 Vector2::operator-() {
return Vector2(-this->x, -this->y);
}
Vector2 Vector2::operator-(const Vector2& v) const {
return Vector2(this->x - v.x, this->y - v.y);
}
Vector2 Vector2::operator-=(const Vector2& v) {
this->x -= v.x;
this->y -= v.y;
return *this;
}
Vector2 Vector2::operator+(const Vector2& v) const {
return Vector2(this->x + v.x, this->y + v.y);
}
Vector2 Vector2::operator+=(const Vector2& v) {
this->x += v.x;
this->y += v.y;
return *this;
}
Vector2 Vector2::Scale(const Vector2& v1, const Vector2& v2) {
return Vector2(v1.x * v2.x, v1.y * v2.y);
}
// Vector2 Passer::LinearAlgebra::operator*(const Vector2 &v, float f) {
// return Vector2(v.x * f, v.y * f);
// }
// Vector2 Passer::LinearAlgebra::operator*(float f, const Vector2 &v) {
// return Vector2(v.x * f, v.y * f);
// }
Vector2 Vector2::operator*=(float f) {
this->x *= f;
this->y *= f;
return *this;
}
// Vector2 Passer::LinearAlgebra::operator/(const Vector2 &v, float f) {
// return Vector2(v.x / f, v.y / f);
// }
// Vector2 Passer::LinearAlgebra::operator/(float f, const Vector2 &v) {
// return Vector2(v.x / f, v.y / f);
// }
Vector2 Vector2::operator/=(float f) {
this->x /= f;
this->y /= f;
return *this;
}
float Vector2::Dot(const Vector2& v1, const Vector2& v2) {
return v1.x * v2.x + v1.y * v2.y;
}
float Vector2::Distance(const Vector2& v1, const Vector2& v2) {
return Magnitude(v1 - v2);
}
float Vector2::Angle(const Vector2& v1, const Vector2& v2) {
return (float)fabs(SignedAngle(v1, v2));
}
float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) {
float sqrMagFrom = v1.sqrMagnitude();
float sqrMagTo = v2.sqrMagnitude();
if (sqrMagFrom == 0 || sqrMagTo == 0)
return 0;
if (!isfinite(sqrMagFrom) || !isfinite(sqrMagTo))
#if defined(AVR)
return NAN;
#else
return nanf("");
#endif
float angleFrom = atan2f(v1.y, v1.x);
float angleTo = atan2f(v2.y, v2.x);
return -(angleTo - angleFrom) * Passer::LinearAlgebra::Rad2Deg;
}
Vector2 Vector2::Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a) {
float angleRad = a.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
#if defined(AVR)
float sinValue = sin(angleRad);
float cosValue = cos(angleRad); // * Angle::Deg2Rad);
#else
float sinValue = (float)sinf(angleRad);
float cosValue = (float)cosf(angleRad);
#endif
float tx = v.x;
float ty = v.y;
Vector2 r = Vector2((cosValue * tx) - (sinValue * ty),
(sinValue * tx) + (cosValue * ty));
return r;
}
Vector2 Vector2::Lerp(const Vector2& v1, const Vector2& v2, float f) {
Vector2 v = v1 + (v2 - v1) * f;
return v;
}

212
LinearAlgebra/Vector2.h Normal file
View File

@ -0,0 +1,212 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef VECTOR2_H
#define VECTOR2_H
#include "Angle.h"
extern "C" {
/// <summary>
/// 2-dimensional Vector representation
/// </summary>
/// This is a C-style implementation
/// This uses the right-handed coordinate system.
typedef struct Vec2 {
/// <summary>
/// The right axis of the vector
/// </summary>
float x;
/// <summary>
/// The upward/forward axis of the vector
/// </summary>
float y;
} Vec2;
}
namespace Passer {
namespace LinearAlgebra {
struct Vector3;
template <typename T>
class PolarOf;
// using Polar = PolarOf<float>
/// @brief A 2=dimensional vector
/// @remark This uses the right=handed carthesian coordinate system.
/// @note This implementation intentionally avoids the use of x and y
struct Vector2 : Vec2 {
friend struct Vec2;
public:
/// @brief A new 2-dimensional zero vector
Vector2();
/// @brief A new 2-dimensional vector
/// @param right The distance in the right direction in meters
/// @param forward The distance in the forward direction in meters
Vector2(float right, float forward);
/// @brief Convert a Vector3 to a Vector2
/// @param v The 3D vector
/// @note This will project the vector to the horizontal plane
Vector2(Vector3 v);
/// @brief Convert a Polar vector to a 2-dimensional vector
/// @param v The vector in polar coordinates
Vector2(PolarOf<float> v);
/// @brief Vector2 destructor
~Vector2();
/// @brief A vector with zero for all axis
const static Vector2 zero;
/// @brief A vector with one for all axis
const static Vector2 one;
/// @brief A normalized forward-oriented vector
const static Vector2 forward;
/// @brief A normalized back-oriented vector
const static Vector2 back;
/// @brief A normalized right-oriented vector
const static Vector2 right;
/// @brief A normalized left-oriented vector
const static Vector2 left;
/// @brief A normalized up-oriented vector
/// @note This is a convenience function which is equal to Vector2::forward
const static Vector2 up;
/// @brief A normalized down-oriented vector
/// @note This is a convenience function which is equal to Vector2::down
const static Vector2 down;
/// @brief Check if this vector to the given 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 Vector2& v);
/// @brief The vector length
/// @param v The vector for which you need the length
/// @return The vector length
static float Magnitude(const Vector2& v);
/// @brief The vector length
/// @return The vector length
float magnitude() const;
/// @brief The squared vector length
/// @param v The vector for which you need the squared length
/// @return The squared vector length
/// @remark The squared length is computationally simpler than the real
/// length. Think of Pythagoras A^2 + B^2 = C^2. This prevents the calculation
/// of the squared root of C.
static float SqrMagnitude(const Vector2& v);
/// @brief The squared vector length
/// @return The squared vector length
/// @remark The squared length is computationally simpler than the real
/// length. Think of Pythagoras A^2 + B^2 = C^2. This prevents the calculation
/// of the squared root of C.
float sqrMagnitude() const;
/// @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 Vector2 Normalize(const Vector2& v);
/// @brief Convert the vector to a length 1
/// @return The vector normalized to a length of 1
Vector2 normalized() const;
/// @brief Negate the vector such that it points in the opposite direction
/// @return The negated vector
Vector2 operator-();
/// @brief Subtract a vector from this vector
/// @param v The vector to subtract from this vector
/// @return The result of the subtraction
Vector2 operator-(const Vector2& v) const;
Vector2 operator-=(const Vector2& v);
/// @brief Add a vector to this vector
/// @param v The vector to add to this vector
/// @return The result of the addition
Vector2 operator+(const Vector2& v) const;
Vector2 operator+=(const Vector2& v);
/// @brief Scale the vector using another vector
/// @param v1 The vector to scale
/// @param v2 A vector with the scaling factors
/// @return The scaled vector
/// @remark Each component of the vector v1 will be multiplied with the
/// matching component from the scaling vector v2.
static Vector2 Scale(const Vector2& v1, const Vector2& v2);
/// @brief Scale the vector uniformly up
/// @param f The scaling factor
/// @return The scaled vector
/// @remark Each component of the vector will be multipled with the same
/// factor f.
friend Vector2 operator*(const Vector2& v, float f) {
return Vector2(v.x * f, v.y * f);
}
friend Vector2 operator*(float f, const Vector2& v) {
return Vector2(v.x * f, v.y * f);
// return Vector2(f * v.x, f * v.y);
}
Vector2 operator*=(float f);
/// @brief Scale the vector uniformly down
/// @param f The scaling factor
/// @return The scaled vector
/// @remark Each componet of the vector will be divided by the same factor.
friend Vector2 operator/(const Vector2& v, float f) {
return Vector2(v.x / f, v.y / f);
}
friend Vector2 operator/(float f, const Vector2& v) {
return Vector2(f / v.x, f / v.y);
}
Vector2 operator/=(float f);
/// @brief The dot product of two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The dot product of the two vectors
static float Dot(const Vector2& v1, const Vector2& v2);
/// @brief The distance between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The distance between the two vectors
static float Distance(const Vector2& v1, const Vector2& v2);
/// @brief The angle between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The angle between the two vectors
/// @remark This reterns an unsigned angle which is the shortest distance
/// between the two vectors. Use Vector2::SignedAngle if a signed angle is
/// needed.
static float Angle(const Vector2& v1, const Vector2& v2);
/// @brief The signed angle between two vectors
/// @param v1 The starting vector
/// @param v2 The ending vector
/// @return The signed angle between the two vectors
static float SignedAngle(const Vector2& v1, const Vector2& v2);
/// @brief Rotate the vector
/// @param v The vector to rotate
/// @param a The angle in degrees to rotate
/// @return The rotated vector
static Vector2 Rotate(const Vector2& v, Passer::LinearAlgebra::Angle a);
/// @brief Lerp (linear interpolation) between two vectors
/// @param v1 The starting vector
/// @param v2 The end vector
/// @param f The interpolation distance
/// @return The lerped vector
/// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value
/// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference
/// between *v1* and *v2* etc.
static Vector2 Lerp(const Vector2& v1, const Vector2& v2, float f);
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#include "Polar.h"
#endif

224
LinearAlgebra/Vector3.cpp Normal file
View File

@ -0,0 +1,224 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Vector3.h"
#include "Angle.h"
#include "Spherical.h"
#include <math.h>
const float Deg2Rad = 0.0174532924F;
const float Rad2Deg = 57.29578F;
const float epsilon = 1E-05f;
Vector3::Vector3() {
this->x = 0;
this->y = 0;
this->z = 0;
}
Vector3::Vector3(float right, float up, float forward) {
this->x = right;
this->y = up;
this->z = forward;
}
Vector3::Vector3(Vector2 v) {
this->x = v.x;
this->y = 0.0f;
this->z = v.y;
}
Vector3::Vector3(Spherical s) {
float verticalRad =
(90.0f - s.vertical.ToFloat()) * Passer::LinearAlgebra::Deg2Rad;
float horizontalRad = s.horizontal.ToFloat() * Passer::LinearAlgebra::Deg2Rad;
float cosVertical = cosf(verticalRad);
float sinVertical = sinf(verticalRad);
float cosHorizontal = cosf(horizontalRad);
float sinHorizontal = sinf(horizontalRad);
x = s.distance * sinVertical * sinHorizontal;
y = s.distance * cosVertical;
z = s.distance * sinVertical * cosHorizontal;
// Vector3 v = Vector3(s.distance * sinVertical * sinHorizontal,
// s.distance * cosVertical,
// );
// return v;
}
Vector3::~Vector3() {}
const Vector3 Vector3::zero = Vector3(0, 0, 0);
const Vector3 Vector3::one = Vector3(1, 1, 1);
const Vector3 Vector3::right = Vector3(1, 0, 0);
const Vector3 Vector3::left = Vector3(-1, 0, 0);
const Vector3 Vector3::up = Vector3(0, 1, 0);
const Vector3 Vector3::down = Vector3(0, -1, 0);
const Vector3 Vector3::forward = Vector3(0, 0, 1);
const Vector3 Vector3::back = Vector3(0, 0, -1);
// inline float Vector3::Forward() { return z; }
// inline float Vector3::Up() { return y; }
// inline float Vector3::Right() { return x; }
// Vector3 Vector3::FromHorizontal(const Vector2 &v) {
// return Vector3(v.x, 0, v.y);
// }
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::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);
}
Vector3 Vector3::Normalize(const Vector3& v) {
float num = Vector3::Magnitude(v);
Vector3 result = Vector3::zero;
if (num > epsilon) {
result = v / num;
}
return result;
}
Vector3 Vector3::normalized() const {
float num = this->magnitude();
Vector3 result = Vector3::zero;
if (num > epsilon) {
result = ((Vector3) * this) / num;
}
return result;
}
Vector3 Vector3::operator-() const {
return Vector3(-this->x, -this->y, -this->z);
}
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) {
this->x -= v.x;
this->y -= v.y;
this->z -= v.z;
return *this;
}
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) {
this->x += v.x;
this->y += v.y;
this->z += v.z;
return *this;
}
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) {
// return Vector3(v.x * f, v.y * f, v.z * f);
// }
// Vector3 Passer::LinearAlgebra::operator*(float f, const Vector3 &v) {
// return Vector3(v.x * f, v.y * f, v.z * f);
// }
Vector3 Vector3::operator*=(float f) {
this->x *= f;
this->y *= f;
this->z *= f;
return *this;
}
// Vector3 Passer::LinearAlgebra::operator/(const Vector3 &v, float f) {
// return Vector3(v.x / f, v.y / f, v.z / f);
// }
// Vector3 Passer::LinearAlgebra::operator/(float f, const Vector3 &v) {
// return Vector3(v.x / f, v.y / f, v.z / f);
// }
Vector3 Vector3::operator/=(float f) {
this->x /= f;
this->y /= f;
this->z /= f;
return *this;
}
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) {
return (this->x == v.x && this->y == v.y && this->z == v.z);
}
float Vector3::Distance(const Vector3& v1, const Vector3& v2) {
return Magnitude(v1 - 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) {
float sqrMagnitude = Dot(n, n);
if (sqrMagnitude < epsilon)
return Vector3::zero;
else {
float dot = Dot(v, n);
Vector3 r = n * dot / sqrMagnitude;
return r;
}
}
Vector3 Vector3::ProjectOnPlane(const Vector3& v, const Vector3& n) {
Vector3 r = v - Project(v, n);
return r;
}
float clamp(float x, float lower, float upper) {
float lowerClamp = fmaxf(x, lower);
float upperClamp = fminf(upper, lowerClamp);
return upperClamp;
}
AngleOf<float> Vector3::Angle(const Vector3& v1, const Vector3& v2) {
float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude());
if (denominator < epsilon)
return 0;
float dot = Vector3::Dot(v1, v2);
float fraction = dot / denominator;
if (isnan(fraction))
return fraction; // short cut to returning NaN universally
float cdot = clamp(fraction, -1.0, 1.0);
float r = ((float)acos(cdot)) * Rad2Deg;
return AngleOf<float>(r);
}
AngleOf<float> Vector3::SignedAngle(const Vector3& v1,
const Vector3& v2,
const Vector3& axis) {
// angle in [0,180]
AngleOf<float> angle = Vector3::Angle(v1, v2);
Vector3 cross = Vector3::Cross(v1, v2);
float b = Vector3::Dot(axis, cross);
float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F);
// angle in [-179,180]
AngleOf<float> signed_angle = angle * signd;
return AngleOf<float>(signed_angle);
}
Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) {
Vector3 v = v1 + (v2 - v1) * f;
return v;
}

236
LinearAlgebra/Vector3.h Normal file
View File

@ -0,0 +1,236 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#ifndef VECTOR3_H
#define VECTOR3_H
#include "Vector2.h"
namespace Passer {
namespace LinearAlgebra {
// struct Spherical;
template <typename T>
class SphericalOf;
extern "C" {
/// <summary>
/// 3-dimensional Vector representation
/// </summary>
/// This is a C-style implementation
/// This uses the right-handed coordinate system.
typedef struct Vec3 {
protected:
/// <summary>
/// The right axis of the vector
/// </summary>
float x;
/// <summary>
/// The upward axis of the vector
/// </summary>
float y;
/// <summary>
/// The forward axis of the vector
/// </summary>
float z;
} Vec3;
}
/// @brief A 3-dimensional vector
/// @remark This uses a right-handed carthesian coordinate system.
/// @note This implementation intentionally avoids the use of x, y and z values.
struct Vector3 : Vec3 {
friend struct Vec3;
public:
/// @brief A new 3-dimensional zero vector
Vector3();
/// @brief A new 3-dimensional vector
/// @param right The distance in the right direction in meters
/// @param up The distance in the upward direction in meters
/// @param forward The distance in the forward direction in meters
Vector3(float right, float up, float forward);
/// @brief Convert a 2-dimenstional vector to a 3-dimensional vector
/// @param v The vector to convert
Vector3(Vector2 v);
/// @brief Convert vector in spherical coordinates to 3d carthesian
/// coordinates
/// @param v The vector to convert
Vector3(SphericalOf<float> v);
/// @brief Vector3 destructor
~Vector3();
/// @brief A vector with zero for all axis
const static Vector3 zero;
/// @brief A vector with one for all axis
const static Vector3 one;
/// @brief A normalized forward-oriented vector
const static Vector3 forward;
/// @brief A normalized back-oriented vector
const static Vector3 back;
/// @brief A normalized right-oriented vector
const static Vector3 right;
/// @brief A normalized left-oriented vector
const static Vector3 left;
/// @brief A normalized up-oriented vector
const static Vector3 up;
/// @brief A normalized down-oriented vector
const static Vector3 down;
// Access functions which are intended to replace the use of XYZ
inline float Forward() const { return z; };
inline float Up() const { return y; };
inline float Right() const { return x; };
/// @brief Check if this vector to the given 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 Vector3& v);
/// @brief The vector length
/// @param v The vector for which you need the length
/// @return The vector length
static float Magnitude(const Vector3& v);
/// @brief The vector length
/// @return The vector length
float magnitude() const;
/// @brief The squared vector length
/// @param v The vector for which you need the length
/// @return The squared vector length
/// @remark The squared length is computationally simpler than the real
/// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the
/// calculation of the squared root of C.
static float SqrMagnitude(const Vector3& v);
/// @brief The squared vector length
/// @return The squared vector length
/// @remark The squared length is computationally simpler than the real
/// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the
/// calculation of the squared root of C.
float sqrMagnitude() const;
/// @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 Vector3 Normalize(const Vector3& v);
/// @brief Convert the vector to a length of 1
/// @return The vector normalized to a length of 1
Vector3 normalized() const;
/// @brief Negate te vector such that it points in the opposite direction
/// @return The negated vector
Vector3 operator-() const;
/// @brief Subtract a vector from this vector
/// @param v The vector to subtract from this vector
/// @return The result of this subtraction
Vector3 operator-(const Vector3& v) const;
Vector3 operator-=(const Vector3& v);
/// @brief Add a vector to this vector
/// @param v The vector to add to this vector
/// @return The result of the addition
Vector3 operator+(const Vector3& v) const;
Vector3 operator+=(const Vector3& v);
/// @brief Scale the vector using another vector
/// @param v1 The vector to scale
/// @param v2 A vector with the scaling factors
/// @return The scaled vector
/// @remark Each component of the vector v1 will be multiplied with the
/// matching component from the scaling vector v2.
static Vector3 Scale(const Vector3& v1, const Vector3& v2);
/// @brief Scale the vector uniformly up
/// @param f The scaling factor
/// @return The scaled vector
/// @remark Each component of the vector will be multipled with the same
/// factor f.
friend Vector3 operator*(const Vector3& v, float f) {
return Vector3(v.x * f, v.y * f, v.z * f);
}
friend Vector3 operator*(float f, const Vector3& v) {
// return Vector3(f * v.x, f * v.y, f * v.z);
return Vector3(v.x * f, v.y * f, v.z * f);
}
Vector3 operator*=(float f);
/// @brief Scale the vector uniformly down
/// @param f The scaling factor
/// @return The scaled vector
/// @remark Each componet of the vector will be divided by the same factor.
friend Vector3 operator/(const Vector3& v, float f) {
return Vector3(v.x / f, v.y / f, v.z / f);
}
friend Vector3 operator/(float f, const Vector3& v) {
// return Vector3(f / v.x, f / v.y, f / v.z);
return Vector3(v.x / f, v.y / f, v.z / f);
}
Vector3 operator/=(float f);
/// @brief The distance between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The distance between the two vectors
static float Distance(const Vector3& v1, const Vector3& v2);
/// @brief The dot product of two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The dot product of the two vectors
static float Dot(const Vector3& v1, const Vector3& v2);
/// @brief The cross product of two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The cross product of the two vectors
static Vector3 Cross(const Vector3& v1, const Vector3& v2);
/// @brief Project the vector on another vector
/// @param v The vector to project
/// @param n The normal vecto to project on
/// @return The projected vector
static Vector3 Project(const Vector3& v, const Vector3& n);
/// @brief Project the vector on a plane defined by a normal orthogonal to the
/// plane.
/// @param v The vector to project
/// @param n The normal of the plane to project on
/// @return Teh projected vector
static Vector3 ProjectOnPlane(const Vector3& v, const Vector3& n);
/// @brief The angle between two vectors
/// @param v1 The first vector
/// @param v2 The second vector
/// @return The angle between the two vectors
/// @remark This reterns an unsigned angle which is the shortest distance
/// between the two vectors. Use Vector3::SignedAngle if a signed angle is
/// needed.
static AngleOf<float> Angle(const Vector3& v1, const Vector3& v2);
/// @brief The signed angle between two vectors
/// @param v1 The starting vector
/// @param v2 The ending vector
/// @param axis The axis to rotate around
/// @return The signed angle between the two vectors
static AngleOf<float> SignedAngle(const Vector3& v1,
const Vector3& v2,
const Vector3& axis);
/// @brief Lerp (linear interpolation) between two vectors
/// @param v1 The starting vector
/// @param v2 The ending vector
/// @param f The interpolation distance
/// @return The lerped vector
/// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value
/// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference
/// between *v1* and *v2* etc.
static Vector3 Lerp(const Vector3& v1, const Vector3& v2, float f);
};
} // namespace LinearAlgebra
} // namespace Passer
using namespace Passer::LinearAlgebra;
#include "Spherical.h"
#endif

View File

@ -0,0 +1 @@
COMPONENT_ADD_INCLUDEDIRS = .

View File

View File

@ -0,0 +1,168 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Angle.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Angle, Normalize) {
Angle r = 0;
r = Angle::Normalize(90.0f);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize 90";
r = Angle::Normalize(-90);
EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize -90";
r = Angle::Normalize(270);
EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize 270";
r = Angle::Normalize(270 + 360);
EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Normalize 270+360";
r = Angle::Normalize(-270);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize -270";
r = Angle::Normalize(-270 - 360);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Normalize -270-360";
r = Angle::Normalize(0);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Normalize 0";
if (std::numeric_limits<float>::is_iec559) {
r = Angle::Normalize(FLOAT_INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), FLOAT_INFINITY) << "Normalize INFINITY";
r = Angle::Normalize(-FLOAT_INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), -FLOAT_INFINITY) << "Normalize INFINITY";
}
}
TEST(Angle, Clamp) {
Angle r = 0;
r = Angle::Clamp(1, 0, 2);
EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 0 2";
r = Angle::Clamp(-1, 0, 2);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp -1 0 2";
r = Angle::Clamp(3, 0, 2);
EXPECT_FLOAT_EQ(r.ToFloat(), 2) << "Clamp 3 0 2";
r = Angle::Clamp(1, 0, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp 1 0 0";
r = Angle::Clamp(0, 0, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Clamp 0 0 0";
r = Angle::Clamp(0, 1, -1);
EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 0 1 -1";
if (std::numeric_limits<float>::is_iec559) {
r = Angle::Clamp(1, 0, FLOAT_INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 0 INFINITY";
r = Angle::Clamp(1, -FLOAT_INFINITY, 1);
EXPECT_FLOAT_EQ(r.ToFloat(), 1) << "Clamp 1 -INFINITY 1";
}
}
TEST(Angle, Difference) {
Angle r = 0;
r = Angle::Difference(0, 90);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference 0 90";
r = Angle::Difference(0, -90);
EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 0 -90";
r = Angle::Difference(0, 270);
EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 0 270";
r = Angle::Difference(0, -270);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference 0 -270";
r = Angle::Difference(90, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), -90) << "Difference 90 0";
r = Angle::Difference(-90, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "Difference -90 0";
r = Angle::Difference(0, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Difference 0 0";
r = Angle::Difference(90, 90);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "Difference 90 90";
if (std::numeric_limits<float>::is_iec559) {
r = Angle::Difference(0, INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), INFINITY) << "Difference 0 INFINITY";
r = Angle::Difference(0, -INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), -INFINITY) << "Difference 0 -INFINITY";
r = Angle::Difference(-INFINITY, INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), INFINITY) << "Difference -INFINITY INFINITY";
}
}
TEST(Angle, MoveTowards) {
Angle r = 0;
r = Angle::MoveTowards(0, 90, 30);
EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 90 30";
r = Angle::MoveTowards(0, 90, 90);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 90";
r = Angle::MoveTowards(0, 90, 180);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 180";
r = Angle::MoveTowards(0, 90, 270);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 270";
r = Angle::MoveTowards(0, 90, -30);
EXPECT_FLOAT_EQ(r.ToFloat(), -30) << "MoveTowards 0 90 -30";
r = Angle::MoveTowards(0, -90, -30);
EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 -90 -30";
r = Angle::MoveTowards(0, -90, -90);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 -90 -90";
r = Angle::MoveTowards(0, -90, -180);
EXPECT_FLOAT_EQ(r.ToFloat(), 180) << "MoveTowards 0 -90 -180";
r = Angle::MoveTowards(0, -90, -270);
EXPECT_FLOAT_EQ(r.ToFloat(), 270) << "MoveTowards 0 -90 -270";
r = Angle::MoveTowards(0, 90, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 90 0";
r = Angle::MoveTowards(0, 0, 0);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 0 0";
r = Angle::MoveTowards(0, 0, 30);
EXPECT_FLOAT_EQ(r.ToFloat(), 0) << "MoveTowards 0 0 30";
if (std::numeric_limits<float>::is_iec559) {
r = Angle::MoveTowards(0, 90, FLOAT_INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), 90) << "MoveTowards 0 90 FLOAT_INFINITY";
r = Angle::MoveTowards(0, FLOAT_INFINITY, 30);
EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 FLOAT_INFINITY 30";
r = Angle::MoveTowards(0, -90, -FLOAT_INFINITY);
EXPECT_FLOAT_EQ(r.ToFloat(), FLOAT_INFINITY)
<< "MoveTowards 0 -90 -FLOAT_INFINITY";
r = Angle::MoveTowards(0, -FLOAT_INFINITY, -30);
EXPECT_FLOAT_EQ(r.ToFloat(), 30) << "MoveTowards 0 -FLOAT_INFINITY -30";
}
}
#endif

View File

@ -0,0 +1,79 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Angle16.h"
#include "Angle8.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Angle8, Construct) {
float angle = 0.0F;
Angle8 a = Angle8(angle);
EXPECT_FLOAT_EQ(a.ToFloat(), angle);
angle = -180.0F;
a = Angle8(angle);
EXPECT_FLOAT_EQ(a.ToFloat(), angle);
}
TEST(Angle8, Negate) {
float angle = 0;
Angle8 a = Angle8(angle);
a = -a;
EXPECT_FLOAT_EQ(a.ToFloat(), angle);
angle = 90.0F;
a = Angle8(angle);
a = -a;
EXPECT_FLOAT_EQ(a.ToFloat(), -angle);
}
TEST(Angle8, Add) {
Angle8 a = Angle8(-45);
Angle8 b = Angle8(45.0F);
Angle8 r = a + b;
EXPECT_FLOAT_EQ(r.ToFloat(), 0);
}
TEST(Angle8, Subtract) {
Angle8 a = Angle8(0);
Angle8 b = Angle8(45.0F);
Angle8 r = a - b;
EXPECT_FLOAT_EQ(r.ToFloat(), -45);
}
TEST(Angle16, Construct) {
Angle16 a = Angle16(0.0F);
EXPECT_FLOAT_EQ(a.ToFloat(), 0);
}
TEST(Angle16, Negate) {
float angle = 0;
Angle16 a = Angle16(angle);
a = -a;
EXPECT_FLOAT_EQ(a.ToFloat(), angle);
angle = 90.0F;
a = Angle16(angle);
a = -a;
EXPECT_FLOAT_EQ(a.ToFloat(), -angle);
}
TEST(Angle16, Subtract) {
Angle16 a = Angle16(0);
Angle16 b = Angle16(45.0F);
Angle16 r = a - b;
EXPECT_FLOAT_EQ(r.ToFloat(), -45);
}
TEST(Angle16, Add) {
Angle16 a = Angle16(-45);
Angle16 b = Angle16(45.0F);
Angle16 r = a + b;
EXPECT_FLOAT_EQ(r.ToFloat(), 0);
}
#endif

View File

@ -0,0 +1,41 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "FloatSingle.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(FloatC, Clamp) {
float r = 0;
r = Float::Clamp(1, 0, 2);
EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 2";
r = Float::Clamp(-1, 0, 2);
EXPECT_FLOAT_EQ(r, 0) << "Clamp -1 0 2";
r = Float::Clamp(3, 0, 2);
EXPECT_FLOAT_EQ(r, 2) << "Clamp 3 0 2";
r = Float::Clamp(1, 0, 0);
EXPECT_FLOAT_EQ(r, 0) << "Clamp 1 0 0";
r = Float::Clamp(0, 0, 0);
EXPECT_FLOAT_EQ(r, 0) << "Clamp 0 0 0";
r = Float::Clamp(0, 1, -1);
EXPECT_FLOAT_EQ(r, 1) << "Clamp 0 1 -1";
if (std::numeric_limits<float>::is_iec559) {
r = Float::Clamp(1, 0, FLOAT_INFINITY);
EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 0 INFINITY";
r = Float::Clamp(1, -FLOAT_INFINITY, 1);
EXPECT_FLOAT_EQ(r, 1) << "Clamp 1 -INFINITY 1";
}
}
#endif

View File

@ -0,0 +1,135 @@
#if GTEST
#include <gtest/gtest.h>
#include <limits>
#include <math.h>
#include "Matrix.h"
TEST(MatrixSingle, Init) {
// zero
MatrixOf<float> m0 = MatrixOf<float>(0, 0);
// one
float data1[] = {1.0F};
MatrixOf<float> m1 = MatrixOf<float>(1, 1, data1);
// two
float data2[] = {1.0F, 2.0F, 3.0F, 4.0F};
MatrixOf<float> m2 = MatrixOf<float>(2, 2, data2);
// negative
// MatrixOf<float> m_1 = MatrixOf<float>(-1, -1);
// parameters are unsigned
}
TEST(MatrixSingle, Transpose) {
float data1[] = {1.0F};
MatrixOf<float> m = MatrixOf<float>(1, 1, data1);
MatrixOf<float> r = MatrixOf<float>(1, 1);
m.Transpose(&r);
// 2 x 2
float data3[] = {1.0F, 2.0F, 3.0F, 4.0F};
MatrixOf<float> m22 = MatrixOf<float>(2, 2, data3);
EXPECT_EQ(m22.RowCount(), 2);
EXPECT_EQ(m22.ColCount(), 2);
float data4[] = {0.0F, 0.0F, 0.0F, 0.0F};
MatrixOf<float> r22 = MatrixOf<float>(2, 2, data4);
EXPECT_EQ(r22.RowCount(), 2);
EXPECT_EQ(r22.ColCount(), 2);
m22.Transpose(&r22);
EXPECT_EQ(r22.RowCount(), 2);
EXPECT_EQ(r22.ColCount(), 2);
EXPECT_FLOAT_EQ(r22.Get(0, 0), 1.0F);
EXPECT_FLOAT_EQ(r22.Get(0, 1), 3.0F);
EXPECT_FLOAT_EQ(r22.Get(1, 0), 2.0F);
EXPECT_FLOAT_EQ(r22.Get(1, 1), 4.0F);
// 1 x 2
float data12[] = {1.0F, 2.0F};
MatrixOf<float> m12 = MatrixOf<float>(1, 2, data12);
EXPECT_EQ(m12.RowCount(), 1);
EXPECT_EQ(m12.ColCount(), 2);
float data21[] = {0.0F, 0.0F};
MatrixOf<float> r21 = MatrixOf<float>(2, 1, data21);
EXPECT_EQ(r21.RowCount(), 2);
EXPECT_EQ(r21.ColCount(), 1);
m12.Transpose(&r21);
EXPECT_EQ(r21.RowCount(), 2);
EXPECT_EQ(r21.ColCount(), 1);
EXPECT_FLOAT_EQ(r21.Get(0, 0), 1.0F);
EXPECT_FLOAT_EQ(r21.Get(1, 0), 2.0F);
// changing dimensions, same size is okay
MatrixOf<float> r12 = MatrixOf<float>(1, 2, data21);
EXPECT_EQ(r12.RowCount(), 1);
EXPECT_EQ(r12.ColCount(), 2);
m12.Transpose(&r12);
EXPECT_EQ(r12.RowCount(), 2);
EXPECT_EQ(r12.ColCount(), 1);
EXPECT_FLOAT_EQ(r12.Get(0, 0), 1.0F);
EXPECT_FLOAT_EQ(r12.Get(0, 1), 2.0F);
}
TEST(MatrixSingle, Multiply) {
float m12data[] = {1.0F, 2.0F};
MatrixOf<float> m12 = MatrixOf<float>(1, 2, m12data);
EXPECT_EQ(m12.RowCount(), 1);
EXPECT_EQ(m12.ColCount(), 2);
EXPECT_FLOAT_EQ(m12.Get(0, 0), 1.0F);
EXPECT_FLOAT_EQ(m12.Get(0, 1), 2.0F);
float m21data[] = {3.0F, 4.0F};
MatrixOf<float> m21 = MatrixOf<float>(2, 1, m21data);
EXPECT_EQ(m21.RowCount(), 2);
EXPECT_EQ(m21.ColCount(), 1);
EXPECT_FLOAT_EQ(m21.Get(0, 0), 3.0F);
EXPECT_FLOAT_EQ(m21.Get(1, 0), 4.0F);
float r11data[] = {0.0F};
MatrixOf<float> r11 = MatrixOf<float>(1, 1, r11data);
EXPECT_EQ(r11.RowCount(), 1);
EXPECT_EQ(r11.ColCount(), 1);
MatrixOf<float>::Multiply(&m12, &m21, &r11);
EXPECT_EQ(r11.RowCount(), 1);
EXPECT_EQ(r11.ColCount(), 1);
EXPECT_FLOAT_EQ(r11.Get(0, 0), 11.0F);
float r22data[] = {0.0F, 0.0F, 0.0F, 0.0F};
MatrixOf<float> r22 = MatrixOf<float>(2, 2, r22data);
MatrixOf<float>::Multiply(&m21, &m12, &r22);
EXPECT_EQ(r22.RowCount(), 2);
EXPECT_EQ(r22.ColCount(), 2);
EXPECT_FLOAT_EQ(r22.Get(0, 0), 3.0F);
EXPECT_FLOAT_EQ(r22.Get(0, 1), 4.0F);
EXPECT_FLOAT_EQ(r22.Get(1, 0), 6.0F);
EXPECT_FLOAT_EQ(r22.Get(1, 1), 8.0F);
}
TEST(MatrixSingle, Multiply_Vector3) {
Vector3 v = Vector3(1.0, 2.0, 3.0);
Vector3 r = Vector3::zero;
// float m13data[] = {3.0, 4.0, 5.0};
// MatrixOf<float> m13 = MatrixOf<float>(1, 3, m13data);
// Vector3 r = MatrixOf<float>::Multiply(&m13, v);
float m33data[] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
MatrixOf<float> m33 = MatrixOf<float>(3, 3, m33data);
r = MatrixOf<float>::Multiply(&m33, v);
EXPECT_FLOAT_EQ(Vector3::Distance(r, Vector3(1.0f, 2.0f, 3.0f)), 0);
}
#endif

View File

@ -0,0 +1,173 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Polar.h"
#include "Spherical.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Polar, FromVector2) {
Vector2 v = Vector2(0, 1);
Polar p = Polar::FromVector2(v);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "s.angle 0 0 1";
v = Vector2(1, 0);
p = Polar::FromVector2(v);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 90.0F) << "s.angle 1 0";
v = Vector2(-1, 1);
p = Polar::FromVector2(v);
EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1";
EXPECT_NEAR(p.angle.ToFloat(), -45.0F, 1.0e-05) << "s.angle -1 1";
}
TEST(Polar, FromSpherical) {
Spherical s;
Polar p;
s = Spherical(1, 0, 0);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(1 0 0)";
s = Spherical(1, 45, 0);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 45.0F) << "p.angle FromSpherical(1 45 0)";
s = Spherical(1, -45, 0);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), -45.0F)
<< "p.angle FromSpherical(1 -45 0)";
s = Spherical(0, 0, 0);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 0)";
s = Spherical(-1, 0, 0);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 180.0F) << "p.angle FromSpherical(-1 0 0)";
s = Spherical(0, 0, 90);
p = Polar::FromSpherical(s);
EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)";
EXPECT_FLOAT_EQ(p.angle.ToFloat(), 0.0F) << "p.angle FromSpherical(0 0 90)";
}
TEST(Polar, Negation) {
Polar v = Polar(2, 45);
Polar r = Polar::zero;
r = -v;
EXPECT_FLOAT_EQ(r.distance, 2);
EXPECT_FLOAT_EQ(r.angle.ToFloat(), -135);
EXPECT_TRUE(r == Polar(2, -135)) << "Negate(2 45)";
v = Polar(2, -45);
r = -v;
EXPECT_TRUE(r == Polar(2, 135)) << "Negate(2 -45)";
v = Polar(2, 0);
r = -v;
EXPECT_TRUE(r == Polar(2, 180)) << "Negate(2 0)";
v = Polar(0, 0);
r = -v;
EXPECT_FLOAT_EQ(r.distance, 0.0f);
EXPECT_FLOAT_EQ(r.angle.ToFloat(), 0.0f);
EXPECT_TRUE(r == Polar(0, 0)) << "Negate(0 0)";
}
TEST(Polar, Subtraction) {
Polar v1 = Polar(4, 45);
Polar v2 = Polar(1, -90);
Polar r = Polar::zero;
r = v1 - v2;
// don't know what to expect yet
v2 = Polar::zero;
r = v1 - v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Subtraction(0 0)";
}
TEST(Polar, Addition) {
Polar v1 = Polar(1, 45);
Polar v2 = Polar(1, -90);
Polar r = Polar::zero;
r = v1 - v2;
// don't know what to expect yet
v2 = Polar::zero;
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)";
r = v1;
r += v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)";
v2 = Polar(1, -45);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)";
EXPECT_FLOAT_EQ(r.angle.ToFloat(), 0) << "Addition(0 0 0)";
}
TEST(Polar, Scale_Multiply) {
Polar v1 = Polar(4, 45);
Polar r = Polar::zero;
r = v1 * 2.0f;
EXPECT_FLOAT_EQ(r.distance, v1.distance * 2) << "ScaleMult(4 45, 2)";
EXPECT_FLOAT_EQ(r.angle.ToFloat(), v1.angle.ToFloat())
<< "ScaleMult(4 45, 2)";
}
TEST(Polar, Scale_Divide) {
Polar v1 = Polar(4, 45);
Polar r = Polar::zero;
r = v1 / 2.0f;
EXPECT_FLOAT_EQ(r.distance, v1.distance / 2) << "ScaleDiv(4 45, 2)";
EXPECT_FLOAT_EQ(r.angle.ToFloat(), v1.angle.ToFloat()) << "ScaleDiv(4 45, 2)";
}
TEST(Polar, Distance) {
Polar v1 = Polar(4, 45);
Polar v2 = Polar(1, -90);
float d = 0;
d = Polar::Distance(v1, v2);
// don't know what to expect yet
v2 = Polar::zero;
d = Polar::Distance(v1, v2);
EXPECT_FLOAT_EQ(d, v1.distance) << "Distance(4 45, zero)";
}
TEST(Polar, Rotate) {
Polar v = Polar(4, 45);
Polar r = Polar::zero;
r = Polar::Rotate(v, 45);
EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)";
EXPECT_FLOAT_EQ(r.angle.ToFloat(), 90.0f) << "Rotate(4 45, 45)";
}
#endif

View File

@ -0,0 +1,189 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Quaternion.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Quaternion, Normalize) {
bool r = false;
Quaternion q1 = Quaternion(0, 0, 0, 1);
Quaternion q = Quaternion::identity;
q = q1;
q.Normalize();
r = q == q1;
EXPECT_TRUE(r) << "q.Normalzed 0 0 0 1";
q = Quaternion::Normalize(q1);
r = q == q1;
EXPECT_TRUE(r) << "Quaternion::Normalize 0 0 0 1";
}
TEST(Quaternion, ToAngles) {
bool r = false;
Quaternion q1 = Quaternion(0, 0, 0, 1);
Vector3 v = Vector3::zero;
v = Quaternion::ToAngles(q1);
r = v == Vector3(0, 0, 0);
EXPECT_TRUE(r) << "Quaternion::ToAngles 0 0 0 1";
q1 = Quaternion(1, 0, 0, 0);
v = Quaternion::ToAngles(q1);
r = v == Vector3(180, 0, 0);
EXPECT_TRUE(r) << "Quaternion::ToAngles 1 0 0 0";
}
TEST(Quaternion, Multiplication) {
bool r = false;
Quaternion q1 = Quaternion(0, 0, 0, 1);
Quaternion q2 = Quaternion(1, 0, 0, 0);
Quaternion q = Quaternion::identity;
q = q1 * q2;
r = q == Quaternion(1, 0, 0, 0);
EXPECT_TRUE(r) << "0 0 0 1 * 1 0 0 0";
}
TEST(Quaternion, MultiplicationVector) {
bool r = false;
Quaternion q1 = Quaternion(0, 0, 0, 1);
Vector3 v1 = Vector3(0, 1, 0);
Vector3 v = Vector3::zero;
v = q1 * v1;
r = v == Vector3(0, 1, 0);
EXPECT_TRUE(r) << "0 0 0 1 * Vector 0 1 0";
q1 = Quaternion(1, 0, 0, 0);
v = q1 * v1;
r = v == Vector3(0, -1, 0);
EXPECT_TRUE(r) << "1 0 0 0 * Vector 0 1 0";
}
TEST(Quaternion, Equality) {
bool r = false;
Quaternion q1 = Quaternion(0, 0, 0, 1);
Quaternion q2 = Quaternion(1, 0, 0, 0);
r = q1 == q2;
EXPECT_FALSE(r) << " 0 0 0 1 == 1 0 0 0";
q2 = Quaternion(0, 0, 0, 1);
r = q1 == q2;
EXPECT_TRUE(r) << "0 0 0 1 == 0 0 0 1";
}
TEST(Quaternion, Inverse) {
}
TEST(Quaternion, LookRotation) {
}
TEST(Quaternion, FromToRotation) {
}
TEST(Quaternion, RotateTowards) {
}
TEST(Quaternion, AngleAxis) {
}
TEST(Quaternion, Angle) {
}
TEST(Quaternion, Slerp) {
}
TEST(Quaternion, SlerpUnclamped) {
}
TEST(Quaternion, Euler) {
bool r = false;
Vector3 v1 = Vector3(0, 0, 0);
Quaternion q = Quaternion::identity;
q = Quaternion::Euler(v1);
r = q == Quaternion::identity;
EXPECT_TRUE(r) << "Euler Vector 0 0 0";
q = Quaternion::Euler(0, 0, 0);
r = q == Quaternion::identity;
EXPECT_TRUE(r) << "Euler 0 0 0";
v1 = Vector3(90, 90, -90);
q = Quaternion::Euler(v1);
r = q == Quaternion(0, 0.707106709F, -0.707106709F, 0);
EXPECT_TRUE(r) << "Euler Vector 90 90 -90";
q = Quaternion::Euler(90, 90, -90);
r = q == Quaternion(0, 0.707106709F, -0.707106709F, 0);
EXPECT_TRUE(r) << "Euler 90 90 -90";
}
TEST(Quaternion, GetAngleAround) {
bool r = false;
Vector3 v1 = Vector3(0, 1, 0);
Quaternion q1 = Quaternion(0, 0, 0, 1);
float f;
f = Quaternion::GetAngleAround(v1, q1);
EXPECT_FLOAT_EQ(f, 0) << "GetAngleAround 0 1 0 , 0 0 0 1";
q1 = Quaternion(0, 0.707106709F, -0.707106709F, 0);
f = Quaternion::GetAngleAround(v1, q1);
EXPECT_FLOAT_EQ(f, 180) << "GetAngleAround 0 1 0 , 0 0.7 -0.7 0";
v1 = Vector3(0, 0, 0);
f = Quaternion::GetAngleAround(v1, q1);
r = isnan(f);
EXPECT_TRUE(r) << "GetAngleAround 0 0 0 , 0 0.7 -0.7 0";
}
TEST(Quaternion, GetRotationAround) {
bool r = false;
Vector3 v1 = Vector3(0, 1, 0);
Quaternion q1 = Quaternion(0, 0, 0, 1);
Quaternion q = Quaternion::identity;
q = Quaternion::GetRotationAround(v1, q1);
r = q == Quaternion::identity;
EXPECT_TRUE(r) << "GetRotationAround 0 1 0 , 0 0 0 1";
q1 = Quaternion(0, 0.707106709F, -0.707106709F, 0);
q = Quaternion::GetRotationAround(v1, q1);
r = q == Quaternion(0, 1, 0, 0);
EXPECT_TRUE(r) << "GetRotationAround 0 1 0 , 0 0.7 -0.7 0";
v1 = Vector3(0, 0, 0);
q = Quaternion::GetRotationAround(v1, q1);
r = isnan(q.x) && isnan(q.y) && isnan(q.z) && isnan(q.w);
EXPECT_TRUE(r) << "GetRotationAround 0 0 0 , 0 0.7 -0.7 0";
}
TEST(Quaternion, GetSwingTwist) {
}
TEST(Quaternion, Dot) {
}
#endif

View File

@ -0,0 +1,157 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Spherical.h"
#include "Vector3.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Spherical16, FromVector3) {
Vector3 v = Vector3(0, 0, 1);
Spherical16 s = Spherical16::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1";
EXPECT_FLOAT_EQ((float)s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1";
EXPECT_FLOAT_EQ((float)s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1";
v = Vector3(0, 1, 0);
s = Spherical16::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0";
v = Vector3(1, 0, 0);
s = Spherical16::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0";
}
// TEST(Spherical16, FromPolar) {
// Polar p = Polar(1, 0);
// Spherical16 s = Spherical16::FromPolar(p);
// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)";
// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)";
// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)";
// p = Polar(1, 45);
// s = Spherical16::FromPolar(p);
// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)";
// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)";
// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)";
// p = Polar(1, -45);
// s = Spherical16::FromPolar(p);
// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)";
// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)";
// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)";
// p = Polar(0, 0);
// s = Spherical16::FromPolar(p);
// EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)";
// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)";
// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)";
// p = Polar(-1, 0);
// s = Spherical16::FromPolar(p);
// EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)";
// EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -180.0F) << "s.hor Polar(-1 0)";
// EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)";
// }
TEST(Spherical16, Incident1) {
Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f);
Spherical16 s = Spherical16::FromVector3(v);
Spherical16 sr = Spherical16(2.49F, 98.18f, 24.4F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-01);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02);
Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3();
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0";
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0";
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0";
}
TEST(Spherical16, Incident2) {
Vector3 v = Vector3(1.0f, 0.0f, 1.0f);
Spherical16 s = Spherical16::FromVector3(v);
Spherical16 sr = Spherical16(1.4142135623F, 45.0f, 0.0F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-05);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05);
Vector3 r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3();
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06);
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
v = Vector3(0.0f, 1.0f, 1.0f);
s = Spherical16::FromVector3(v);
sr = Spherical16(1.4142135623F, 0.0f, 45.0F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-05);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05);
r = Spherical16(sr.distance, sr.horizontal, sr.vertical).ToVector3();
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06);
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
v = Vector3(1.0f, 1.0f, 1.0f);
s = Spherical16::FromVector3(v);
r = Spherical16(s.distance, s.horizontal, s.vertical).ToVector3();
EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02);
EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02);
EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04);
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-04);
// s = Spherical16(10, 45, 45);
// r = s.ToVector3();
// EXPECT_NEAR(r.x, 5, 1.0e-06);
// EXPECT_NEAR(r.y, 7.07, 1.0e-06);
// EXPECT_NEAR(r.z, 5, 1.0e-06);
}
TEST(Spherical16, Addition) {
Spherical16 v1 = Spherical16(1, 45, 0);
Spherical16 v2 = Spherical16::zero;
Spherical16 r = Spherical16::zero;
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)";
r = v1;
r += v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)";
v2 = Spherical16(1, -45, 0);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)";
v2 = Spherical16(1, 0, 90);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)";
}
#endif

View File

@ -0,0 +1,156 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Spherical.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Spherical, FromVector3) {
Vector3 v = Vector3(0, 0, 1);
Spherical s = Spherical::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 0 1";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 0 0 1";
v = Vector3(0, 1, 0);
s = Spherical::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor 0 1 0";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 90.0F) << "s.vert 0 1 0";
v = Vector3(1, 0, 0);
s = Spherical::FromVector3(v);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 90.0F) << "s.hor 1 0 0";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert 1 0 0";
}
TEST(Spherical, FromPolar) {
Polar p = Polar(1, 0);
Spherical s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(1 0)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 0)";
p = Polar(1, 45);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 45.0F) << "s.hor Polar(1 45)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 45)";
p = Polar(1, -45);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), -45.0F) << "s.hor Polar(1 -45)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(1 -45)";
p = Polar(0, 0);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 0.0F) << "s.hor Polar(0 0)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(0 0)";
p = Polar(-1, 0);
s = Spherical::FromPolar(p);
EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)";
EXPECT_FLOAT_EQ(s.horizontal.ToFloat(), 180.0F) << "s.hor Polar(-1 0)";
EXPECT_FLOAT_EQ(s.vertical.ToFloat(), 0.0F) << "s.vert Polar(-1 0)";
}
TEST(Spherical, Incident1) {
Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f);
Spherical s = Spherical::FromVector3(v);
Spherical sr = Spherical(2.49F, 98.18f, 24.4F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-01);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-02);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-02);
Vector3 r = Vector3(sr);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0";
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0";
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0";
}
TEST(Spherical, Incident2) {
Vector3 v = Vector3(1.0f, 0.0f, 1.0f);
Spherical s = Spherical::FromVector3(v);
Spherical sr = Spherical(1.4142135623F, 45.0f, 0.0F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-05);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05);
Vector3 r = Vector3(sr);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06);
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
v = Vector3(0.0f, 1.0f, 1.0f);
s = Spherical::FromVector3(v);
sr = Spherical(1.4142135623F, 0.0f, 45.0F);
EXPECT_NEAR(s.distance, sr.distance, 1.0e-05);
EXPECT_NEAR(s.horizontal.ToFloat(), sr.horizontal.ToFloat(), 1.0e-05);
EXPECT_NEAR(s.vertical.ToFloat(), sr.vertical.ToFloat(), 1.0e-05);
r = Vector3(sr);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06);
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
v = Vector3(1.0f, 1.0f, 1.0f);
s = Spherical::FromVector3(v);
r = Vector3(s);
EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02);
EXPECT_NEAR(s.horizontal.ToFloat(), 45.0F, 1.0e-02);
EXPECT_NEAR(s.vertical.ToFloat(), 35.26F, 1.0e-02);
EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06);
EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06);
EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06);
// s = Spherical(10, 45, 45);
// r = s.ToVector3();
// EXPECT_NEAR(r.x, 5, 1.0e-06);
// EXPECT_NEAR(r.y, 7.07, 1.0e-06);
// EXPECT_NEAR(r.z, 5, 1.0e-06);
}
TEST(Spherical, Addition) {
Spherical v1 = Spherical(1, 45, 0);
Spherical v2 = Spherical::zero;
Spherical r = Spherical::zero;
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)";
r = v1;
r += v2;
EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)";
v2 = Spherical(1, -45, 0);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 0) << "Addition(1 -45 0)";
EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 0) << "Addition(1 -45 0)";
v2 = Spherical(1, 0, 90);
r = v1 + v2;
EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.horizontal.ToFloat(), 45) << "Addition(1 0 90)";
EXPECT_FLOAT_EQ(r.vertical.ToFloat(), 45) << "Addition(1 0 90)";
}
#endif

View File

@ -0,0 +1,499 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Vector2.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Vector2, FromPolar) {
Vector2 v;
Polar p;
Vector2 r;
v = Vector2(0, 1);
p = Polar::FromVector2(v);
r = Vector2(p);
EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 1)";
EXPECT_FLOAT_EQ(r.y, 1.0F) << "FromPolar(0 1)";
v = Vector2(1, 0);
p = Polar::FromVector2(v);
r = Vector2(p);
EXPECT_FLOAT_EQ(r.x, 1.0F) << "FromPolar(1 0)";
EXPECT_NEAR(r.y, 0.0F, 1.0e-07) << "FromPolar(1 0)";
v = Vector2(0, 0);
p = Polar::FromVector2(v);
r = Vector2(p);
EXPECT_FLOAT_EQ(r.x, 0.0F) << "FromPolar(0 0)";
EXPECT_FLOAT_EQ(r.y, 0.0F) << "FromPolar(0 0)";
}
TEST(Vector2, Magnitude) {
Vector2 v = Vector2(1, 2);
float m = 0;
m = v.magnitude();
EXPECT_FLOAT_EQ(m, 2.236068F) << "v.magnitude 1 2";
m = Vector2::Magnitude(v);
EXPECT_FLOAT_EQ(m, 2.236068F) << "Vector2::Magnitude 1 2";
v = Vector2(-1, -2);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, 2.236068F) << "v.magnitude -1 -2";
v = Vector2(0, 0);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, 0) << "v.magnitude 0 0 ";
if (std::numeric_limits<float>::is_iec559) {
v = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.magnitude INFINITY INFINITY ";
v = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.magnitude -INFINITY -INFINITY ";
}
}
TEST(Vector2, SqrMagnitude) {
Vector2 v = Vector2(1, 2);
float m = 0;
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, 5) << "v.sqrMagnitude 1 2";
m = Vector2::SqrMagnitude(v);
EXPECT_FLOAT_EQ(m, 5) << "Vector2::SqrMagnitude 1 2";
v = Vector2(-1, -2);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, 5) << "v.sqrMagnitude -1 -2";
v = Vector2(0, 0);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, 0) << "v.sqrMagnitude 0 0 ";
if (std::numeric_limits<float>::is_iec559) {
v = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.sqrMagnitude INFINITY INFINITY ";
v = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.sqrMagnitude -INFINITY -INFINITY ";
}
}
TEST(Vector2, Normalize) {
bool r = false;
Vector2 v1 = Vector2(0, 2);
Vector2 v = Vector2::zero;
v = v1.normalized();
EXPECT_TRUE(v == Vector2(0, 1)) << "v.normalized 0 2";
v = Vector2::Normalize(v1);
EXPECT_TRUE(v == Vector2(0, 1)) << "Vector3::Normalize 0 2";
v1 = Vector2(0, -2);
v = v1.normalized();
EXPECT_TRUE(v == Vector2(0, -1)) << "v.normalized 0 -2";
v1 = Vector2(0, 0);
v = v1.normalized();
EXPECT_TRUE(v == Vector2(0, 0)) << "v.normalized 0 0";
if (std::numeric_limits<float>::is_iec559) {
v1 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
v = v1.normalized();
r = isnan(v.x) && isnan(v.y);
EXPECT_TRUE(r) << "v.normalized INFINITY INFINITY";
v1 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
v = v1.normalized();
r = isnan(v.x) && isnan(v.y);
EXPECT_TRUE(r) << "v.normalized -INFINITY -INFINITY";
}
}
TEST(Vector2, Negate) {
Vector2 v1 = Vector2(4, 5);
Vector2 v = Vector2::zero;
v = -v1;
EXPECT_TRUE(v == Vector2(-4, -5)) << "- 4 5";
v1 = Vector2(-4, -5);
v = -v1;
EXPECT_TRUE(v == Vector2(4, 5)) << "- -4 -5";
v1 = Vector2(0, 0);
v = -v1;
EXPECT_TRUE(v == Vector2(0, 0)) << "- 0 0";
if (std::numeric_limits<float>::is_iec559) {
v1 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
v = -v1;
EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY))
<< "- INFINITY INFINITY";
v1 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
v = -v1;
EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY))
<< "- -INFINITY -INFINITY";
}
}
TEST(Vector2, Subtract) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
Vector2 v = Vector2::zero;
v = v1 - v2;
EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 - 1 2";
v2 = Vector2(-1, -2);
v = v1 - v2;
EXPECT_TRUE(v == Vector2(5, 7)) << "4 5 - -1 -2";
v2 = Vector2(4, 5);
v = v1 - v2;
EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5";
v = v1;
v -= v2;
EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5";
v2 = Vector2(0, 0);
v = v1 - v2;
EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0";
v -= v2;
EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
v = v1 - v2;
EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 - INFINITY INFINITY";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
v = v1 - v2;
EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 - -INFINITY -INFINITY";
}
}
TEST(Vector2, Addition) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
Vector2 v = Vector2::zero;
v = v1 + v2;
EXPECT_TRUE(v == Vector2(5, 7)) << "4 5 + 1 2";
v2 = Vector2(-1, -2);
v = v1 + v2;
EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2";
v = v1;
v += v2;
EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2";
v2 = Vector2(0, 0);
v = v1 + v2;
EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0";
v += v2;
EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
v = v1 + v2;
EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 + INFINITY INFINITY";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
v = v1 + v2;
EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 + -INFINITY -INFINITY";
}
}
TEST(Vector2, Scale) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
Vector2 v = Vector2::zero;
v = Vector2::Scale(v1, v2);
EXPECT_TRUE(v == Vector2(4, 10)) << "Scale 4 5 , 1 2";
v2 = Vector2(-1, -2);
v = Vector2::Scale(v1, v2);
EXPECT_TRUE(v == Vector2(-4, -10)) << "Scale 4 5 , -1 -2";
v2 = Vector2(0, 0);
v = Vector2::Scale(v1, v2);
EXPECT_TRUE(v == Vector2(0, 0)) << "Scale 4 5 , 0 0";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
v = Vector2::Scale(v1, v2);
EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 + INFINITY INFINITY";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
v = Vector2::Scale(v1, v2);
EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 + -INFINITY -INFINITY";
}
}
TEST(Vector2, Multiply) {
Vector2 v1 = Vector2(4, 5);
float f = 3;
Vector2 v = Vector2::zero;
v = v1 * f;
EXPECT_TRUE(v == Vector2(12, 15)) << "4 5 * 3";
f = -3;
v = v1 * f;
EXPECT_TRUE(v == Vector2(-12, -15)) << "4 5 * -3";
f = 0;
v = v1 * f;
EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 * 0";
if (std::numeric_limits<float>::is_iec559) {
f = FLOAT_INFINITY;
v = v1 * f;
EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 * INFINITY";
f = -FLOAT_INFINITY;
v = v1 * f;
EXPECT_TRUE(v == Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 * -INFINITY";
}
}
TEST(Vector2, Divide) {
Vector2 v1 = Vector2(4, 5);
float f = 2;
Vector2 v = Vector2::zero;
v = v1 / f;
EXPECT_TRUE(v == Vector2(2, 2.5F)) << "4 5 / 3";
f = -2;
v = v1 / f;
EXPECT_TRUE(v == Vector2(-2, -2.5F)) << "4 5 / -3";
if (std::numeric_limits<float>::is_iec559) {
f = 0;
v = v1 / f;
EXPECT_TRUE(v == Vector2(FLOAT_INFINITY, FLOAT_INFINITY)) << "4 5 / 0";
f = FLOAT_INFINITY;
v = v1 / f;
EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 / INFINITY";
f = -FLOAT_INFINITY;
v = v1 / f;
EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 / -INFINITY";
}
}
TEST(Vector2, Dot) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
float f = 0;
f = Vector2::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, 14) << "Dot(4 5, 1 2)";
v2 = Vector2(-1, -2);
f = Vector2::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, -14) << "Dot(4 5, -1 -2)";
v2 = Vector2(0, 0);
f = Vector2::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, 0) << "Dot(4 5, 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector2::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, FLOAT_INFINITY) << "Dot(4 5, INFINITY INFINITY)";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector2::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, -FLOAT_INFINITY) << "Dot(4 5, -INFINITY -INFINITY)";
}
}
TEST(Vector2, Equality) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
bool r = false;
r = v1 == v2;
EXPECT_FALSE(r) << "4 5 == 1 2";
v2 = Vector2(4, 5);
r = v1 == v2;
EXPECT_TRUE(r) << "4 5 == 1 2";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
r = v1 == v2;
EXPECT_FALSE(r) << "4 5 == INFINITY INFINITY";
v1 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
r = v1 == v2;
EXPECT_FALSE(r) << "-INFINITY -INFINITY == INFINITY INFINITY";
}
}
TEST(Vector2, Distance) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
float f = 0;
f = Vector2::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, 4.24264F) << "Distance(4 5, 1 2)";
v2 = Vector2(-1, -2);
f = Vector2::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, 8.602325F) << "Distance(4 5, -1 -2)";
v2 = Vector2(0, 0);
f = Vector2::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, 6.403124F) << "Distance(4 5, 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector2::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, FLOAT_INFINITY) << "Distance(4 5, INFINITY INFINITY)";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector2::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, FLOAT_INFINITY) << "Distance(4 5, -INFINITY -INFINITY)";
}
}
TEST(Vector2, Angle) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
float f = 0;
bool r = false;
f = Vector2::Angle(v1, v2);
EXPECT_FLOAT_EQ(f, 12.09476F) << "Angle(4 5, 1 2)";
v2 = Vector2(-1, -2);
f = Vector2::Angle(v1, v2);
EXPECT_FLOAT_EQ(f, 167.9052F) << "Angle(4 5, -1 -2)";
v2 = Vector2(0, 0);
f = Vector2::Angle(v1, v2);
EXPECT_FLOAT_EQ(f, 0) << "Angle(4 5, 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector2::Angle(v1, v2);
r = isnan(f);
EXPECT_TRUE(r) << "Angle(4 5, INFINITY INFINITY)";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector2::Angle(v1, v2);
r = isnan(f);
EXPECT_TRUE(r) << "Angle(4 5, -INFINITY -INFINITY)";
}
}
TEST(Vector2, SignedAngle) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
float f = 0;
bool r = false;
f = Vector2::SignedAngle(v1, v2);
EXPECT_FLOAT_EQ(f, -12.09476F) << "SignedAngle(4 5, 1 2)";
v2 = Vector2(-1, -2);
f = Vector2::SignedAngle(v1, v2);
EXPECT_FLOAT_EQ(f, 167.9052F) << "SignedAngle(4 5, -1 -2)";
v2 = Vector2(0, 0);
f = Vector2::SignedAngle(v1, v2);
EXPECT_FLOAT_EQ(f, 0) << "SignedAngle(4 5, 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector2::SignedAngle(v1, v2);
r = isnan(f);
EXPECT_TRUE(r) << "SignedAngle(4 5, INFINITY INFINITY)";
v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector2::SignedAngle(v1, v2);
r = isnan(f);
EXPECT_TRUE(r) << "SignedAngle(4 5, -INFINITY -INFINITY)";
}
v1 = Vector2(0, 1);
v2 = Vector2(1, 0);
f = Vector2::SignedAngle(v1, v2);
EXPECT_FLOAT_EQ(f, 90.0F) << "SignedAngle(0 1, 1 0)";
v1 = Vector2(0, 1);
v2 = Vector2(0, -1);
f = Vector2::SignedAngle(v1, v2);
EXPECT_FLOAT_EQ(f, 180.0F) << "SignedAngle(0 1, 1 0)";
}
TEST(Vector2, Rotate) {
Vector2 v1 = Vector2(1, 2);
Vector2 r = Vector2(0, 0);
r = Vector2::Rotate(v1, 0);
EXPECT_FLOAT_EQ(Vector2::Distance(r, v1), 0);
r = Vector2::Rotate(v1, 180);
EXPECT_NEAR(Vector2::Distance(r, Vector2(-1, -2)), 0, 1.0e-06);
r = Vector2::Rotate(v1, -90);
EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06);
r = Vector2::Rotate(v1, 270);
EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06);
}
TEST(Vector2, Lerp) {
Vector2 v1 = Vector2(4, 5);
Vector2 v2 = Vector2(1, 2);
Vector2 r = Vector2(0, 0);
r = Vector2::Lerp(v1, v2, 0);
EXPECT_FLOAT_EQ(Vector2::Distance(r, v1), 0);
r = Vector2::Lerp(v1, v2, 1);
EXPECT_FLOAT_EQ(Vector2::Distance(r, v2), 0);
r = Vector2::Lerp(v1, v2, 0.5f);
EXPECT_FLOAT_EQ(Vector2::Distance(r, Vector2(2.5f, 3.5f)), 0);
r = Vector2::Lerp(v1, v2, -1);
EXPECT_FLOAT_EQ(Vector2::Distance(r, Vector2(7.0f, 8.0f)), 0);
r = Vector2::Lerp(v1, v2, 2);
EXPECT_FLOAT_EQ(Vector2::Distance(r, Vector2(-2.0, -1.0f)), 0);
}
#endif

View File

@ -0,0 +1,583 @@
#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>
#include "Vector3.h"
#define FLOAT_INFINITY std::numeric_limits<float>::infinity()
TEST(Vector3, FromSpherical) {
Vector3 v = Vector3(0, 0, 1);
Spherical s = Spherical::FromVector3(v);
Vector3 r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1";
EXPECT_NEAR(r.Up(), 0.0F, 1.0e-06) << "toVector3.y 0 0 1";
EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1";
v = Vector3(0, 1, 0);
s = Spherical::FromVector3(v);
r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0";
EXPECT_FLOAT_EQ(r.Up(), 1.0F) << "toVector3.y 0 1 0";
EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0";
v = Vector3(1, 0, 0);
s = Spherical::FromVector3(v);
r = Vector3(s);
EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0";
EXPECT_NEAR(r.Up(), 0.0F, 1.0e-06) << "toVector3.y 1 0 0";
EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 1 0 0";
}
TEST(Vector3, Magnitude) {
Vector3 v = Vector3(1, 2, 3);
float m = 0;
m = v.magnitude();
EXPECT_FLOAT_EQ(m, 3.741657F) << "v.magnitude 1 2 3";
m = Vector3::Magnitude(v);
EXPECT_FLOAT_EQ(m, 3.741657F) << "Vector3::Magnitude 1 2 3";
v = Vector3(-1, -2, -3);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, 3.741657F) << "v.magnitude -1 -2 -3";
v = Vector3(0, 0, 0);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, 0) << "v.magnitude 0 0 0 ";
if (std::numeric_limits<float>::is_iec559) {
v = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY)
<< "v.magnitude INFINITY INFINITY INFINITY ";
v = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
m = v.magnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY)
<< "v.magnitude -INFINITY -INFINITY -INFINITY ";
}
}
TEST(Vector3, SqrMagnitude) {
Vector3 v = Vector3(1, 2, 3);
float m = 0;
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, 14) << "v.sqrMagnitude 1 2 3";
m = Vector3::SqrMagnitude(v);
EXPECT_FLOAT_EQ(m, 14) << "Vector3::SqrMagnitude 1 2 3";
v = Vector3(-1, -2, -3);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, 14) << "v.sqrMagnitude -1 -2 -3";
v = Vector3(0, 0, 0);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, 0) << "v.sqrMagnitude 0 0 0 ";
if (std::numeric_limits<float>::is_iec559) {
v = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY)
<< "v.sqrMagnitude INFINITY INFINITY INFINITY ";
v = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
m = v.sqrMagnitude();
EXPECT_FLOAT_EQ(m, FLOAT_INFINITY)
<< "v.sqrMagnitude -INFINITY -INFINITY -INFINITY ";
}
}
TEST(Vector3, Normalize) {
bool r = false;
Vector3 v1 = Vector3(0, 2, 0);
Vector3 v = Vector3::zero;
v = v1.normalized();
EXPECT_TRUE(v == Vector3(0, 1, 0)) << "v.normalized 0 2 0";
v = Vector3::Normalize(v1);
EXPECT_TRUE(v == Vector3(0, 1, 0)) << "Vector3::Normalize 0 2 0";
v1 = Vector3(0, -2, 0);
v = v1.normalized();
EXPECT_TRUE(v == Vector3(0, -1, 0)) << "v.normalized 0 -2 0";
v1 = Vector3(0, 0, 0);
v = v1.normalized();
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "v.normalized 0 0 0";
if (std::numeric_limits<float>::is_iec559) {
v1 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = v1.normalized();
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "v.normalized INFINITY INFINITY INFINITY";
v1 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = v1.normalized();
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "v.normalized -INFINITY -INFINITY -INFINITY";
}
}
TEST(Vector3, Negate) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v = Vector3::zero;
v = -v1;
EXPECT_TRUE(v == Vector3(-4, -5, -6)) << "- 4 5 6";
v1 = Vector3(-4, -5, -6);
v = -v1;
EXPECT_TRUE(v == Vector3(4, 5, 6)) << "- -4 -5 -6";
v1 = Vector3(0, 0, 0);
v = -v1;
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "- 0 0 0";
if (std::numeric_limits<float>::is_iec559) {
v1 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = -v1;
EXPECT_TRUE(v == Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY))
<< "- INFINITY INFINITY INFINITY";
v1 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = -v1;
EXPECT_TRUE(v == Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY))
<< "- -INFINITY -INFINITY -INFINITY";
}
}
TEST(Vector3, Subtract) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v = Vector3::zero;
v = v1 - v2;
EXPECT_TRUE(v == Vector3(3, 3, 3)) << "4 5 6 - 1 2 3";
v2 = Vector3(-1, -2, -3);
v = v1 - v2;
EXPECT_TRUE(v == Vector3(5, 7, 9)) << "4 5 6 - -1 -2 -3";
v2 = Vector3(4, 5, 6);
v = v1 - v2;
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "4 5 6 - 4 5 6";
v2 = Vector3(0, 0, 0);
v = v1 - v2;
EXPECT_TRUE(v == Vector3(4, 5, 6)) << "4 5 6 - 0 0 0";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = v1 - v2;
EXPECT_TRUE(v == Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 6 - INFINITY INFINITY INFINITY";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = v1 - v2;
EXPECT_TRUE(v == Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 6 - -INFINITY -INFINITY -INFINITY";
}
}
TEST(Vector3, Addition) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v = Vector3::zero;
v = v1 + v2;
EXPECT_TRUE(v == Vector3(5, 7, 9)) << "4 5 6 + 1 2 3";
v2 = Vector3(-1, -2, -3);
v = v1 + v2;
EXPECT_TRUE(v == Vector3(3, 3, 3)) << "4 5 6 + -1 -2 -3";
v2 = Vector3(0, 0, 0);
v = v1 + v2;
EXPECT_TRUE(v == Vector3(4, 5, 6)) << "4 5 6 + 0 0 0";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = v1 + v2;
EXPECT_TRUE(v == Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 6 + INFINITY INFINITY INFINITY";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = v1 + v2;
EXPECT_TRUE(v == Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 6 + -INFINITY -INFINITY -INFINITY";
}
}
TEST(Vector3, Scale) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v = Vector3::zero;
v = Vector3::Scale(v1, v2);
EXPECT_TRUE(v == Vector3(4, 10, 18)) << "Scale 4 5 6 , 1 2 3";
v2 = Vector3(-1, -2, -3);
v = Vector3::Scale(v1, v2);
EXPECT_TRUE(v == Vector3(-4, -10, -18)) << "Scale 4 5 6 , -1 -2 -3";
v2 = Vector3(0, 0, 0);
v = Vector3::Scale(v1, v2);
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "Scale 4 5 6 , 0 0 0";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = Vector3::Scale(v1, v2);
EXPECT_TRUE(v == Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 6 + INFINITY INFINITY INFINITY";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = Vector3::Scale(v1, v2);
EXPECT_TRUE(v == Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 6 + -INFINITY -INFINITY -INFINITY";
}
}
TEST(Vector3, Multiply) {
Vector3 v1 = Vector3(4, 5, 6);
float f = 3;
Vector3 v = Vector3::zero;
v = v1 * f;
EXPECT_TRUE(v == Vector3(12, 15, 18)) << "4 5 6 * 3";
f = -3;
v = v1 * f;
EXPECT_TRUE(v == Vector3(-12, -15, -18)) << "4 5 6 * -3";
f = 0;
v = v1 * f;
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "4 5 6 * 0";
if (std::numeric_limits<float>::is_iec559) {
f = FLOAT_INFINITY;
v = v1 * f;
EXPECT_TRUE(v == Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 6 * INFINITY";
f = -FLOAT_INFINITY;
v = v1 * f;
EXPECT_TRUE(v == Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY))
<< "4 5 6 * -INFINITY";
}
}
TEST(Vector3, Divide) {
Vector3 v1 = Vector3(4, 5, 6);
float f = 2;
Vector3 v = Vector3::zero;
v = v1 / f;
EXPECT_TRUE(v == Vector3(2, 2.5F, 3)) << "4 5 6 / 3";
f = -2;
v = v1 / f;
EXPECT_TRUE(v == Vector3(-2, -2.5F, -3)) << "4 5 6 / -3";
if (std::numeric_limits<float>::is_iec559) {
f = 0;
v = v1 / f;
EXPECT_TRUE(v == Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY))
<< "4 5 6 / 0";
f = FLOAT_INFINITY;
v = v1 / f;
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "4 5 6 / INFINITY";
f = -FLOAT_INFINITY;
v = v1 / f;
EXPECT_TRUE(v == Vector3(0, 0, 0)) << "4 5 6 / -INFINITY";
}
}
TEST(Vector3, Dot) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
float f = 0;
f = Vector3::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, 32) << "Dot(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3);
f = Vector3::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, -32) << "Dot(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0);
f = Vector3::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, 0) << "Dot(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector3::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, FLOAT_INFINITY)
<< "Dot(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector3::Dot(v1, v2);
EXPECT_FLOAT_EQ(f, -FLOAT_INFINITY)
<< "Dot(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, Equality) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
bool r = false;
r = v1 == v2;
EXPECT_FALSE(r) << "4 5 6 == 1 2 3";
v2 = Vector3(4, 5, 6);
r = v1 == v2;
EXPECT_TRUE(r) << "4 5 6 == 1 2 3";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
r = v1 == v2;
EXPECT_FALSE(r) << "4 5 6 == INFINITY INFINITY INFINITY";
v1 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
r = v1 == v2;
EXPECT_FALSE(r)
<< "-INFINITY -INFINITY -INFINITY == INFINITY INFINITY INFINITY";
}
}
TEST(Vector3, Distance) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
float f = 0;
f = Vector3::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, 5.19615221F) << "Distance(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3);
f = Vector3::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, 12.4498997F) << "Distance(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0);
f = Vector3::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, 8.77496433F) << "Distance(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector3::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, FLOAT_INFINITY)
<< "Distance(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector3::Distance(v1, v2);
EXPECT_FLOAT_EQ(f, FLOAT_INFINITY)
<< "Distance(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, Cross) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v = Vector3::zero;
bool r = false;
v = Vector3::Cross(v1, v2);
r = v == Vector3(3, -6, 3);
EXPECT_TRUE(r) << "Cross(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3);
v = Vector3::Cross(v1, v2);
r = v == Vector3(-3, 6, -3);
EXPECT_TRUE(r) << "Cross(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0);
v = Vector3::Cross(v1, v2);
r = v == Vector3(0, 0, 0);
EXPECT_TRUE(r) << "Cross(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = Vector3::Cross(v1, v2);
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "Cross(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = Vector3::Cross(v1, v2);
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "Cross(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, Project) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v = Vector3::zero;
bool r = false;
v = Vector3::Project(v1, v2);
r = v == Vector3(2.28571439F, 4.57142878F, 6.85714293F);
EXPECT_TRUE(r) << "Project(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3);
v = Vector3::Project(v1, v2);
r = v == Vector3(2.28571439F, 4.57142878F, 6.85714293F);
EXPECT_TRUE(r) << "Project(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0);
v = Vector3::Project(v1, v2);
r = v == Vector3(0, 0, 0);
EXPECT_TRUE(r) << "Project(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = Vector3::Project(v1, v2);
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "Project(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = Vector3::Project(v1, v2);
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "Project(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, ProjectOnPlane) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v = Vector3::zero;
bool r = false;
v = Vector3::ProjectOnPlane(v1, v2);
r = v == Vector3(1.71428561F, 0.428571224F, -0.857142925F);
EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3);
v = Vector3::ProjectOnPlane(v1, v2);
r = v == Vector3(1.71428561F, 0.428571224F, -0.857142925F);
EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0);
v = Vector3::ProjectOnPlane(v1, v2);
r = v == Vector3(4, 5, 6);
EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
v = Vector3::ProjectOnPlane(v1, v2);
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
v = Vector3::ProjectOnPlane(v1, v2);
r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward());
EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, Angle) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
AngleOf<float> f = 0;
bool r = false;
f = Vector3::Angle(v1, v2);
EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F) << "Angle(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3);
f = Vector3::Angle(v1, v2);
EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F) << "Angle(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0);
f = Vector3::Angle(v1, v2);
EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "Angle(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector3::Angle(v1, v2);
r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "Angle(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector3::Angle(v1, v2);
r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, SignedAngle) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 v3 = Vector3(7, 8, -9);
AngleOf<float> f = 0;
bool r = false;
f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f.ToFloat(), -12.9331388F)
<< "SignedAngle(4 5 6, 1 2 3, 7 8 -9)";
v2 = Vector3(-1, -2, -3);
f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F)
<< "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)";
v2 = Vector3(0, 0, 0);
f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )";
v2 = Vector3(1, 2, 3);
v3 = Vector3(-7, -8, 9);
f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F)
<< "SignedAngle(4 5 6, 1 2 3, -7 -8 9)";
v3 = Vector3(0, 0, 0);
f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector3::SignedAngle(v1, v2, v3);
r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "SignedAngle(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector3::SignedAngle(v1, v2, v3);
r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "SignedAngle(4 5 6, -INFINITY -INFINITY -INFINITY)";
}
}
TEST(Vector3, Lerp) {
Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3);
Vector3 r = Vector3(0, 0, 0);
r = Vector3::Lerp(v1, v2, 0);
EXPECT_FLOAT_EQ(Vector3::Distance(r, v1), 0);
r = Vector3::Lerp(v1, v2, 1);
EXPECT_FLOAT_EQ(Vector3::Distance(r, v2), 0);
r = Vector3::Lerp(v1, v2, 0.5f);
EXPECT_FLOAT_EQ(Vector3::Distance(r, Vector3(2.5f, 3.5f, 4.5f)), 0);
r = Vector3::Lerp(v1, v2, -1);
EXPECT_FLOAT_EQ(Vector3::Distance(r, Vector3(7.0f, 8.0f, 9.0f)), 0);
r = Vector3::Lerp(v1, v2, 2);
EXPECT_FLOAT_EQ(Vector3::Distance(r, Vector3(-2.0, -1.0f, 0.0f)), 0);
}
#endif