Second pass idLib integration.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
class idComplex {
|
||||
public:
|
||||
float r;
|
||||
float i;
|
||||
|
||||
idComplex() = default;
|
||||
idComplex(const float real, const float imaginary) : r(real), i(imaginary) {}
|
||||
|
||||
void Set(const float real, const float imaginary) { r = real; i = imaginary; }
|
||||
void Zero() { r = 0.0f; i = 0.0f; }
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 2);
|
||||
return (&r)[index];
|
||||
}
|
||||
float& operator[](const int index) {
|
||||
assert(index >= 0 && index < 2);
|
||||
return (&r)[index];
|
||||
}
|
||||
|
||||
idComplex operator-() const { return idComplex(-r, -i); }
|
||||
idComplex operator+(const idComplex& other) const {
|
||||
return idComplex(r + other.r, i + other.i);
|
||||
}
|
||||
idComplex operator-(const idComplex& other) const {
|
||||
return idComplex(r - other.r, i - other.i);
|
||||
}
|
||||
idComplex operator*(const idComplex& other) const {
|
||||
return idComplex(r * other.r - i * other.i,
|
||||
i * other.r + r * other.i);
|
||||
}
|
||||
idComplex operator/(const idComplex& other) const {
|
||||
const float denominator = other.r * other.r + other.i * other.i;
|
||||
assert(denominator != 0.0f);
|
||||
return idComplex((r * other.r + i * other.i) / denominator,
|
||||
(i * other.r - r * other.i) / denominator);
|
||||
}
|
||||
idComplex operator*(const float scale) const { return idComplex(r * scale, i * scale); }
|
||||
idComplex operator/(const float scale) const {
|
||||
assert(scale != 0.0f);
|
||||
return idComplex(r / scale, i / scale);
|
||||
}
|
||||
idComplex operator+(const float value) const { return idComplex(r + value, i); }
|
||||
idComplex operator-(const float value) const { return idComplex(r - value, i); }
|
||||
|
||||
idComplex& operator+=(const idComplex& other) { r += other.r; i += other.i; return *this; }
|
||||
idComplex& operator-=(const idComplex& other) { r -= other.r; i -= other.i; return *this; }
|
||||
idComplex& operator*=(const idComplex& other) { return *this = *this * other; }
|
||||
idComplex& operator/=(const idComplex& other) { return *this = *this / other; }
|
||||
idComplex& operator+=(const float value) { r += value; return *this; }
|
||||
idComplex& operator-=(const float value) { r -= value; return *this; }
|
||||
idComplex& operator*=(const float scale) { r *= scale; i *= scale; return *this; }
|
||||
idComplex& operator/=(const float scale) {
|
||||
assert(scale != 0.0f); r /= scale; i /= scale; return *this;
|
||||
}
|
||||
|
||||
bool Compare(const idComplex& other) const { return r == other.r && i == other.i; }
|
||||
bool Compare(const idComplex& other, const float epsilon) const {
|
||||
return std::fabs(r - other.r) <= epsilon
|
||||
&& std::fabs(i - other.i) <= epsilon;
|
||||
}
|
||||
bool operator==(const idComplex& other) const { return Compare(other); }
|
||||
bool operator!=(const idComplex& other) const { return !Compare(other); }
|
||||
|
||||
idComplex Reciprocal() const {
|
||||
const float denominator = r * r + i * i;
|
||||
assert(denominator != 0.0f);
|
||||
return idComplex(r / denominator, -i / denominator);
|
||||
}
|
||||
idComplex Sqrt() const {
|
||||
const float magnitude = Abs();
|
||||
const float real = std::sqrt((magnitude + r) * 0.5f);
|
||||
const float imaginary = std::copysign(
|
||||
std::sqrt((magnitude - r) * 0.5f), i);
|
||||
return idComplex(real, imaginary);
|
||||
}
|
||||
float Abs() const { return std::sqrt(r * r + i * i); }
|
||||
int GetDimension() const { return 2; }
|
||||
const float* ToFloatPtr() const { return &r; }
|
||||
float* ToFloatPtr() { return &r; }
|
||||
};
|
||||
|
||||
inline idComplex operator*(const float lhs, const idComplex& rhs) { return rhs * lhs; }
|
||||
inline idComplex operator/(const float lhs, const idComplex& rhs) {
|
||||
return idComplex(lhs, 0.0f) / rhs;
|
||||
}
|
||||
inline idComplex operator+(const float lhs, const idComplex& rhs) { return rhs + lhs; }
|
||||
inline idComplex operator-(const float lhs, const idComplex& rhs) {
|
||||
return idComplex(lhs - rhs.r, -rhs.i);
|
||||
}
|
||||
|
||||
static_assert(sizeof(idComplex) == 8, "Recovered idComplex ABI changed");
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#include "angles.h"
|
||||
#include "vector.h"
|
||||
#include "../containers/list.h"
|
||||
|
||||
template<class type_t>
|
||||
class alignas(4) idCurve {
|
||||
public:
|
||||
idCurve() : times(), values(), currentIndex(-1), changed(true) {}
|
||||
virtual ~idCurve() = default;
|
||||
|
||||
virtual int AddValue(float time, const type_t& value) {
|
||||
int index = 0;
|
||||
while (index < times.Num() && times[index] < time) ++index;
|
||||
times.Insert(time, index);
|
||||
values.Insert(value, index);
|
||||
changed = true;
|
||||
currentIndex = -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
virtual void RemoveIndex(int index) {
|
||||
if (index < 0 || index >= times.Num()) return;
|
||||
times.RemoveIndex(index);
|
||||
values.RemoveIndex(index);
|
||||
changed = true;
|
||||
currentIndex = -1;
|
||||
}
|
||||
|
||||
virtual void Clear() {
|
||||
times.Clear();
|
||||
values.Clear();
|
||||
currentIndex = -1;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
virtual void SetNumValues(int count) {
|
||||
times.SetNum(count);
|
||||
values.SetNum(count);
|
||||
currentIndex = -1;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
virtual type_t GetCurrentValue(float time) const {
|
||||
if (values.Num() == 0) return type_t();
|
||||
return values[IndexForTime(time)];
|
||||
}
|
||||
virtual type_t GetCurrentFirstDerivative(float) const { return type_t(); }
|
||||
virtual type_t GetCurrentSecondDerivative(float) const { return type_t(); }
|
||||
virtual bool IsDone(float time) const {
|
||||
return times.Num() == 0 || time >= times[times.Num() - 1];
|
||||
}
|
||||
virtual float GetLengthForTime(float time) const {
|
||||
return EstimateLengthForTime(time);
|
||||
}
|
||||
virtual float EstimateLengthForTime(float) const { return 0.0f; }
|
||||
|
||||
int GetNumValues() const { return values.Num(); }
|
||||
float GetTime(int index) const { return times[index]; }
|
||||
const type_t& GetValue(int index) const { return values[index]; }
|
||||
type_t& GetValue(int index) { changed = true; return values[index]; }
|
||||
void SetTime(int index, float time) { times[index] = time; changed = true; }
|
||||
void SetValue(int index, const type_t& value) {
|
||||
values[index] = value;
|
||||
changed = true;
|
||||
}
|
||||
void ShiftTime(float delta) {
|
||||
for (int index = 0; index < times.Num(); ++index) times[index] += delta;
|
||||
changed = true;
|
||||
}
|
||||
void MakeUniform(float totalTime) {
|
||||
const int count = times.Num();
|
||||
if (count <= 1) return;
|
||||
const float step = totalTime / static_cast<float>(count - 1);
|
||||
for (int index = 0; index < count; ++index) times[index] = step * index;
|
||||
changed = true;
|
||||
}
|
||||
float MakeUniformMoveSpeed(float totalTime) {
|
||||
MakeUniform(totalTime);
|
||||
return totalTime;
|
||||
}
|
||||
void SetConstantSpeed(float totalTime) { MakeUniform(totalTime); }
|
||||
float GetLengthBetweenKnots(int, int) const { return 0.0f; }
|
||||
float GetTimeForLength(float length, float epsilon = 0.1f) const {
|
||||
return EstimateTimeForLength(length, epsilon);
|
||||
}
|
||||
float EstimateTimeForLength(float length, float) const { return length; }
|
||||
void GetBatchValues(const float* timesIn, type_t* valuesOut,
|
||||
type_t* derivativesOut, int count) const {
|
||||
for (int index = 0; index < count; ++index) {
|
||||
valuesOut[index] = GetCurrentValue(timesIn[index]);
|
||||
if (derivativesOut != nullptr) {
|
||||
derivativesOut[index] = GetCurrentFirstDerivative(timesIn[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idList<float, 116> times;
|
||||
idList<type_t, 116> values;
|
||||
mutable int currentIndex;
|
||||
mutable bool changed;
|
||||
|
||||
protected:
|
||||
virtual idCurve<type_t>* CreateNewCurve() const {
|
||||
return new idCurve<type_t>();
|
||||
}
|
||||
|
||||
int IndexForTime(float time) const {
|
||||
if (times.Num() <= 1) return 0;
|
||||
int low = 0;
|
||||
int high = times.Num();
|
||||
while (low < high) {
|
||||
const int middle = (low + high) / 2;
|
||||
if (times[middle] <= time) low = middle + 1;
|
||||
else high = middle;
|
||||
}
|
||||
currentIndex = low > 0 ? low - 1 : 0;
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
float RombergIntegral(float, float, int) const { return 0.0f; }
|
||||
};
|
||||
|
||||
template<class type_t>
|
||||
class idCurve_Spline : public idCurve<type_t> {
|
||||
public:
|
||||
idCurve_Spline() = default;
|
||||
~idCurve_Spline() override = default;
|
||||
};
|
||||
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idCurve<idVec4>) == 44,
|
||||
"Recovered idCurve<idVec4> ABI changed");
|
||||
static_assert(sizeof(idCurve<idVec3>) == 44,
|
||||
"Recovered idCurve<idVec3> ABI changed");
|
||||
static_assert(sizeof(idCurve<idAngles>) == 44,
|
||||
"Recovered idCurve<idAngles> ABI changed");
|
||||
static_assert(sizeof(idCurve<idVec1>) == 44,
|
||||
"Recovered idCurve<idVec1> ABI changed");
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/typesafenumber.h"
|
||||
|
||||
enum DegreesUnique_t : int;
|
||||
typedef idTypesafeNumber<float, DegreesUnique_t> degrees_t;
|
||||
|
||||
static_assert(sizeof(degrees_t) == 4, "Recovered degrees_t ABI changed");
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
#pragma once
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
enum extrapolation_t : int {
|
||||
EXTRAPOLATION_NONE = 0x01,
|
||||
EXTRAPOLATION_LINEAR = 0x02,
|
||||
EXTRAPOLATION_ACCELLINEAR = 0x04,
|
||||
EXTRAPOLATION_DECELLINEAR = 0x08,
|
||||
EXTRAPOLATION_ACCELSINE = 0x10,
|
||||
EXTRAPOLATION_DECELSINE = 0x20,
|
||||
EXTRAPOLATION_NOSTOP = 0x40
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class idExtrapolate {
|
||||
public:
|
||||
extrapolation_t extrapolationType;
|
||||
float startTime;
|
||||
float duration;
|
||||
T startValue;
|
||||
T baseSpeed;
|
||||
T speed;
|
||||
mutable float currentTime;
|
||||
mutable T currentValue;
|
||||
|
||||
idExtrapolate()
|
||||
: extrapolationType(EXTRAPOLATION_NONE), startTime(0.0f), duration(0.0f),
|
||||
startValue(T()), baseSpeed(T()), speed(T()), currentTime(-1.0f),
|
||||
currentValue(startValue) {
|
||||
}
|
||||
|
||||
void Init(const float newStartTime, const float newDuration,
|
||||
const T& newStartValue, const T& newBaseSpeed, const T& newSpeed,
|
||||
const extrapolation_t newType) {
|
||||
extrapolationType = newType;
|
||||
startTime = newStartTime;
|
||||
duration = newDuration;
|
||||
startValue = newStartValue;
|
||||
baseSpeed = newBaseSpeed;
|
||||
speed = newSpeed;
|
||||
currentTime = -1.0f;
|
||||
currentValue = startValue;
|
||||
}
|
||||
|
||||
T GetCurrentValue(float time) const {
|
||||
if (time == currentTime) return currentValue;
|
||||
currentTime = time;
|
||||
if (time < startTime) {
|
||||
currentValue = startValue;
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
const int type = static_cast<int>(extrapolationType) & ~EXTRAPOLATION_NOSTOP;
|
||||
if (duration == 0.0f
|
||||
&& type != EXTRAPOLATION_NONE && type != EXTRAPOLATION_LINEAR) {
|
||||
currentValue = startValue;
|
||||
return currentValue;
|
||||
}
|
||||
if ((static_cast<int>(extrapolationType) & EXTRAPOLATION_NOSTOP) == 0
|
||||
&& time > startTime + duration) {
|
||||
time = startTime + duration;
|
||||
}
|
||||
|
||||
const float elapsed = time - startTime;
|
||||
const float elapsedSeconds = elapsed * 0.001f;
|
||||
const float fraction = duration != 0.0f ? elapsed / duration : 0.0f;
|
||||
switch (type) {
|
||||
case EXTRAPOLATION_NONE:
|
||||
currentValue = startValue + baseSpeed * elapsedSeconds;
|
||||
break;
|
||||
case EXTRAPOLATION_LINEAR:
|
||||
currentValue = startValue + (baseSpeed + speed) * elapsedSeconds;
|
||||
break;
|
||||
case EXTRAPOLATION_ACCELLINEAR:
|
||||
currentValue = startValue + baseSpeed * elapsedSeconds
|
||||
+ speed * (0.5f * fraction * fraction * duration * 0.001f);
|
||||
break;
|
||||
case EXTRAPOLATION_DECELLINEAR:
|
||||
currentValue = startValue + baseSpeed * elapsedSeconds
|
||||
+ speed * ((-0.5f * fraction * fraction + fraction)
|
||||
* duration * 0.001f);
|
||||
break;
|
||||
case EXTRAPOLATION_ACCELSINE:
|
||||
currentValue = startValue + baseSpeed * elapsedSeconds
|
||||
+ speed * ((1.0f - std::cos(fraction * HALF_PI))
|
||||
* duration * SQRT_HALF * 0.001f);
|
||||
break;
|
||||
case EXTRAPOLATION_DECELSINE:
|
||||
currentValue = startValue + baseSpeed * elapsedSeconds
|
||||
+ speed * (std::sin(fraction * HALF_PI)
|
||||
* duration * SQRT_HALF * 0.001f);
|
||||
break;
|
||||
default:
|
||||
currentValue = startValue;
|
||||
break;
|
||||
}
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
T GetCurrentSpeed(const float time) const {
|
||||
if (time < startTime) return T();
|
||||
const int type = static_cast<int>(extrapolationType) & ~EXTRAPOLATION_NOSTOP;
|
||||
if (duration == 0.0f
|
||||
&& type != EXTRAPOLATION_NONE && type != EXTRAPOLATION_LINEAR) {
|
||||
return T();
|
||||
}
|
||||
if ((static_cast<int>(extrapolationType) & EXTRAPOLATION_NOSTOP) == 0
|
||||
&& time > startTime + duration) {
|
||||
return T();
|
||||
}
|
||||
const float fraction = duration != 0.0f
|
||||
? (time - startTime) / duration : 0.0f;
|
||||
switch (type) {
|
||||
case EXTRAPOLATION_LINEAR: return baseSpeed + speed;
|
||||
case EXTRAPOLATION_ACCELLINEAR: return baseSpeed + speed * fraction;
|
||||
case EXTRAPOLATION_DECELLINEAR: return baseSpeed + speed * (1.0f - fraction);
|
||||
case EXTRAPOLATION_ACCELSINE:
|
||||
return baseSpeed + speed * std::sin(fraction * HALF_PI);
|
||||
case EXTRAPOLATION_DECELSINE:
|
||||
return baseSpeed + speed * std::cos(fraction * HALF_PI);
|
||||
case EXTRAPOLATION_NONE:
|
||||
default: return baseSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsDone(const float time) const {
|
||||
return (static_cast<int>(extrapolationType) & EXTRAPOLATION_NOSTOP) == 0
|
||||
&& time >= startTime + duration;
|
||||
}
|
||||
|
||||
void SetStartTime(const float value) { startTime = value; currentTime = -1.0f; }
|
||||
void SetStartValue(const T& value) { startValue = value; currentTime = -1.0f; }
|
||||
float GetStartTime() const { return startTime; }
|
||||
float GetEndTime() const { return startTime + duration; }
|
||||
float GetDuration() const { return duration; }
|
||||
const T& GetStartValue() const { return startValue; }
|
||||
const T& GetBaseSpeed() const { return baseSpeed; }
|
||||
const T& GetSpeed() const { return speed; }
|
||||
|
||||
private:
|
||||
static constexpr float HALF_PI = 1.57079632679489661923f;
|
||||
static constexpr float SQRT_HALF = 0.70710678118654752440f;
|
||||
};
|
||||
|
||||
static_assert(sizeof(idExtrapolate<float>) == 32,
|
||||
"Recovered idExtrapolate<float> ABI changed");
|
||||
static_assert(sizeof(idExtrapolate<idVec3>) == 64,
|
||||
"Recovered idExtrapolate<idVec3> ABI changed");
|
||||
static_assert(sizeof(idExtrapolate<idAngles>) == 64,
|
||||
"Recovered idExtrapolate<idAngles> ABI changed");
|
||||
static_assert(sizeof(idExtrapolate<idQuat>) == 80,
|
||||
"Recovered idExtrapolate<idQuat> ABI changed");
|
||||
@@ -0,0 +1,327 @@
|
||||
#pragma once
|
||||
|
||||
#include "extrapolate.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
enum XUI_INTERPOLATE : int {
|
||||
XUI_INTERPOLATE_LINEAR = 0,
|
||||
XUI_INTERPOLATE_NONE = 1,
|
||||
XUI_INTERPOLATE_EASE = 2
|
||||
};
|
||||
|
||||
class idInterpolateParms {
|
||||
public:
|
||||
int accelTimeMs;
|
||||
int decelTimeMs;
|
||||
int durationMs;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class idInterpolate {
|
||||
public:
|
||||
float startTime;
|
||||
float duration;
|
||||
T startValue;
|
||||
T endValue;
|
||||
mutable float currentTime;
|
||||
mutable T currentValue;
|
||||
|
||||
idInterpolate()
|
||||
: startTime(0.0f), duration(0.0f), startValue(T()), endValue(T()),
|
||||
currentTime(-1.0f), currentValue(startValue) {
|
||||
}
|
||||
|
||||
void Init(const float newStartTime, const float newDuration,
|
||||
const T& newStartValue, const T& newEndValue) {
|
||||
startTime = newStartTime;
|
||||
duration = newDuration;
|
||||
startValue = newStartValue;
|
||||
endValue = newEndValue;
|
||||
currentTime = -1.0f;
|
||||
currentValue = startValue;
|
||||
}
|
||||
|
||||
T GetCurrentValue(const float time) const {
|
||||
if (time == currentTime) return currentValue;
|
||||
currentTime = time;
|
||||
const float delta = time - startTime;
|
||||
if ((duration >= 0.0f && delta <= 0.0f)
|
||||
|| (duration < 0.0f && delta >= 0.0f)) {
|
||||
currentValue = startValue;
|
||||
} else if ((duration >= 0.0f && delta >= duration)
|
||||
|| (duration < 0.0f && delta <= duration)) {
|
||||
currentValue = endValue;
|
||||
} else {
|
||||
currentValue = startValue + (endValue - startValue) * (delta / duration);
|
||||
}
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
T GetCurrentValueEaseOut(const float time) const {
|
||||
const float delta = time - startTime;
|
||||
if (duration <= 0.0f || delta <= 0.0f) return startValue;
|
||||
if (delta >= duration) return endValue;
|
||||
const float fraction = std::sin((delta / duration) * 1.57079632679489661923f);
|
||||
currentTime = time;
|
||||
currentValue = startValue + (endValue - startValue) * fraction;
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
bool IsDone(const float time) const {
|
||||
return duration >= 0.0f ? time >= startTime + duration
|
||||
: time <= startTime + duration;
|
||||
}
|
||||
void SetStartTime(const float value) { startTime = value; currentTime = -1.0f; }
|
||||
void SetDuration(const float value) { duration = value; currentTime = -1.0f; }
|
||||
void SetStartValue(const T& value) { startValue = value; currentTime = -1.0f; }
|
||||
void SetEndValue(const T& value) { endValue = value; currentTime = -1.0f; }
|
||||
float GetStartTime() const { return startTime; }
|
||||
float GetEndTime() const { return startTime + duration; }
|
||||
float GetDuration() const { return duration; }
|
||||
const T& GetStartValue() const { return startValue; }
|
||||
const T& GetEndValue() const { return endValue; }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class idInterpolateAccelDecelLinear {
|
||||
public:
|
||||
float startTime;
|
||||
float accelTime;
|
||||
float linearTime;
|
||||
float decelTime;
|
||||
T startValue;
|
||||
T endValue;
|
||||
mutable idExtrapolate<T> extrapolate;
|
||||
|
||||
idInterpolateAccelDecelLinear()
|
||||
: startTime(0.0f), accelTime(0.0f), linearTime(0.0f), decelTime(0.0f),
|
||||
startValue(T()), endValue(T()), extrapolate() {
|
||||
}
|
||||
|
||||
void Init(const float newStartTime, float newAccelTime, float newDecelTime,
|
||||
const float duration, const T& newStartValue, const T& newEndValue) {
|
||||
startTime = newStartTime;
|
||||
accelTime = newAccelTime;
|
||||
decelTime = newDecelTime;
|
||||
startValue = newStartValue;
|
||||
endValue = newEndValue;
|
||||
if (duration <= 0.0f) {
|
||||
linearTime = 0.0f;
|
||||
extrapolate.Init(startTime, 0.0f, startValue, T(), T(), EXTRAPOLATION_NONE);
|
||||
return;
|
||||
}
|
||||
if (accelTime + decelTime > duration) {
|
||||
const float sum = accelTime + decelTime;
|
||||
accelTime = sum > 0.0f ? accelTime * duration / sum : 0.0f;
|
||||
decelTime = duration - accelTime;
|
||||
}
|
||||
linearTime = duration - accelTime - decelTime;
|
||||
const float effectiveTime = 0.5f * (accelTime + decelTime) + linearTime;
|
||||
const T phaseSpeed = (endValue - startValue) * (1000.0f / effectiveTime);
|
||||
extrapolation_t phase = EXTRAPOLATION_ACCELLINEAR;
|
||||
float phaseDuration = accelTime;
|
||||
if (accelTime == 0.0f) {
|
||||
phase = linearTime == 0.0f
|
||||
? EXTRAPOLATION_DECELLINEAR : EXTRAPOLATION_LINEAR;
|
||||
phaseDuration = linearTime == 0.0f ? decelTime : linearTime;
|
||||
}
|
||||
extrapolate.Init(startTime, phaseDuration, startValue, T(), phaseSpeed, phase);
|
||||
}
|
||||
|
||||
T GetCurrentValue(const float time) const {
|
||||
SetPhase(time);
|
||||
return extrapolate.GetCurrentValue(time);
|
||||
}
|
||||
T GetCurrentSpeed(const float time) const {
|
||||
SetPhase(time);
|
||||
return extrapolate.GetCurrentSpeed(time);
|
||||
}
|
||||
bool IsDone(const float time) const {
|
||||
return time >= startTime + accelTime + linearTime + decelTime;
|
||||
}
|
||||
float GetStartTime() const { return startTime; }
|
||||
float GetEndTime() const { return startTime + accelTime + linearTime + decelTime; }
|
||||
float GetDuration() const { return accelTime + linearTime + decelTime; }
|
||||
void SetStartTime(const float value) { startTime = value; extrapolate.currentTime = -1.0f; }
|
||||
void SetStartValue(const T& value) { startValue = value; extrapolate.currentTime = -1.0f; }
|
||||
void SetEndValue(const T& value) { endValue = value; extrapolate.currentTime = -1.0f; }
|
||||
|
||||
private:
|
||||
void SetPhase(const float time) const {
|
||||
const float elapsed = time - startTime;
|
||||
const T zero = T();
|
||||
const T phaseSpeed = extrapolate.speed;
|
||||
if (elapsed < accelTime) {
|
||||
if ((static_cast<int>(extrapolate.extrapolationType) & ~EXTRAPOLATION_NOSTOP)
|
||||
!= EXTRAPOLATION_ACCELLINEAR) {
|
||||
extrapolate.Init(startTime, accelTime, startValue, zero,
|
||||
phaseSpeed, EXTRAPOLATION_ACCELLINEAR);
|
||||
}
|
||||
} else if (elapsed < accelTime + linearTime) {
|
||||
if ((static_cast<int>(extrapolate.extrapolationType) & ~EXTRAPOLATION_NOSTOP)
|
||||
!= EXTRAPOLATION_LINEAR) {
|
||||
const T phaseStart = startValue
|
||||
+ phaseSpeed * (accelTime * 0.0005f);
|
||||
extrapolate.Init(startTime + accelTime, linearTime, phaseStart,
|
||||
zero, phaseSpeed, EXTRAPOLATION_LINEAR);
|
||||
}
|
||||
} else if ((static_cast<int>(extrapolate.extrapolationType)
|
||||
& ~EXTRAPOLATION_NOSTOP) != EXTRAPOLATION_DECELLINEAR) {
|
||||
const T phaseStart = endValue
|
||||
- phaseSpeed * (decelTime * 0.0005f);
|
||||
extrapolate.Init(startTime + accelTime + linearTime, decelTime,
|
||||
phaseStart, zero, phaseSpeed, EXTRAPOLATION_DECELLINEAR);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class idInterpolateAccelDecelSine {
|
||||
public:
|
||||
float startTime;
|
||||
float accelTime;
|
||||
float linearTime;
|
||||
float decelTime;
|
||||
T startValue;
|
||||
T endValue;
|
||||
mutable idExtrapolate<T> extrapolate;
|
||||
|
||||
idInterpolateAccelDecelSine()
|
||||
: startTime(0.0f), accelTime(0.0f), linearTime(0.0f), decelTime(0.0f),
|
||||
startValue(T()), endValue(T()), extrapolate() {
|
||||
}
|
||||
|
||||
void Init(const float newStartTime, float newAccelTime, float newDecelTime,
|
||||
const float duration, const T& newStartValue, const T& newEndValue) {
|
||||
startTime = newStartTime;
|
||||
accelTime = newAccelTime;
|
||||
decelTime = newDecelTime;
|
||||
startValue = newStartValue;
|
||||
endValue = newEndValue;
|
||||
if (duration <= 0.0f) {
|
||||
linearTime = 0.0f;
|
||||
extrapolate.Init(startTime, 0.0f, startValue, T(), T(), EXTRAPOLATION_NONE);
|
||||
return;
|
||||
}
|
||||
if (accelTime + decelTime > duration) {
|
||||
const float sum = accelTime + decelTime;
|
||||
accelTime = sum > 0.0f ? accelTime * duration / sum : 0.0f;
|
||||
decelTime = duration - accelTime;
|
||||
}
|
||||
linearTime = duration - accelTime - decelTime;
|
||||
const float effectiveTime = 0.70710678118654752440f
|
||||
* (accelTime + decelTime) + linearTime;
|
||||
const T phaseSpeed = (endValue - startValue) * (1000.0f / effectiveTime);
|
||||
extrapolation_t phase = EXTRAPOLATION_ACCELSINE;
|
||||
float phaseDuration = accelTime;
|
||||
if (accelTime == 0.0f) {
|
||||
phase = linearTime == 0.0f
|
||||
? EXTRAPOLATION_DECELSINE : EXTRAPOLATION_LINEAR;
|
||||
phaseDuration = linearTime == 0.0f ? decelTime : linearTime;
|
||||
}
|
||||
extrapolate.Init(startTime, phaseDuration, startValue, T(), phaseSpeed, phase);
|
||||
}
|
||||
|
||||
T GetCurrentValue(const float time) const { SetPhase(time); return extrapolate.GetCurrentValue(time); }
|
||||
T GetCurrentSpeed(const float time) const { SetPhase(time); return extrapolate.GetCurrentSpeed(time); }
|
||||
bool IsDone(const float time) const { return time >= startTime + accelTime + linearTime + decelTime; }
|
||||
|
||||
private:
|
||||
void SetPhase(const float time) const {
|
||||
constexpr float SQRT_HALF = 0.70710678118654752440f;
|
||||
const float elapsed = time - startTime;
|
||||
const T zero = T();
|
||||
const T phaseSpeed = extrapolate.speed;
|
||||
if (elapsed < accelTime) {
|
||||
if ((static_cast<int>(extrapolate.extrapolationType) & ~EXTRAPOLATION_NOSTOP)
|
||||
!= EXTRAPOLATION_ACCELSINE) {
|
||||
extrapolate.Init(startTime, accelTime, startValue, zero,
|
||||
phaseSpeed, EXTRAPOLATION_ACCELSINE);
|
||||
}
|
||||
} else if (elapsed < accelTime + linearTime) {
|
||||
if ((static_cast<int>(extrapolate.extrapolationType) & ~EXTRAPOLATION_NOSTOP)
|
||||
!= EXTRAPOLATION_LINEAR) {
|
||||
const T phaseStart = startValue
|
||||
+ phaseSpeed * (accelTime * SQRT_HALF * 0.001f);
|
||||
extrapolate.Init(startTime + accelTime, linearTime, phaseStart,
|
||||
zero, phaseSpeed, EXTRAPOLATION_LINEAR);
|
||||
}
|
||||
} else if ((static_cast<int>(extrapolate.extrapolationType)
|
||||
& ~EXTRAPOLATION_NOSTOP) != EXTRAPOLATION_DECELSINE) {
|
||||
const T phaseStart = endValue
|
||||
- phaseSpeed * (decelTime * SQRT_HALF * 0.001f);
|
||||
extrapolate.Init(startTime + accelTime + linearTime, decelTime,
|
||||
phaseStart, zero, phaseSpeed, EXTRAPOLATION_DECELSINE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class idInterpolateAccelLinearEx {
|
||||
public:
|
||||
float startTime;
|
||||
float duration;
|
||||
float startSpeed;
|
||||
float endSpeed;
|
||||
T startValue;
|
||||
T endValue;
|
||||
idExtrapolate<T> extrapolate;
|
||||
|
||||
idInterpolateAccelLinearEx()
|
||||
: startTime(0.0f), duration(0.0f), startSpeed(0.0f), endSpeed(0.0f),
|
||||
startValue(T()), endValue(T()), extrapolate() {
|
||||
}
|
||||
|
||||
void InitDuration(const float newStartTime, const float newStartSpeed,
|
||||
const float newDuration, const T& newStartValue, const T& newEndValue) {
|
||||
startTime = newStartTime;
|
||||
startSpeed = newStartSpeed;
|
||||
duration = newDuration;
|
||||
startValue = newStartValue;
|
||||
endValue = newEndValue;
|
||||
endSpeed = duration > 0.0f
|
||||
? -2.0f * ((duration * 0.001f * startSpeed + startValue - endValue)
|
||||
/ (duration * 0.001f)) + startSpeed
|
||||
: startSpeed;
|
||||
extrapolate.Init(startTime, duration, startValue, T() + startSpeed,
|
||||
T() + (endSpeed - startSpeed), EXTRAPOLATION_ACCELLINEAR);
|
||||
}
|
||||
|
||||
float InitEndSpeed(const float newStartTime, const float newStartSpeed,
|
||||
const float newEndSpeed, const T& newStartValue, const T& newEndValue) {
|
||||
startTime = newStartTime;
|
||||
startSpeed = newStartSpeed;
|
||||
endSpeed = newEndSpeed;
|
||||
startValue = newStartValue;
|
||||
endValue = newEndValue;
|
||||
const float denominator = 2.0f * startSpeed + (endSpeed - startSpeed);
|
||||
duration = denominator != 0.0f
|
||||
? static_cast<float>((endValue - startValue) / denominator) * 2000.0f
|
||||
: 0.0f;
|
||||
extrapolate.Init(startTime, duration, startValue, T() + startSpeed,
|
||||
T() + (endSpeed - startSpeed), EXTRAPOLATION_ACCELLINEAR);
|
||||
return duration;
|
||||
}
|
||||
|
||||
T GetCurrentValue(const float time) const {
|
||||
if (time < startTime + duration) return extrapolate.GetCurrentValue(time);
|
||||
if (startSpeed == endSpeed) return endValue;
|
||||
return endValue + (T() + endSpeed) * ((time - startTime - duration) * 0.001f);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(idInterpolate<float>) == 24,
|
||||
"Recovered idInterpolate<float> ABI changed");
|
||||
static_assert(sizeof(idInterpolate<idVec3>) == 48,
|
||||
"Recovered idInterpolate<idVec3> ABI changed");
|
||||
static_assert(sizeof(idInterpolate<idQuat>) == 60,
|
||||
"Recovered idInterpolate<idQuat> ABI changed");
|
||||
static_assert(sizeof(idInterpolateAccelDecelLinear<float>) == 56,
|
||||
"Recovered idInterpolateAccelDecelLinear<float> ABI changed");
|
||||
static_assert(sizeof(idInterpolateAccelDecelLinear<idVec3>) == 104,
|
||||
"Recovered idInterpolateAccelDecelLinear<idVec3> ABI changed");
|
||||
static_assert(sizeof(idInterpolateAccelDecelLinear<idQuat>) == 128,
|
||||
"Recovered idInterpolateAccelDecelLinear<idQuat> ABI changed");
|
||||
static_assert(sizeof(idInterpolateAccelLinearEx<float>) == 56,
|
||||
"Recovered idInterpolateAccelLinearEx<float> ABI changed");
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
class idMatX;
|
||||
class idVecX;
|
||||
class idCmdArgs;
|
||||
|
||||
class idLCP {
|
||||
public:
|
||||
virtual ~idLCP() = default;
|
||||
virtual bool Solve(const idMatX* matrix, idVecX* result,
|
||||
const idVecX* constants, const idVecX* lower,
|
||||
const idVecX* upper, const int* boxIndex,
|
||||
const float* ignored = nullptr) = 0;
|
||||
virtual void SetMaxIterations(const int maximum) { maxIterations = maximum; }
|
||||
virtual int GetMaxIterations() { return maxIterations; }
|
||||
|
||||
static idLCP* AllocSymmetric();
|
||||
static void Test_f(const idCmdArgs& args);
|
||||
|
||||
int maxIterations;
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(sizeof(idLCP) == 8, "Recovered idLCP ABI changed");
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/precompiled.h"
|
||||
#include "vector.h"
|
||||
|
||||
class idMat3x4 {
|
||||
public:
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
float* ToFloatPtr() { return mat; }
|
||||
const float* ToFloatPtr() const { return mat; }
|
||||
|
||||
private:
|
||||
public:
|
||||
float mat[12];
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include "../containers/array.h"
|
||||
#include "vector.h"
|
||||
#include "mat3x4.h"
|
||||
|
||||
struct alignas(16) idNativeVector4 {
|
||||
float value[4];
|
||||
};
|
||||
|
||||
struct _XMMATRIX {
|
||||
union {
|
||||
idNativeVector4 r[4];
|
||||
struct {
|
||||
float _11, _12, _13, _14;
|
||||
float _21, _22, _23, _24;
|
||||
float _31, _32, _33, _34;
|
||||
float _41, _42, _43, _44;
|
||||
} __s1;
|
||||
float m[4][4];
|
||||
} ___u0;
|
||||
};
|
||||
|
||||
struct _D3DMATRIX {
|
||||
union {
|
||||
struct {
|
||||
float _11, _12, _13, _14;
|
||||
float _21, _22, _23, _24;
|
||||
float _31, _32, _33, _34;
|
||||
float _41, _42, _43, _44;
|
||||
} __s0;
|
||||
float m[4][4];
|
||||
} ___u0;
|
||||
};
|
||||
|
||||
struct _ATIMATRIX {
|
||||
float _11, _21, _31, _41;
|
||||
float _12, _22, _32, _42;
|
||||
float _13, _23, _33, _43;
|
||||
float _14, _24, _34, _44;
|
||||
unsigned int dwFlags;
|
||||
};
|
||||
|
||||
class idMat2 {
|
||||
public:
|
||||
idVec2 mat[2];
|
||||
idMat2() = default;
|
||||
explicit idMat2(float diagonal) {
|
||||
mat[0].Set(diagonal, 0.0f);
|
||||
mat[1].Set(0.0f, diagonal);
|
||||
}
|
||||
idVec2& operator[](int index) { return mat[index]; }
|
||||
const idVec2& operator[](int index) const { return mat[index]; }
|
||||
};
|
||||
|
||||
class idMat4 {
|
||||
public:
|
||||
idVec4 mat[4];
|
||||
idMat4() = default;
|
||||
explicit idMat4(float diagonal) {
|
||||
for (int row = 0; row < 4; ++row)
|
||||
for (int column = 0; column < 4; ++column)
|
||||
mat[row][column] = row == column ? diagonal : 0.0f;
|
||||
}
|
||||
idVec4& operator[](int index) { return mat[index]; }
|
||||
const idVec4& operator[](int index) const { return mat[index]; }
|
||||
};
|
||||
|
||||
class idMat5 {
|
||||
public:
|
||||
idVec5 mat[5];
|
||||
idVec5& operator[](int index) { return mat[index]; }
|
||||
const idVec5& operator[](int index) const { return mat[index]; }
|
||||
};
|
||||
|
||||
class idMat6 {
|
||||
public:
|
||||
idVec6 mat[6];
|
||||
idVec6& operator[](int index) { return mat[index]; }
|
||||
const idVec6& operator[](int index) const { return mat[index]; }
|
||||
};
|
||||
|
||||
struct swfMatrix_t {
|
||||
float xx;
|
||||
float yy;
|
||||
float xy;
|
||||
float yx;
|
||||
float tx;
|
||||
float ty;
|
||||
};
|
||||
|
||||
using XMMATRIX = _XMMATRIX;
|
||||
using ATIMATRIX = _ATIMATRIX;
|
||||
using D3DMATRIX = _D3DMATRIX;
|
||||
using matrix_t = idArray<float, 36>;
|
||||
using FXLMATRIX = _XMMATRIX;
|
||||
|
||||
static_assert(sizeof(_XMMATRIX) == 64, "Recovered XMMATRIX ABI changed");
|
||||
static_assert(sizeof(_D3DMATRIX) == 64, "Recovered D3DMATRIX ABI changed");
|
||||
static_assert(sizeof(_ATIMATRIX) == 68, "Recovered ATIMATRIX ABI changed");
|
||||
static_assert(sizeof(idMat2) == 16, "Recovered idMat2 ABI changed");
|
||||
static_assert(sizeof(idMat4) == 64, "Recovered idMat4 ABI changed");
|
||||
static_assert(sizeof(idMat5) == 100, "Recovered idMat5 ABI changed");
|
||||
static_assert(sizeof(idMat6) == 144, "Recovered idMat6 ABI changed");
|
||||
static_assert(sizeof(swfMatrix_t) == 24, "Recovered swfMatrix_t ABI changed");
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
typedef void (*idODEDeriveFunction)(float time, const void* userData,
|
||||
const float* state, float* derivatives);
|
||||
|
||||
class idODE {
|
||||
public:
|
||||
idODE(const int stateDimension, idODEDeriveFunction deriveFunction,
|
||||
const void* data)
|
||||
: dimension(stateDimension), derive(deriveFunction), userData(data) {}
|
||||
virtual ~idODE() = default;
|
||||
virtual float Evaluate(const float* state, float* newState,
|
||||
float time, float timeStep) = 0;
|
||||
|
||||
int dimension;
|
||||
idODEDeriveFunction derive;
|
||||
const void* userData;
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(sizeof(idODE) == 16, "Recovered idODE ABI changed");
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
class idPlane {
|
||||
public:
|
||||
float a;
|
||||
float b;
|
||||
float c;
|
||||
float d;
|
||||
|
||||
idPlane() = default;
|
||||
idPlane(const float newA, const float newB, const float newC, const float newD)
|
||||
: a(newA), b(newB), c(newC), d(newD) {}
|
||||
idPlane(const idVec3& normal, const float distance)
|
||||
: a(normal.x), b(normal.y), c(normal.z), d(-distance) {}
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 4); return (&a)[index];
|
||||
}
|
||||
float& operator[](const int index) {
|
||||
assert(index >= 0 && index < 4); return (&a)[index];
|
||||
}
|
||||
idPlane operator-() const { return idPlane(-a, -b, -c, -d); }
|
||||
idVec3& Normal() { return *reinterpret_cast<idVec3*>(&a); }
|
||||
const idVec3& Normal() const { return *reinterpret_cast<const idVec3*>(&a); }
|
||||
float Dist() const { return -d; }
|
||||
void SetDist(const float distance) { d = -distance; }
|
||||
float Distance(const idVec3& point) const {
|
||||
return a * point.x + b * point.y + c * point.z + d;
|
||||
}
|
||||
bool Compare(const idPlane& other, const float normalEpsilon,
|
||||
const float distanceEpsilon) const {
|
||||
return std::fabs(a - other.a) <= normalEpsilon
|
||||
&& std::fabs(b - other.b) <= normalEpsilon
|
||||
&& std::fabs(c - other.c) <= normalEpsilon
|
||||
&& std::fabs(d - other.d) <= distanceEpsilon;
|
||||
}
|
||||
int GetDimension() const { return 4; }
|
||||
const float* ToFloatPtr() const { return &a; }
|
||||
float* ToFloatPtr() { return &a; }
|
||||
};
|
||||
|
||||
static_assert(sizeof(idPlane) == 16, "Recovered idPlane ABI changed");
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
class idPluecker {
|
||||
public:
|
||||
float p[6];
|
||||
|
||||
idPluecker() = default;
|
||||
explicit idPluecker(const float* values) {
|
||||
std::memcpy(p, values, sizeof(p));
|
||||
}
|
||||
idPluecker(const float p0, const float p1, const float p2,
|
||||
const float p3, const float p4, const float p5) {
|
||||
Set(p0, p1, p2, p3, p4, p5);
|
||||
}
|
||||
idPluecker(const idVec3& start, const idVec3& end) { FromLine(start, end); }
|
||||
|
||||
float operator[](const int index) const { assert(index >= 0 && index < 6); return p[index]; }
|
||||
float& operator[](const int index) { assert(index >= 0 && index < 6); return p[index]; }
|
||||
|
||||
idPluecker operator-() const {
|
||||
return idPluecker(-p[0], -p[1], -p[2], -p[3], -p[4], -p[5]);
|
||||
}
|
||||
idPluecker operator*(const float scale) const {
|
||||
return idPluecker(p[0] * scale, p[1] * scale, p[2] * scale,
|
||||
p[3] * scale, p[4] * scale, p[5] * scale);
|
||||
}
|
||||
idPluecker operator/(const float scale) const {
|
||||
assert(scale != 0.0f); return *this * (1.0f / scale);
|
||||
}
|
||||
float operator*(const idPluecker& other) const {
|
||||
return PermutedInnerProduct(other);
|
||||
}
|
||||
idPluecker operator+(const idPluecker& other) const {
|
||||
return idPluecker(p[0] + other.p[0], p[1] + other.p[1],
|
||||
p[2] + other.p[2], p[3] + other.p[3],
|
||||
p[4] + other.p[4], p[5] + other.p[5]);
|
||||
}
|
||||
idPluecker operator-(const idPluecker& other) const { return *this + -other; }
|
||||
idPluecker& operator*=(const float scale) {
|
||||
for (float& value : p) value *= scale; return *this;
|
||||
}
|
||||
idPluecker& operator/=(const float scale) {
|
||||
assert(scale != 0.0f); return *this *= 1.0f / scale;
|
||||
}
|
||||
idPluecker& operator+=(const idPluecker& other) {
|
||||
for (int index = 0; index < 6; ++index) p[index] += other.p[index];
|
||||
return *this;
|
||||
}
|
||||
idPluecker& operator-=(const idPluecker& other) {
|
||||
for (int index = 0; index < 6; ++index) p[index] -= other.p[index];
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Compare(const idPluecker& other) const {
|
||||
for (int index = 0; index < 6; ++index) if (p[index] != other.p[index]) return false;
|
||||
return true;
|
||||
}
|
||||
bool Compare(const idPluecker& other, const float epsilon) const {
|
||||
for (int index = 0; index < 6; ++index)
|
||||
if (std::fabs(p[index] - other.p[index]) > epsilon) return false;
|
||||
return true;
|
||||
}
|
||||
bool operator==(const idPluecker& other) const { return Compare(other); }
|
||||
bool operator!=(const idPluecker& other) const { return !Compare(other); }
|
||||
|
||||
void Set(const float p0, const float p1, const float p2,
|
||||
const float p3, const float p4, const float p5) {
|
||||
p[0] = p0; p[1] = p1; p[2] = p2;
|
||||
p[3] = p3; p[4] = p4; p[5] = p5;
|
||||
}
|
||||
void Zero() { for (float& value : p) value = 0.0f; }
|
||||
void FromLine(const idVec3& start, const idVec3& end) {
|
||||
p[0] = start.x * end.y - end.x * start.y;
|
||||
p[1] = start.x * end.z - end.x * start.z;
|
||||
p[2] = start.x - end.x;
|
||||
p[3] = start.y * end.z - end.y * start.z;
|
||||
p[4] = start.z - end.z;
|
||||
p[5] = end.y - start.y;
|
||||
}
|
||||
void FromRay(const idVec3& start, const idVec3& direction) {
|
||||
p[0] = start.x * direction.y - direction.x * start.y;
|
||||
p[1] = start.x * direction.z - direction.x * start.z;
|
||||
p[2] = -direction.x;
|
||||
p[3] = start.y * direction.z - direction.y * start.z;
|
||||
p[4] = -direction.z;
|
||||
p[5] = direction.y;
|
||||
}
|
||||
bool ToRay(idVec3& start, idVec3& direction) const {
|
||||
const idVec3 moment(p[3], -p[1], p[0]);
|
||||
direction.Set(-p[2], p[5], -p[4]);
|
||||
const float lengthSqr = direction.LengthSqr();
|
||||
if (lengthSqr == 0.0f) return false;
|
||||
start = direction.Cross(moment) * (1.0f / lengthSqr);
|
||||
return true;
|
||||
}
|
||||
bool ToLine(idVec3& start, idVec3& end) const {
|
||||
idVec3 direction;
|
||||
if (!ToRay(start, direction)) return false;
|
||||
end = start + direction;
|
||||
return true;
|
||||
}
|
||||
void ToDir(idVec3& direction) const { direction.Set(-p[2], p[5], -p[4]); }
|
||||
float PermutedInnerProduct(const idPluecker& other) const {
|
||||
return p[0] * other.p[4] + p[1] * other.p[5]
|
||||
+ p[2] * other.p[3] + p[4] * other.p[0]
|
||||
+ p[5] * other.p[1] + p[3] * other.p[2];
|
||||
}
|
||||
float LengthSqr() const { return p[2] * p[2] + p[4] * p[4] + p[5] * p[5]; }
|
||||
float Length() const { return std::sqrt(LengthSqr()); }
|
||||
float NormalizeSelf() {
|
||||
const float length = Length();
|
||||
if (length != 0.0f) *this /= length;
|
||||
return length;
|
||||
}
|
||||
idPluecker Normalize() const { idPluecker result(*this); result.NormalizeSelf(); return result; }
|
||||
int GetDimension() const { return 6; }
|
||||
const float* ToFloatPtr() const { return p; }
|
||||
float* ToFloatPtr() { return p; }
|
||||
};
|
||||
|
||||
static_assert(sizeof(idPluecker) == 24, "Recovered idPluecker ABI changed");
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
class idPolar3 {
|
||||
public:
|
||||
float radius;
|
||||
float theta;
|
||||
float phi;
|
||||
|
||||
idPolar3() = default;
|
||||
idPolar3(const float newRadius, const float newTheta, const float newPhi) {
|
||||
Set(newRadius, newTheta, newPhi);
|
||||
}
|
||||
|
||||
void Set(const float newRadius, const float newTheta, const float newPhi) {
|
||||
assert(newRadius >= 0.0f);
|
||||
radius = newRadius;
|
||||
theta = newTheta;
|
||||
phi = newPhi;
|
||||
}
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 3);
|
||||
return (&radius)[index];
|
||||
}
|
||||
float& operator[](const int index) {
|
||||
assert(index >= 0 && index < 3);
|
||||
return (&radius)[index];
|
||||
}
|
||||
idPolar3 operator-() const { return idPolar3(radius, -theta, -phi); }
|
||||
|
||||
idVec3 ToVec3() const {
|
||||
const float cosPhi = std::cos(phi);
|
||||
return idVec3(cosPhi * radius * std::cos(theta),
|
||||
cosPhi * radius * std::sin(theta), radius * std::sin(phi));
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(idPolar3) == 12, "Recovered idPolar3 ABI changed");
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/complex.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <new>
|
||||
|
||||
class idPolynomial {
|
||||
public:
|
||||
int degree;
|
||||
int allocated;
|
||||
float* coefficient;
|
||||
|
||||
idPolynomial() : degree(-1), allocated(0), coefficient(nullptr) {}
|
||||
explicit idPolynomial(const int newDegree) : idPolynomial() { Zero(newDegree); }
|
||||
idPolynomial(const idPolynomial& other) : idPolynomial() { *this = other; }
|
||||
~idPolynomial() { delete[] coefficient; }
|
||||
|
||||
idPolynomial& operator=(const idPolynomial& other) {
|
||||
if (this != &other) {
|
||||
Resize(other.degree, false);
|
||||
std::copy(other.coefficient, other.coefficient + other.degree + 1,
|
||||
coefficient);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index <= degree); return coefficient[index];
|
||||
}
|
||||
float& operator[](const int index) {
|
||||
assert(index >= 0 && index <= degree); return coefficient[index];
|
||||
}
|
||||
void Zero() { if (coefficient != nullptr) std::fill(coefficient, coefficient + degree + 1, 0.0f); }
|
||||
void Zero(const int newDegree) { Resize(newDegree, false); Zero(); }
|
||||
int GetDimension() const { return degree + 1; }
|
||||
int GetDegree() const { return degree; }
|
||||
float GetValue(const float x) const {
|
||||
float result = 0.0f;
|
||||
for (int index = degree; index >= 0; --index) result = result * x + coefficient[index];
|
||||
return result;
|
||||
}
|
||||
idComplex GetValue(const idComplex& x) const {
|
||||
idComplex result(0.0f, 0.0f);
|
||||
for (int index = degree; index >= 0; --index)
|
||||
result = result * x + coefficient[index];
|
||||
return result;
|
||||
}
|
||||
idPolynomial GetDerivative() const {
|
||||
idPolynomial result((std::max)(degree - 1, 0));
|
||||
if (degree <= 0) { result[0] = 0.0f; return result; }
|
||||
for (int index = 1; index <= degree; ++index)
|
||||
result[index - 1] = coefficient[index] * static_cast<float>(index);
|
||||
return result;
|
||||
}
|
||||
idPolynomial GetAntiDerivative() const {
|
||||
idPolynomial result(degree + 1);
|
||||
result[0] = 0.0f;
|
||||
for (int index = 0; index <= degree; ++index)
|
||||
result[index + 1] = coefficient[index] / static_cast<float>(index + 1);
|
||||
return result;
|
||||
}
|
||||
bool Compare(const idPolynomial& other) const {
|
||||
if (degree != other.degree) return false;
|
||||
for (int index = 0; index <= degree; ++index)
|
||||
if (coefficient[index] != other.coefficient[index]) return false;
|
||||
return true;
|
||||
}
|
||||
bool Compare(const idPolynomial& other, const float epsilon) const {
|
||||
if (degree != other.degree) return false;
|
||||
for (int index = 0; index <= degree; ++index)
|
||||
if (std::fabs(coefficient[index] - other.coefficient[index]) > epsilon) return false;
|
||||
return true;
|
||||
}
|
||||
bool operator==(const idPolynomial& other) const { return Compare(other); }
|
||||
bool operator!=(const idPolynomial& other) const { return !Compare(other); }
|
||||
|
||||
private:
|
||||
void Resize(const int newDegree, const bool keep) {
|
||||
assert(newDegree >= 0);
|
||||
const int required = newDegree + 1;
|
||||
if (required > allocated) {
|
||||
const int newAllocated = (required + 3) & ~3;
|
||||
float* replacement = new float[newAllocated];
|
||||
std::fill(replacement, replacement + newAllocated, 0.0f);
|
||||
if (keep && coefficient != nullptr) {
|
||||
std::copy(coefficient,
|
||||
coefficient + (std::min)(degree + 1, required), replacement);
|
||||
}
|
||||
delete[] coefficient;
|
||||
coefficient = replacement;
|
||||
allocated = newAllocated;
|
||||
} else if (!keep && coefficient != nullptr) {
|
||||
std::fill(coefficient, coefficient + allocated, 0.0f);
|
||||
}
|
||||
degree = newDegree;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(sizeof(idPolynomial) == 12, "Recovered idPolynomial ABI changed");
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
class idCQuat {
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
idCQuat() = default;
|
||||
idCQuat(const float newX, const float newY, const float newZ)
|
||||
: x(newX), y(newY), z(newZ) {}
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 3); return (&x)[index];
|
||||
}
|
||||
float& operator[](const int index) {
|
||||
assert(index >= 0 && index < 3); return (&x)[index];
|
||||
}
|
||||
};
|
||||
|
||||
// PDB type 23290 is an intentionally empty marker.
|
||||
struct quat_t {};
|
||||
|
||||
static_assert(sizeof(idCQuat) == 12, "Recovered idCQuat ABI changed");
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/typesafenumber.h"
|
||||
|
||||
enum RadiansUnique_t : int;
|
||||
typedef idTypesafeNumber<float, RadiansUnique_t> radians_t;
|
||||
|
||||
static_assert(sizeof(radians_t) == 4, "Recovered radians_t ABI changed");
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class idRandom {
|
||||
public:
|
||||
static const int MAX_RAND = 0x7FFF;
|
||||
|
||||
int seed;
|
||||
|
||||
explicit idRandom(const int initialSeed = 0) : seed(initialSeed) {}
|
||||
void SetSeed(const int value) { seed = value; }
|
||||
int GetSeed() const { return seed; }
|
||||
|
||||
int RandomInt() {
|
||||
seed = static_cast<int>(1103515245u * static_cast<unsigned int>(seed) + 12345u);
|
||||
return (static_cast<unsigned int>(seed) >> 16) & MAX_RAND;
|
||||
}
|
||||
|
||||
int RandomInt(const int max) {
|
||||
return max == 0 ? 0 : RandomInt() % max;
|
||||
}
|
||||
|
||||
float RandomFloat() { return RandomInt() * (1.0f / 32768.0f); }
|
||||
float CRandomFloat() { return 2.0f * RandomFloat() - 1.0f; }
|
||||
};
|
||||
|
||||
class idRandom2 {
|
||||
public:
|
||||
static const int MAX_RAND = 0x7FFF;
|
||||
|
||||
unsigned int seed;
|
||||
|
||||
explicit idRandom2(const unsigned int initialSeed = 0) : seed(initialSeed) {}
|
||||
void SetSeed(const unsigned int value) { seed = value; }
|
||||
unsigned int GetSeed() const { return seed; }
|
||||
|
||||
int RandomInt() {
|
||||
seed = 1664525u * seed + 1013904223u;
|
||||
return static_cast<int>((seed >> 10) & MAX_RAND);
|
||||
}
|
||||
|
||||
int RandomInt(const int max) {
|
||||
return max == 0 ? 0 : RandomInt() % max;
|
||||
}
|
||||
|
||||
int RandomInt(const int min, const int max) {
|
||||
return min >= max ? min : min + RandomInt(max - min + 1);
|
||||
}
|
||||
|
||||
float RandomFloat() { return RandomInt() * (1.0f / 32768.0f); }
|
||||
float CRandomFloat() { return 2.0f * RandomFloat() - 1.0f; }
|
||||
|
||||
float BellCurve(const int degree) {
|
||||
if (degree <= 0) return 0.0f;
|
||||
float sum = 0.0f;
|
||||
for (int index = 0; index < degree; ++index) sum += CRandomFloat();
|
||||
return sum / static_cast<float>(degree);
|
||||
}
|
||||
};
|
||||
|
||||
class idRandomMersenneCyclic {
|
||||
public:
|
||||
unsigned int MT[624];
|
||||
};
|
||||
|
||||
class idRandomWELL1024 {
|
||||
public:
|
||||
unsigned int seedArray[32];
|
||||
unsigned int state_i;
|
||||
unsigned int STATE[32];
|
||||
};
|
||||
|
||||
class idRandomMersenne {
|
||||
public:
|
||||
unsigned int MT[624];
|
||||
unsigned int index;
|
||||
|
||||
explicit idRandomMersenne(const unsigned int seed = 5489u) {
|
||||
SetSeed(seed);
|
||||
}
|
||||
|
||||
void SetSeed(const unsigned int seed) {
|
||||
MT[0] = seed;
|
||||
for (unsigned int i = 1; i < 624; ++i) {
|
||||
MT[i] = 1812433253u * (MT[i - 1] ^ (MT[i - 1] >> 30)) + i;
|
||||
}
|
||||
index = 624;
|
||||
}
|
||||
|
||||
void GenerateNumbers() {
|
||||
static const unsigned int mag01[2] = { 0u, 0x9908B0DFu };
|
||||
for (unsigned int i = 0; i < 227; ++i) {
|
||||
const unsigned int value = (MT[i] & 0x80000000u)
|
||||
| (MT[i + 1] & 0x7FFFFFFEu);
|
||||
MT[i] = MT[i + 397] ^ (value >> 1) ^ mag01[value & 1u];
|
||||
}
|
||||
for (unsigned int i = 227; i < 623; ++i) {
|
||||
const unsigned int value = (MT[i] & 0x80000000u)
|
||||
| (MT[i + 1] & 0x7FFFFFFEu);
|
||||
MT[i] = MT[i - 227] ^ (value >> 1) ^ mag01[value & 1u];
|
||||
}
|
||||
const unsigned int value = (MT[623] & 0x80000000u)
|
||||
| (MT[0] & 0x7FFFFFFEu);
|
||||
MT[623] = MT[396] ^ (value >> 1) ^ mag01[value & 1u];
|
||||
}
|
||||
|
||||
unsigned int RandomInt() {
|
||||
if (index >= 624) {
|
||||
index = 0;
|
||||
GenerateNumbers();
|
||||
}
|
||||
unsigned int value = MT[index++];
|
||||
value ^= value >> 11;
|
||||
value ^= (value << 7) & 0x9D2C5680u;
|
||||
value ^= (value << 15) & 0xEFC60000u;
|
||||
value ^= value >> 18;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
using idRandomType = idRandom2;
|
||||
|
||||
static_assert(sizeof(idRandom) == 4, "Recovered idRandom ABI changed");
|
||||
static_assert(sizeof(idRandom2) == 4, "Recovered idRandom2 ABI changed");
|
||||
static_assert(sizeof(idRandomMersenneCyclic) == 2496,
|
||||
"Recovered idRandomMersenneCyclic ABI changed");
|
||||
static_assert(sizeof(idRandomWELL1024) == 260,
|
||||
"Recovered idRandomWELL1024 ABI changed");
|
||||
static_assert(sizeof(idRandomMersenne) == 2500,
|
||||
"Recovered idRandomMersenne ABI changed");
|
||||
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class idRotation {
|
||||
public:
|
||||
idVec3 origin;
|
||||
idVec3 vec;
|
||||
float angle;
|
||||
mutable idMat3 axis;
|
||||
mutable bool axisValid;
|
||||
|
||||
idRotation()
|
||||
: origin(0.0f, 0.0f, 0.0f), vec(0.0f, 0.0f, 1.0f), angle(0.0f),
|
||||
axis(1.0f), axisValid(false) {
|
||||
}
|
||||
|
||||
idRotation(const idVec3& rotationOrigin, const idVec3& rotationVector,
|
||||
const float rotationAngle)
|
||||
: origin(rotationOrigin), vec(rotationVector), angle(rotationAngle),
|
||||
axis(1.0f), axisValid(false) {
|
||||
}
|
||||
|
||||
const idMat3& ToMat3() const {
|
||||
if (axisValid) return axis;
|
||||
const float halfAngle = angle * 0.00872664625997164788f;
|
||||
const float sine = std::sin(halfAngle);
|
||||
const float cosine = std::cos(halfAngle);
|
||||
const float x = vec.x * sine;
|
||||
const float y = vec.y * sine;
|
||||
const float z = vec.z * sine;
|
||||
const float x2 = x + x;
|
||||
const float y2 = y + y;
|
||||
const float z2 = z + z;
|
||||
const float xx = x * x2;
|
||||
const float xy = x * y2;
|
||||
const float xz = x * z2;
|
||||
const float yy = y * y2;
|
||||
const float yz = y * z2;
|
||||
const float zz = z * z2;
|
||||
const float wx = cosine * x2;
|
||||
const float wy = cosine * y2;
|
||||
const float wz = cosine * z2;
|
||||
axis = idMat3(
|
||||
1.0f - (yy + zz), xy - wz, xz + wy,
|
||||
xy + wz, 1.0f - (xx + zz), yz - wx,
|
||||
xz - wy, yz + wx, 1.0f - (xx + yy));
|
||||
axisValid = true;
|
||||
return axis;
|
||||
}
|
||||
|
||||
idVec3 operator*(const idVec3& point) const {
|
||||
return origin + ToMat3() * (point - origin);
|
||||
}
|
||||
|
||||
idRotation operator-() const {
|
||||
return idRotation(origin, vec, -angle);
|
||||
}
|
||||
|
||||
void RotatePoint(idVec3& point) const { point = *this * point; }
|
||||
void RotateAxis(idMat3& value) const { value *= ToMat3(); }
|
||||
|
||||
void Normalize180() {
|
||||
angle -= std::floor(angle / 360.0f) * 360.0f;
|
||||
if (angle > 180.0f) angle -= 360.0f;
|
||||
if (angle < -180.0f) angle += 360.0f;
|
||||
axisValid = false;
|
||||
}
|
||||
|
||||
idVec3 ToAngularVelocity() const {
|
||||
return vec * (angle * 0.01745329251994329577f);
|
||||
}
|
||||
|
||||
void SetOrigin(const idVec3& value) { origin = value; }
|
||||
void SetVec(const idVec3& value) { vec = value; axisValid = false; }
|
||||
void SetAngle(float value) { angle = value; axisValid = false; }
|
||||
const idVec3& GetOrigin() const { return origin; }
|
||||
const idVec3& GetVec() const { return vec; }
|
||||
float GetAngle() const { return angle; }
|
||||
};
|
||||
|
||||
inline idVec3& operator*=(idVec3& vector, const idRotation& rotation) {
|
||||
vector = rotation * vector;
|
||||
return vector;
|
||||
}
|
||||
|
||||
static_assert(sizeof(idRotation) == 68, "Recovered idRotation ABI changed");
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/precompiled.h"
|
||||
|
||||
#include "vector.h"
|
||||
#include "spatialvec.h"
|
||||
|
||||
// Tungsten stores every spatial matrix in a six-row, eight-float-stride slab.
|
||||
@@ -65,6 +64,8 @@ private:
|
||||
bool Inverse6x6(idSpatialMat& dst) const;
|
||||
void ClearPadding();
|
||||
|
||||
public:
|
||||
// Public in the recovered PDB declaration (ordinal 12835).
|
||||
int numRows;
|
||||
int numColumns;
|
||||
int allocatedRows;
|
||||
@@ -74,4 +75,3 @@ private:
|
||||
#if INTPTR_MAX == INT32_MAX
|
||||
static_assert(sizeof(idSpatialMat) == 16, "Recovered idSpatialMat ABI changed");
|
||||
#endif
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
idVec1() = default;
|
||||
explicit idVec1(const float newX) : x(newX) {}
|
||||
void Zero() { x = 0.0f; }
|
||||
int GetDimension() const { return 1; }
|
||||
float operator[](const int) const { return x; }
|
||||
float& operator[](const int) { return x; }
|
||||
};
|
||||
@@ -42,6 +43,8 @@ public:
|
||||
y = 0.0f;
|
||||
}
|
||||
|
||||
int GetDimension() const { return 2; }
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 2);
|
||||
return (&x)[index];
|
||||
@@ -84,6 +87,9 @@ public:
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
int GetDimension() const { return 3; }
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 3);
|
||||
return (&x)[index];
|
||||
@@ -144,8 +150,73 @@ public:
|
||||
mat[2].Set(0.0f, 0.0f, diagonal);
|
||||
}
|
||||
|
||||
idMat3(float xx, float xy, float xz,
|
||||
float yx, float yy, float yz,
|
||||
float zx, float zy, float zz) {
|
||||
mat[0].Set(xx, xy, xz);
|
||||
mat[1].Set(yx, yy, yz);
|
||||
mat[2].Set(zx, zy, zz);
|
||||
}
|
||||
|
||||
idVec3& operator[](const int index) { return mat[index]; }
|
||||
const idVec3& operator[](const int index) const { return mat[index]; }
|
||||
|
||||
idVec3 operator*(const idVec3& vector) const {
|
||||
return idVec3(
|
||||
mat[0].x * vector.x + mat[0].y * vector.y + mat[0].z * vector.z,
|
||||
mat[1].x * vector.x + mat[1].y * vector.y + mat[1].z * vector.z,
|
||||
mat[2].x * vector.x + mat[2].y * vector.y + mat[2].z * vector.z);
|
||||
}
|
||||
|
||||
idMat3 operator*(const idMat3& other) const {
|
||||
idMat3 result;
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int column = 0; column < 3; ++column) {
|
||||
result[row][column] = mat[row][0] * other[0][column]
|
||||
+ mat[row][1] * other[1][column]
|
||||
+ mat[row][2] * other[2][column];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
idMat3& operator*=(const idMat3& other) {
|
||||
*this = *this * other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
idMat3 Transpose() const {
|
||||
return idMat3(
|
||||
mat[0].x, mat[1].x, mat[2].x,
|
||||
mat[0].y, mat[1].y, mat[2].y,
|
||||
mat[0].z, mat[1].z, mat[2].z);
|
||||
}
|
||||
|
||||
float Determinant() const {
|
||||
return mat[0].x * (mat[1].y * mat[2].z - mat[1].z * mat[2].y)
|
||||
- mat[0].y * (mat[1].x * mat[2].z - mat[1].z * mat[2].x)
|
||||
+ mat[0].z * (mat[1].x * mat[2].y - mat[1].y * mat[2].x);
|
||||
}
|
||||
|
||||
bool InverseSelf() {
|
||||
const float determinant = Determinant();
|
||||
if (std::fabs(determinant) < 1.0e-14f) return false;
|
||||
const float inverseDeterminant = 1.0f / determinant;
|
||||
const idMat3 source = *this;
|
||||
mat[0].Set(
|
||||
(source[1].y * source[2].z - source[1].z * source[2].y) * inverseDeterminant,
|
||||
(source[0].z * source[2].y - source[0].y * source[2].z) * inverseDeterminant,
|
||||
(source[0].y * source[1].z - source[0].z * source[1].y) * inverseDeterminant);
|
||||
mat[1].Set(
|
||||
(source[1].z * source[2].x - source[1].x * source[2].z) * inverseDeterminant,
|
||||
(source[0].x * source[2].z - source[0].z * source[2].x) * inverseDeterminant,
|
||||
(source[0].z * source[1].x - source[0].x * source[1].z) * inverseDeterminant);
|
||||
mat[2].Set(
|
||||
(source[1].x * source[2].y - source[1].y * source[2].x) * inverseDeterminant,
|
||||
(source[0].y * source[2].x - source[0].x * source[2].y) * inverseDeterminant,
|
||||
(source[0].x * source[1].y - source[0].y * source[1].x) * inverseDeterminant);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(idMat3) == 36, "Recovered idMat3 layout changed");
|
||||
@@ -183,6 +254,8 @@ public:
|
||||
w = newW;
|
||||
}
|
||||
|
||||
int GetDimension() const { return 4; }
|
||||
|
||||
float operator[](const int index) const {
|
||||
assert(index >= 0 && index < 4);
|
||||
return (&x)[index];
|
||||
@@ -196,6 +269,35 @@ public:
|
||||
|
||||
static_assert(sizeof(idVec4) == 16, "Recovered idVec4 layout changed");
|
||||
|
||||
class idVec5 {
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float s;
|
||||
float t;
|
||||
|
||||
idVec5() = default;
|
||||
idVec5(float newX, float newY, float newZ, float newS, float newT)
|
||||
: x(newX), y(newY), z(newZ), s(newS), t(newT) {}
|
||||
int GetDimension() const { return 5; }
|
||||
float& operator[](int index) { return (&x)[index]; }
|
||||
float operator[](int index) const { return (&x)[index]; }
|
||||
};
|
||||
|
||||
class idVec6 {
|
||||
public:
|
||||
float p[6];
|
||||
int GetDimension() const { return 6; }
|
||||
|
||||
idVec6() = default;
|
||||
float& operator[](int index) { return p[index]; }
|
||||
float operator[](int index) const { return p[index]; }
|
||||
};
|
||||
|
||||
static_assert(sizeof(idVec5) == 20, "Recovered idVec5 layout changed");
|
||||
static_assert(sizeof(idVec6) == 24, "Recovered idVec6 layout changed");
|
||||
|
||||
class idAngles {
|
||||
public:
|
||||
float pitch;
|
||||
@@ -209,6 +311,66 @@ public:
|
||||
|
||||
float operator[](const int index) const { return (&pitch)[index]; }
|
||||
float& operator[](const int index) { return (&pitch)[index]; }
|
||||
|
||||
idAngles operator+(const idAngles& other) const {
|
||||
return idAngles(pitch + other.pitch, yaw + other.yaw, roll + other.roll);
|
||||
}
|
||||
idAngles operator-(const idAngles& other) const {
|
||||
return idAngles(pitch - other.pitch, yaw - other.yaw, roll - other.roll);
|
||||
}
|
||||
idAngles operator*(const float scale) const {
|
||||
return idAngles(pitch * scale, yaw * scale, roll * scale);
|
||||
}
|
||||
|
||||
idAngles& Normalize360() {
|
||||
float* angle = &pitch;
|
||||
for (int index = 0; index < 3; ++index) {
|
||||
angle[index] -= std::floor(angle[index] / 360.0f) * 360.0f;
|
||||
if (angle[index] >= 360.0f) angle[index] -= 360.0f;
|
||||
if (angle[index] < 0.0f) angle[index] += 360.0f;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
idAngles& Normalize180() {
|
||||
Normalize360();
|
||||
if (pitch > 180.0f) pitch -= 360.0f;
|
||||
if (yaw > 180.0f) yaw -= 360.0f;
|
||||
if (roll > 180.0f) roll -= 360.0f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ToVectors(idVec3* forward, idVec3* right = nullptr,
|
||||
idVec3* up = nullptr) const {
|
||||
constexpr float DEG2RAD = 0.01745329251994329577f;
|
||||
const float sy = std::sin(yaw * DEG2RAD);
|
||||
const float cy = std::cos(yaw * DEG2RAD);
|
||||
const float sp = std::sin(pitch * DEG2RAD);
|
||||
const float cp = std::cos(pitch * DEG2RAD);
|
||||
const float sr = std::sin(roll * DEG2RAD);
|
||||
const float cr = std::cos(roll * DEG2RAD);
|
||||
if (forward != nullptr) forward->Set(cp * cy, cp * sy, -sp);
|
||||
if (right != nullptr) right->Set(
|
||||
cr * sy - sr * sp * cy,
|
||||
-(sr * sp * sy + cr * cy),
|
||||
-sr * cp);
|
||||
if (up != nullptr) up->Set(
|
||||
cr * sp * cy + sr * sy,
|
||||
cr * sp * sy - sr * cy,
|
||||
cr * cp);
|
||||
}
|
||||
|
||||
idVec3 ToForward() const {
|
||||
idVec3 result;
|
||||
ToVectors(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
idMat3 ToMat3() const {
|
||||
idMat3 result;
|
||||
ToVectors(&result[0], &result[1], &result[2]);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(idAngles) == 12, "Recovered idAngles layout changed");
|
||||
@@ -227,14 +389,23 @@ public:
|
||||
|
||||
float operator[](const int index) const { return (&x)[index]; }
|
||||
float& operator[](const int index) { return (&x)[index]; }
|
||||
|
||||
idQuat operator+(const idQuat& other) const {
|
||||
return idQuat(x + other.x, y + other.y, z + other.z, w + other.w);
|
||||
}
|
||||
idQuat operator-(const idQuat& other) const {
|
||||
return idQuat(x - other.x, y - other.y, z - other.z, w - other.w);
|
||||
}
|
||||
idQuat operator*(const float scale) const {
|
||||
return idQuat(x * scale, y * scale, z * scale, w * scale);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(idQuat) == 16, "Recovered idQuat layout changed");
|
||||
|
||||
// The Xbox 360 type-information stream serializes the dynamic math types by
|
||||
// their three/four-field facades. Keep these definitions allocation-simple on
|
||||
// the standalone recovery targets; the complete idLib target uses BFG's
|
||||
// layout-compatible implementations.
|
||||
// their three/four-field facades. Keep these definitions allocation-simple on
|
||||
// the standalone recovery targets while preserving the recovered public ABI.
|
||||
class idVecX {
|
||||
public:
|
||||
idVecX() : size(0), alloced(0), p(nullptr) {}
|
||||
@@ -268,7 +439,7 @@ public:
|
||||
float& operator[](const int index) { return p[index]; }
|
||||
float operator[](const int index) const { return p[index]; }
|
||||
|
||||
private:
|
||||
public:
|
||||
int size;
|
||||
int alloced;
|
||||
float* p;
|
||||
@@ -319,7 +490,7 @@ public:
|
||||
return mat + row * numColumns;
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
int numRows;
|
||||
int numColumns;
|
||||
int alloced;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
class idVec2i {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
|
||||
idVec2i() = default;
|
||||
idVec2i(const int newX, const int newY) : x(newX), y(newY) {}
|
||||
void Set(const int newX, const int newY) { x = newX; y = newY; }
|
||||
void Zero() { x = 0; y = 0; }
|
||||
int operator[](const int index) const {
|
||||
assert(index >= 0 && index < 2); return (&x)[index];
|
||||
}
|
||||
int& operator[](const int index) {
|
||||
assert(index >= 0 && index < 2); return (&x)[index];
|
||||
}
|
||||
bool operator==(const idVec2i& other) const { return x == other.x && y == other.y; }
|
||||
bool operator!=(const idVec2i& other) const { return !(*this == other); }
|
||||
};
|
||||
|
||||
class idVec3i {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
|
||||
idVec3i() = default;
|
||||
idVec3i(const int newX, const int newY, const int newZ)
|
||||
: x(newX), y(newY), z(newZ) {}
|
||||
void Set(const int newX, const int newY, const int newZ) {
|
||||
x = newX; y = newY; z = newZ;
|
||||
}
|
||||
void Zero() { x = 0; y = 0; z = 0; }
|
||||
int operator[](const int index) const {
|
||||
assert(index >= 0 && index < 3); return (&x)[index];
|
||||
}
|
||||
int& operator[](const int index) {
|
||||
assert(index >= 0 && index < 3); return (&x)[index];
|
||||
}
|
||||
bool operator==(const idVec3i& other) const {
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
bool operator!=(const idVec3i& other) const { return !(*this == other); }
|
||||
};
|
||||
|
||||
static_assert(sizeof(idVec2i) == 8, "Recovered idVec2i ABI changed");
|
||||
static_assert(sizeof(idVec3i) == 12, "Recovered idVec3i ABI changed");
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "idlib/math/vector.h"
|
||||
|
||||
Reference in New Issue
Block a user