mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-04 02:38:00 +03:00
271 lines
No EOL
6.1 KiB
C++
271 lines
No EOL
6.1 KiB
C++
#include "framework.h"
|
|
#include "Specific\trmath.h"
|
|
#include <cmath>
|
|
#include "Specific\prng.h"
|
|
|
|
using namespace TEN::Math::Random;
|
|
|
|
short ANGLE(float angle)
|
|
{
|
|
return angle * 65536.0f / 360.0f;
|
|
}
|
|
|
|
short FROM_DEGREES(float angle)
|
|
{
|
|
return angle * 65536.0f / 360.0f;
|
|
}
|
|
|
|
short FROM_RAD(float angle)
|
|
{
|
|
return angle / RADIAN * 65536.0f / 360.0f;
|
|
}
|
|
|
|
float TO_DEGREES(short angle)
|
|
{
|
|
return lround(angle * 360.0f / 65536.0f);
|
|
}
|
|
|
|
float TO_RAD(short angle)
|
|
{
|
|
return angle * 360.0f / 65536.0f * RADIAN;
|
|
}
|
|
|
|
const float lerp(float v0, float v1, float t)
|
|
{
|
|
return (1 - t) * v0 + t * v1;
|
|
}
|
|
|
|
const Vector3 getRandomVector()
|
|
{
|
|
Vector3 v = {GenerateFloat(-1,1),GenerateFloat(-1,1),GenerateFloat(-1,1)};
|
|
v.Normalize();
|
|
return v;
|
|
}
|
|
|
|
const Vector3 getRandomVectorInCone(const Vector3& direction, const float angleDegrees)
|
|
{
|
|
float x = GenerateFloat(-angleDegrees, angleDegrees) * RADIAN;
|
|
float y = GenerateFloat(-angleDegrees, angleDegrees) * RADIAN;
|
|
float z = GenerateFloat(-angleDegrees, angleDegrees) * RADIAN;
|
|
Matrix m = Matrix::CreateRotationX(x)* Matrix::CreateRotationY(y) * Matrix::CreateRotationZ(z);
|
|
Vector3 result = direction.TransformNormal(direction, m);
|
|
result.Normalize();
|
|
return result;
|
|
}
|
|
|
|
float phd_sin(short a)
|
|
{
|
|
return sin(TO_RAD(a));
|
|
}
|
|
|
|
float phd_cos(short a)
|
|
{
|
|
return cos(TO_RAD(a));
|
|
}
|
|
|
|
int mGetAngle(int x1, int y1, int x2, int y2)
|
|
{
|
|
return (65536 - phd_atan(x2 - x1, y2 - y1)) % 65536;
|
|
}
|
|
|
|
int phd_atan(int x, int y)
|
|
{
|
|
return FROM_RAD(atan2(y, x));
|
|
}
|
|
|
|
void phd_GetVectorAngles(int x, int y, int z, short* angles)
|
|
{
|
|
const auto angle = atan2(x, z);
|
|
|
|
auto vector = Vector3(x, y, z);
|
|
const auto matrix = Matrix::CreateRotationY(-angle);
|
|
Vector3::Transform(vector, matrix, vector);
|
|
|
|
angles[0] = FROM_RAD(angle);
|
|
angles[1] = FROM_RAD(-atan2(y, vector.z));
|
|
}
|
|
|
|
int phd_Distance(PHD_3DPOS* first, PHD_3DPOS* second)
|
|
{
|
|
auto v1 = Vector3(first->xPos, first->yPos, first->zPos);
|
|
auto v2 = Vector3(second->xPos, second->yPos, second->zPos);
|
|
return (int)round(Vector3::Distance(v1, v2));
|
|
}
|
|
|
|
void phd_RotBoundingBoxNoPersp(PHD_3DPOS* pos, BOUNDING_BOX* bounds, BOUNDING_BOX* tbounds)
|
|
{
|
|
Matrix world = Matrix::CreateFromYawPitchRoll(
|
|
TO_RAD(pos->yRot),
|
|
TO_RAD(pos->xRot),
|
|
TO_RAD(pos->zRot)
|
|
);
|
|
|
|
Vector3 bMin = Vector3(bounds->X1, bounds->Y1, bounds->Z1);
|
|
Vector3 bMax = Vector3(bounds->X2, bounds->Y2, bounds->Z2);
|
|
|
|
bMin = Vector3::Transform(bMin, world);
|
|
bMax = Vector3::Transform(bMax, world);
|
|
|
|
tbounds->X1 = bMin.x;
|
|
tbounds->X2 = bMax.x;
|
|
tbounds->Y1 = bMin.y;
|
|
tbounds->Y2 = bMax.y;
|
|
tbounds->Z1 = bMin.z;
|
|
tbounds->Z2 = bMax.z;
|
|
}
|
|
|
|
void InterpolateAngle(short angle, short* rotation, short* outAngle, int shift)
|
|
{
|
|
int deltaAngle = angle - *rotation;
|
|
|
|
if (deltaAngle < -32768)
|
|
deltaAngle += 65536;
|
|
else if (deltaAngle > 32768)
|
|
deltaAngle -= 65536;
|
|
|
|
if (outAngle)
|
|
*outAngle = static_cast<short>(deltaAngle);
|
|
|
|
*rotation += static_cast<short>(deltaAngle >> shift);
|
|
}
|
|
|
|
void GetMatrixFromTrAngle(Matrix* matrix, short* frameptr, int index)
|
|
{
|
|
short* ptr = &frameptr[0];
|
|
|
|
ptr += 9;
|
|
for (int i = 0; i < index; i++)
|
|
{
|
|
ptr += ((*ptr & 0xc000) == 0 ? 2 : 1);
|
|
}
|
|
|
|
int rot0 = *ptr++;
|
|
int frameMode = (rot0 & 0xc000);
|
|
|
|
int rot1;
|
|
int rotX;
|
|
int rotY;
|
|
int rotZ;
|
|
|
|
switch (frameMode)
|
|
{
|
|
case 0:
|
|
rot1 = *ptr++;
|
|
rotX = ((rot0 & 0x3ff0) >> 4);
|
|
rotY = (((rot1 & 0xfc00) >> 10) | ((rot0 & 0xf) << 6) & 0x3ff);
|
|
rotZ = ((rot1) & 0x3ff);
|
|
|
|
*matrix = Matrix::CreateFromYawPitchRoll(rotY * (360.0f / 1024.0f) * RADIAN,
|
|
rotX * (360.0f / 1024.0f) * RADIAN,
|
|
rotZ * (360.0f / 1024.0f) * RADIAN);
|
|
break;
|
|
|
|
case 0x4000:
|
|
*matrix = Matrix::CreateRotationX((rot0 & 0xfff) * (360.0f / 4096.0f) * RADIAN);
|
|
break;
|
|
|
|
case 0x8000:
|
|
*matrix = Matrix::CreateRotationY((rot0 & 0xfff) * (360.0f / 4096.0f) * RADIAN);
|
|
break;
|
|
|
|
case 0xc000:
|
|
*matrix = Matrix::CreateRotationZ((rot0 & 0xfff) * (360.0f / 4096.0f) * RADIAN);
|
|
break;
|
|
}
|
|
}
|
|
|
|
BoundingOrientedBox TO_DX_BBOX(PHD_3DPOS pos, BOUNDING_BOX* box)
|
|
{
|
|
Vector3 boxCentre = Vector3((box->X2 + box->X1) / 2.0f, (box->Y2 + box->Y1) / 2.0f, (box->Z2 + box->Z1) / 2.0f);
|
|
Vector3 boxExtent = Vector3((box->X2 - box->X1) / 2.0f, (box->Y2 - box->Y1) / 2.0f, (box->Z2 - box->Z1) / 2.0f);
|
|
Quaternion rotation = Quaternion::CreateFromYawPitchRoll(TO_RAD(pos.yRot), TO_RAD(pos.xRot), TO_RAD(pos.zRot));
|
|
|
|
BoundingOrientedBox result;
|
|
BoundingOrientedBox(boxCentre, boxExtent, Vector4::UnitY).Transform(result, 1, rotation, Vector3(pos.xPos, pos.yPos, pos.zPos));
|
|
return result;
|
|
}
|
|
|
|
|
|
__int64 FP_Mul(__int64 a, __int64 b)
|
|
{
|
|
return (int)((((__int64)a * (__int64)b)) >> FP_SHIFT);
|
|
}
|
|
|
|
__int64 FP_Div(__int64 a, __int64 b)
|
|
{
|
|
return (int)(((a) / (b >> 8)) << 8);
|
|
}
|
|
|
|
void FP_VectorMul(PHD_VECTOR* v, int scale, PHD_VECTOR* result)
|
|
{
|
|
result->x = FP_FromFixed(v->x * scale);
|
|
result->y = FP_FromFixed(v->y * scale);
|
|
result->z = FP_FromFixed(v->z * scale);
|
|
}
|
|
|
|
int FP_DotProduct(PHD_VECTOR* a, PHD_VECTOR* b)
|
|
{
|
|
return ((a->x * b->x) + (a->y * b->y) + (a->z * b->z)) >> W2V_SHIFT;
|
|
}
|
|
|
|
void FP_CrossProduct(PHD_VECTOR* a, PHD_VECTOR* b, PHD_VECTOR* result)
|
|
{
|
|
result->x = ((a->y * b->z) - (a->z * b->y)) >> W2V_SHIFT;
|
|
result->y = ((a->z * b->x) - (a->x * b->z)) >> W2V_SHIFT;
|
|
result->z = ((a->x * b->y) - (a->y * b->x)) >> W2V_SHIFT;
|
|
}
|
|
|
|
void FP_GetMatrixAngles(MATRIX3D* m, short* angles)
|
|
{
|
|
short yaw = phd_atan(m->m22, m->m02);
|
|
short pitch = phd_atan(sqrt((m->m22 * m->m22) + (m->m02 * m->m02)), m->m12);
|
|
|
|
int sy = phd_sin(yaw);
|
|
int cy = phd_cos(yaw);
|
|
short roll = phd_atan(((cy * m->m00) - (sy * m->m20)), ((sy * m->m21) - (cy * m->m01)));
|
|
|
|
if (((m->m12 >= 0) && pitch > 0)
|
|
|| ((m->m12 < 0) && pitch < 0))
|
|
pitch = -pitch;
|
|
|
|
angles[0] = pitch;
|
|
angles[1] = yaw;
|
|
angles[2] = roll;
|
|
}
|
|
|
|
__int64 FP_ToFixed(__int64 value)
|
|
{
|
|
return (value << FP_SHIFT);
|
|
}
|
|
|
|
__int64 FP_FromFixed(__int64 value)
|
|
{
|
|
return (value >> FP_SHIFT);
|
|
}
|
|
|
|
PHD_VECTOR* FP_Normalise(PHD_VECTOR* v)
|
|
{
|
|
long a = v->x >> FP_SHIFT;
|
|
long b = v->y >> FP_SHIFT;
|
|
long c = v->z >> FP_SHIFT;
|
|
|
|
if ((a == 0) && (b == 0) && (c == 0))
|
|
return v;
|
|
|
|
a = a * a;
|
|
b = b * b;
|
|
c = c * c;
|
|
long d = (a + b + c);
|
|
long e = sqrt(abs(d));
|
|
|
|
e <<= FP_SHIFT;
|
|
|
|
long mod = FP_Div(FP_ONE << 8, e);
|
|
mod >>= 8;
|
|
|
|
v->x = FP_Mul(v->x, mod);
|
|
v->y = FP_Mul(v->y, mod);
|
|
v->z = FP_Mul(v->z, mod);
|
|
|
|
return v;
|
|
} |