mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
592 lines
11 KiB
C++
592 lines
11 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
IceTech GPL Source Code
|
|
Copyright (C) 2026 Justin Marshall
|
|
|
|
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
|
|
|
|
IceTech Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
IceTech Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
idVec2 vec2_origin(0.0f, 0.0f);
|
|
idVec3 vec3_origin(0.0f, 0.0f, 0.0f);
|
|
idVec4 vec4_one(1.0f, 1.0f, 1.0f, 1.0f);
|
|
idVec4 vec4_origin(0.0f, 0.0f, 0.0f, 0.0f);
|
|
idVec5 vec5_origin(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
|
|
idVec6 vec6_origin(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
|
|
idVec6 vec6_infinity(idMath::INFINITY, idMath::INFINITY, idMath::INFINITY, idMath::INFINITY, idMath::INFINITY, idMath::INFINITY);
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// idVec2
|
|
//
|
|
//===============================================================
|
|
|
|
/*
|
|
=============
|
|
idVec2::ToString
|
|
=============
|
|
*/
|
|
const char* idVec2::ToString(int precision) const {
|
|
return idStr::FloatArrayToString(ToFloatPtr(), GetDimension(), precision);
|
|
}
|
|
|
|
/*
|
|
=============
|
|
Lerp
|
|
|
|
Linearly inperpolates one vector to another.
|
|
=============
|
|
*/
|
|
void idVec2::Lerp(const idVec2& v1, const idVec2& v2, const float l) {
|
|
if (l <= 0.0f) {
|
|
(*this) = v1;
|
|
}
|
|
else if (l >= 1.0f) {
|
|
(*this) = v2;
|
|
}
|
|
else {
|
|
(*this) = v1 + l * (v2 - v1);
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// idVec3
|
|
//
|
|
//===============================================================
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToYaw
|
|
=============
|
|
*/
|
|
float idVec3::ToYaw(void) const {
|
|
float yaw;
|
|
|
|
if ((y == 0.0f) && (x == 0.0f)) {
|
|
yaw = 0.0f;
|
|
}
|
|
else {
|
|
#ifdef QUAKE4
|
|
yaw = RAD2DEG(idMath::ATan(y, x));
|
|
#else
|
|
yaw = RAD2DEG(atan2(y, x));
|
|
#endif
|
|
if (yaw < 0.0f) {
|
|
yaw += 360.0f;
|
|
}
|
|
}
|
|
|
|
return yaw;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToPitch
|
|
=============
|
|
*/
|
|
float idVec3::ToPitch(void) const {
|
|
float forward;
|
|
float pitch;
|
|
|
|
if ((x == 0.0f) && (y == 0.0f)) {
|
|
if (z > 0.0f) {
|
|
pitch = 90.0f;
|
|
}
|
|
else {
|
|
pitch = 270.0f;
|
|
}
|
|
}
|
|
else {
|
|
forward = (float)idMath::Sqrt(x * x + y * y);
|
|
#ifdef QUAKE4
|
|
pitch = RAD2DEG(idMath::ATan(z, forward));
|
|
#else
|
|
pitch = RAD2DEG(atan2(z, forward));
|
|
#endif
|
|
if (pitch < 0.0f) {
|
|
pitch += 360.0f;
|
|
}
|
|
}
|
|
|
|
return pitch;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToAngles
|
|
=============
|
|
*/
|
|
idAngles idVec3::ToAngles(void) const {
|
|
float forward;
|
|
float yaw;
|
|
float pitch;
|
|
|
|
if ((x == 0.0f) && (y == 0.0f)) {
|
|
yaw = 0.0f;
|
|
if (z > 0.0f) {
|
|
pitch = 90.0f;
|
|
}
|
|
else {
|
|
pitch = 270.0f;
|
|
}
|
|
}
|
|
else {
|
|
#ifdef QUAKE4
|
|
yaw = RAD2DEG(idMath::ATan(y, x));
|
|
#else
|
|
yaw = RAD2DEG(atan2(y, x));
|
|
#endif
|
|
if (yaw < 0.0f) {
|
|
yaw += 360.0f;
|
|
}
|
|
|
|
forward = (float)idMath::Sqrt(x * x + y * y);
|
|
#ifdef QUAKE4
|
|
pitch = RAD2DEG(idMath::ATan(z, forward));
|
|
#else
|
|
pitch = RAD2DEG(atan2(z, forward));
|
|
#endif
|
|
if (pitch < 0.0f) {
|
|
pitch += 360.0f;
|
|
}
|
|
}
|
|
|
|
return idAngles(-pitch, yaw, 0.0f);
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
/*
|
|
=============
|
|
idVec3::ToRadians
|
|
=============
|
|
*/
|
|
rvAngles idVec3::ToRadians(void) const {
|
|
float forward;
|
|
float yaw;
|
|
float pitch;
|
|
|
|
if ((x == 0.0f) && (y == 0.0f)) {
|
|
yaw = 0.0f;
|
|
if (z > 0.0f) {
|
|
pitch = idMath::HALF_PI;
|
|
}
|
|
else {
|
|
pitch = idMath::THREEFOURTHS_PI;
|
|
}
|
|
}
|
|
else {
|
|
yaw = idMath::ATan(y, x);
|
|
if (yaw < 0.0f) {
|
|
yaw += idMath::TWO_PI;
|
|
}
|
|
|
|
forward = (float)idMath::Sqrt(x * x + y * y);
|
|
pitch = idMath::ATan(z, forward);
|
|
if (pitch < 0.0f) {
|
|
pitch += idMath::TWO_PI;
|
|
}
|
|
}
|
|
|
|
return rvAngles(-pitch, yaw, 0.0f);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToPolar
|
|
=============
|
|
*/
|
|
idPolar3 idVec3::ToPolar(void) const {
|
|
float forward;
|
|
float yaw;
|
|
float pitch;
|
|
|
|
if ((x == 0.0f) && (y == 0.0f)) {
|
|
yaw = 0.0f;
|
|
if (z > 0.0f) {
|
|
pitch = 90.0f;
|
|
}
|
|
else {
|
|
pitch = 270.0f;
|
|
}
|
|
}
|
|
else {
|
|
#ifdef QUAKE4
|
|
yaw = RAD2DEG(idMath::ATan(y, x));
|
|
#else
|
|
yaw = RAD2DEG(atan2(y, x));
|
|
#endif
|
|
if (yaw < 0.0f) {
|
|
yaw += 360.0f;
|
|
}
|
|
|
|
forward = (float)idMath::Sqrt(x * x + y * y);
|
|
#ifdef QUAKE4
|
|
pitch = RAD2DEG(idMath::ATan(z, forward));
|
|
#else
|
|
pitch = RAD2DEG(atan2(z, forward));
|
|
#endif
|
|
if (pitch < 0.0f) {
|
|
pitch += 360.0f;
|
|
}
|
|
}
|
|
return idPolar3(idMath::Sqrt(x * x + y * y + z * z), yaw, -pitch);
|
|
}
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToMat3
|
|
=============
|
|
*/
|
|
idMat3 idVec3::ToMat3(void) const {
|
|
idMat3 mat;
|
|
float d;
|
|
|
|
mat[0] = *this;
|
|
d = x * x + y * y;
|
|
if (!d) {
|
|
mat[1][0] = 1.0f;
|
|
mat[1][1] = 0.0f;
|
|
mat[1][2] = 0.0f;
|
|
}
|
|
else {
|
|
d = idMath::InvSqrt(d);
|
|
mat[1][0] = -y * d;
|
|
mat[1][1] = x * d;
|
|
mat[1][2] = 0.0f;
|
|
}
|
|
mat[2] = Cross(mat[1]);
|
|
|
|
return mat;
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
/*
|
|
=============
|
|
idVec3::ToMat3
|
|
=============
|
|
*/
|
|
idMat3 idVec3::ToMat3(int axis) const {
|
|
idMat3 mat;
|
|
float d;
|
|
int index_x = axis % GetDimension();
|
|
int index_y = (axis + 1) % GetDimension();
|
|
int index_z = (axis + 2) % GetDimension();
|
|
float local_x = (*this)[index_x];
|
|
float local_y = (*this)[index_y];
|
|
|
|
mat[axis] = *this;
|
|
d = local_x * local_x + local_y * local_y;
|
|
if (!d) {
|
|
mat[index_y][index_x] = 1.0f;
|
|
mat[index_y][index_y] = 0.0f;
|
|
mat[index_y][index_z] = 0.0f;
|
|
}
|
|
else {
|
|
d = idMath::InvSqrt(d);
|
|
mat[index_y][index_x] = -local_y * d;
|
|
mat[index_y][index_y] = local_x * d;
|
|
mat[index_y][index_z] = 0.0f;
|
|
}
|
|
mat[index_z] = Cross(mat[index_y]);
|
|
|
|
return mat;
|
|
}
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToMat3
|
|
=============
|
|
*/
|
|
idMat3& idVec3::ToMat3(idMat3& mat) const {
|
|
float d;
|
|
|
|
mat[0] = *this;
|
|
d = x * x + y * y;
|
|
if (!d) {
|
|
mat[1][0] = 1.0f;
|
|
mat[1][1] = 0.0f;
|
|
mat[1][2] = 0.0f;
|
|
}
|
|
else {
|
|
d = idMath::InvSqrt(d);
|
|
mat[1][0] = -y * d;
|
|
mat[1][1] = x * d;
|
|
mat[1][2] = 0.0f;
|
|
}
|
|
mat[2] = Cross(mat[1]);
|
|
return mat;
|
|
}
|
|
#endif
|
|
|
|
#ifdef PREY
|
|
// HUMANHEAD nla
|
|
/*
|
|
=============
|
|
idVec3::hhToMat3
|
|
=============
|
|
*/
|
|
idMat3 idVec3::hhToMat3(void) const {
|
|
idVec3 left;
|
|
idVec3 down;
|
|
|
|
// NormalVectors actually returns left and down
|
|
NormalVectors(left, down);
|
|
return idMat3(*this, left, -down);
|
|
}
|
|
|
|
// HUMANHEAD PDM: Vector conversion to/from axis aligned direction masks (6-bit vector compression)
|
|
int idVec3::DirectionMask() const {
|
|
int mask = 0;
|
|
for (int term = 0; term < 3; term++) {
|
|
mask += (*this)[term] < 0 ? 1 << (term << 1) : (*this)[term]>0 ? 1 << ((term << 1) + 1) : 0;
|
|
}
|
|
return mask;
|
|
}
|
|
|
|
idVec3::idVec3(int directionMask) {
|
|
int negativeMask, positiveMask;
|
|
for (int term = 0; term < 3; term++) {
|
|
negativeMask = 1 << (term << 1);
|
|
positiveMask = 1 << ((term << 1) + 1);
|
|
(*this)[term] = (directionMask & negativeMask) ? -1 : (directionMask & positiveMask) ? 1 : 0;
|
|
}
|
|
}
|
|
// HUMANHEAD END
|
|
#endif
|
|
|
|
/*
|
|
=============
|
|
idVec3::ToString
|
|
=============
|
|
*/
|
|
const char* idVec3::ToString(int precision) const {
|
|
return idStr::FloatArrayToString(ToFloatPtr(), GetDimension(), precision);
|
|
}
|
|
|
|
/*
|
|
=============
|
|
Lerp
|
|
|
|
Linearly inperpolates one vector to another.
|
|
=============
|
|
*/
|
|
void idVec3::Lerp(const idVec3& v1, const idVec3& v2, const float l) {
|
|
if (l <= 0.0f) {
|
|
(*this) = v1;
|
|
}
|
|
else if (l >= 1.0f) {
|
|
(*this) = v2;
|
|
}
|
|
else {
|
|
(*this) = v1 + l * (v2 - v1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
=============
|
|
SLerp
|
|
|
|
Spherical linear interpolation from v1 to v2.
|
|
Vectors are expected to be normalized.
|
|
=============
|
|
*/
|
|
#define LERP_DELTA 1e-6
|
|
|
|
void idVec3::SLerp(const idVec3& v1, const idVec3& v2, const float t) {
|
|
float omega, cosom, sinom, scale0, scale1;
|
|
|
|
if (t <= 0.0f) {
|
|
(*this) = v1;
|
|
return;
|
|
}
|
|
else if (t >= 1.0f) {
|
|
(*this) = v2;
|
|
return;
|
|
}
|
|
|
|
cosom = v1 * v2;
|
|
if ((1.0f - cosom) > LERP_DELTA) {
|
|
omega = acos(cosom);
|
|
#ifdef QUAKE4
|
|
sinom = idMath::Sin(omega);
|
|
scale0 = idMath::Sin((1.0f - t) * omega) / sinom;
|
|
scale1 = idMath::Sin(t * omega) / sinom;
|
|
#else
|
|
sinom = sin(omega);
|
|
scale0 = sin((1.0f - t) * omega) / sinom;
|
|
scale1 = sin(t * omega) / sinom;
|
|
#endif
|
|
}
|
|
else {
|
|
scale0 = 1.0f - t;
|
|
scale1 = t;
|
|
}
|
|
|
|
(*this) = (v1 * scale0 + v2 * scale1);
|
|
}
|
|
|
|
/*
|
|
=============
|
|
ProjectSelfOntoSphere
|
|
|
|
Projects the z component onto a sphere.
|
|
=============
|
|
*/
|
|
void idVec3::ProjectSelfOntoSphere(const float radius) {
|
|
float rsqr = radius * radius;
|
|
float len = Length();
|
|
if (len < rsqr * 0.5f) {
|
|
#ifdef QUAKE4
|
|
z = idMath::Sqrt(rsqr - len);
|
|
#else
|
|
z = sqrt(rsqr - len);
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef QUAKE4
|
|
z = rsqr / (2.0f * idMath::Sqrt(len));
|
|
#else
|
|
z = rsqr / (2.0f * sqrt(len));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// idVec4
|
|
//
|
|
//===============================================================
|
|
|
|
/*
|
|
=============
|
|
idVec4::ToString
|
|
=============
|
|
*/
|
|
const char* idVec4::ToString(int precision) const {
|
|
return idStr::FloatArrayToString(ToFloatPtr(), GetDimension(), precision);
|
|
}
|
|
|
|
/*
|
|
=============
|
|
Lerp
|
|
|
|
Linearly inperpolates one vector to another.
|
|
=============
|
|
*/
|
|
void idVec4::Lerp(const idVec4& v1, const idVec4& v2, const float l) {
|
|
if (l <= 0.0f) {
|
|
(*this) = v1;
|
|
}
|
|
else if (l >= 1.0f) {
|
|
(*this) = v2;
|
|
}
|
|
else {
|
|
(*this) = v1 + l * (v2 - v1);
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// idVec5
|
|
//
|
|
//===============================================================
|
|
|
|
/*
|
|
=============
|
|
idVec5::ToString
|
|
=============
|
|
*/
|
|
const char* idVec5::ToString(int precision) const {
|
|
return idStr::FloatArrayToString(ToFloatPtr(), GetDimension(), precision);
|
|
}
|
|
|
|
/*
|
|
=============
|
|
idVec5::Lerp
|
|
=============
|
|
*/
|
|
void idVec5::Lerp(const idVec5& v1, const idVec5& v2, const float l) {
|
|
if (l <= 0.0f) {
|
|
(*this) = v1;
|
|
}
|
|
else if (l >= 1.0f) {
|
|
(*this) = v2;
|
|
}
|
|
else {
|
|
x = v1.x + l * (v2.x - v1.x);
|
|
y = v1.y + l * (v2.y - v1.y);
|
|
z = v1.z + l * (v2.z - v1.z);
|
|
s = v1.s + l * (v2.s - v1.s);
|
|
t = v1.t + l * (v2.t - v1.t);
|
|
}
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// idVec6
|
|
//
|
|
//===============================================================
|
|
|
|
/*
|
|
=============
|
|
idVec6::ToString
|
|
=============
|
|
*/
|
|
const char* idVec6::ToString(int precision) const {
|
|
return idStr::FloatArrayToString(ToFloatPtr(), GetDimension(), precision);
|
|
}
|
|
|
|
|
|
//===============================================================
|
|
//
|
|
// idVecX
|
|
//
|
|
//===============================================================
|
|
|
|
#ifdef QUAKE4
|
|
float idVecX::tempPtr[VECX_MAX_TEMP];
|
|
#else
|
|
float idVecX::temp[VECX_MAX_TEMP + 4];
|
|
float* idVecX::tempPtr = (float*)(((INT_PTR)idVecX::temp + 15) & ~15);
|
|
#endif
|
|
int idVecX::tempIndex = 0;
|
|
|
|
/*
|
|
=============
|
|
idVecX::ToString
|
|
=============
|
|
*/
|
|
const char* idVecX::ToString(int precision) const {
|
|
return idStr::FloatArrayToString(ToFloatPtr(), GetDimension(), precision);
|
|
}
|