Second pass idLib integration.

This commit is contained in:
Justin Marshall
2026-08-08 19:30:03 -07:00
parent 55a14323f2
commit 1b718f17f6
114 changed files with 9696 additions and 331 deletions
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include "idlib/math/vector.h"
+98
View File
@@ -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");
+141
View File
@@ -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
+9
View File
@@ -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");
+155
View File
@@ -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");
+327
View File
@@ -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");
+26
View File
@@ -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
+2 -2
View File
@@ -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];
};
+105
View File
@@ -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");
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include "idlib/math/vector.h"
+23
View File
@@ -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
+48
View File
@@ -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");
+128
View File
@@ -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");
+44
View File
@@ -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");
+105
View File
@@ -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
+28
View File
@@ -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");
+9
View File
@@ -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");
+131
View File
@@ -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");
+89
View File
@@ -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");
+3 -3
View File
@@ -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
+176 -5
View File
@@ -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;
+51
View File
@@ -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");
+4
View File
@@ -0,0 +1,4 @@
#pragma once
#include "idlib/math/vector.h"