mirror of
https://github.com/encounter/Petari.git
synced 2026-03-30 11:34:15 -07:00
416 lines
10 KiB
C++
416 lines
10 KiB
C++
#include "Game/Util/MathUtil.hpp"
|
|
#include "JSystem/JGeometry/TUtil.hpp"
|
|
#include "JSystem/JMath/JMath.hpp"
|
|
#include "JSystem/JMath/JMATrigonometric.hpp"
|
|
|
|
#include "math_types.hpp"
|
|
|
|
#include <cmath>
|
|
|
|
namespace MR {
|
|
f32 getRandom(f32 min, f32 max) {
|
|
return (min + ((max - min) * getRandom()));
|
|
}
|
|
|
|
// getRandom(s32, s32)
|
|
|
|
f32 getRandomDegree() {
|
|
return minDegree + (maxDegree * getRandom());
|
|
}
|
|
|
|
void calcRandomVec(TVec3f *pOut, f32 a2, f32 a3) {
|
|
f32 v10 = (a2 + ((a3 - a2) * getRandom()));
|
|
f32 v11 = (a2 + ((a3 - a2) * getRandom()));
|
|
f32 v12 = getRandom();
|
|
|
|
f32 dist = a3 - a2;
|
|
pOut->set<f32>((a2 + (dist * v12)), v11, v10);
|
|
}
|
|
|
|
u8 isHalfProbability() {
|
|
return MR::getRandom() < 0.5f;
|
|
}
|
|
|
|
f32 getSignHalfProbability() {
|
|
if (isHalfProbability()) {
|
|
return -1.0f;
|
|
}
|
|
|
|
return 1.0f;
|
|
}
|
|
|
|
void getRandomVector(TVec3f *pOut, f32 a2) {
|
|
f32 z = (-a2 + ((a2 - -a2) * getRandom()));
|
|
f32 y = (-a2 + ((a2 - -a2) * getRandom()));
|
|
pOut->set((-a2 + ((a2 - -a2) * getRandom())), y, z);
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
// stack places randVec and otherVec wrongly
|
|
void addRandomVector(TVec3f *pOut, const TVec3f &rOtherVec, f32 a3) {
|
|
|
|
f32 x = -a3 + ((a3 - -a3) * getRandom());
|
|
f32 y = -a3 + ((a3 - -a3) * getRandom());
|
|
f32 z = -a3 + ((a3 - -a3) * getRandom());
|
|
|
|
TVec3f randVec;
|
|
randVec.x = x;
|
|
randVec.y = y;
|
|
randVec.z = z;
|
|
|
|
TVec3f otherVec(rOtherVec);
|
|
otherVec.add(randVec);
|
|
pOut->set(otherVec);
|
|
}
|
|
#endif
|
|
|
|
void turnRandomVector(TVec3f *pOut, const TVec3f &rOtherVec, f32 a3) {
|
|
f32 mag = PSVECMag((Vec*)(&rOtherVec));
|
|
addRandomVector(pOut, rOtherVec, a3);
|
|
|
|
if (isNearZero(*pOut, 0.001f)) {
|
|
pOut->set(rOtherVec);
|
|
}
|
|
else {
|
|
pOut->setLength(mag);
|
|
}
|
|
}
|
|
|
|
|
|
f32 getInterpolateValue(f32 a1, f32 a2, f32 a3) {
|
|
return (a2 + (a1 * (a3 - a2)));
|
|
}
|
|
|
|
f32 getLinerValue(f32 a1, f32 a2, f32 a3, f32 a4) {
|
|
return (a2 + (a1 / a4) * (a3 - a2));
|
|
}
|
|
|
|
f32 getLinerValueFromMinMax(f32 a1, f32 a2, f32 a3, f32 a4, f32 a5) {
|
|
f32 val = (JGeometry::TUtil<f32>::clamp(a1, a2, a3) - a2) / (a3 - a2);
|
|
return a4 + ((a5 - a4) * val);
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
// wrong register orders
|
|
f32 getEaseInValue(f32 a1, f32 a2, f32 a3, f32 a4) {
|
|
f32 val = (1.0f - JMACosRadian((((a1 / a4) * PI) * 0.5f)));
|
|
return a2 + ((a3 - a2) * val);
|
|
}
|
|
#endif
|
|
|
|
#ifdef NON_MATCHING
|
|
// wrong register orders
|
|
f32 getEaseOutValue(f32 a1, f32 a2, f32 a3, f32 a4) {
|
|
f32 val = (JMASinRadian((((a1 / a4) * PI) * 0.5f)) * (a3 - a2));
|
|
return a2 + val;
|
|
}
|
|
#endif
|
|
|
|
// MR::getEaseInOutValue
|
|
// MR::getScaleWithReactionValueZeroToOne
|
|
// MR::getConvergeVibrationValue
|
|
// MR::getReduceVibrationValue
|
|
|
|
void makeAxisFrontUp(TVec3f *a1, TVec3f *a2, const TVec3f &a3, const TVec3f &a4) {
|
|
PSVECCrossProduct((Vec*)&a4, (Vec*)&a3, (Vec*)a1);
|
|
PSVECNormalize((Vec*)a1, (Vec*)a1);
|
|
PSVECCrossProduct((Vec*)&a3, (Vec*)a1, (Vec*)a2);
|
|
}
|
|
|
|
// MR::makeAxisFrontSide
|
|
// MR::makeAxisUpFront
|
|
// MR::makeAxisUpSide
|
|
// MR::makeAxisVerticalZX
|
|
// MR::makeAxisCrossPlane
|
|
// MR::makeAxisAndCosignVecToVec
|
|
// MR::calcPerpendicFootToLine
|
|
// MR::calcPerpendicFootToLineInside
|
|
|
|
// etc
|
|
|
|
void clampLength(TVec3f *a1, const TVec3f &a2, f32 a3) {
|
|
if (a2.squared() > (a3 * a3)) {
|
|
f32 sqr = a2.squared();
|
|
|
|
if (sqr <= 0.0000038146973f) {
|
|
a1->zero();
|
|
}
|
|
else {
|
|
f32 inv_sqr = JGeometry::TUtil<f32>::inv_sqrt(sqr);
|
|
a1->scale((inv_sqr * a3), a2);
|
|
}
|
|
|
|
}
|
|
else {
|
|
a1->set(a2);
|
|
}
|
|
}
|
|
|
|
// MR::convergeRadian(f32, f32, f32)
|
|
|
|
bool isInRange(f32 a1, f32 a2, f32 a3) {
|
|
if (a2 > a3) {
|
|
if (a1 < a3) {
|
|
return false;
|
|
}
|
|
else {
|
|
return !(a1 > a2);
|
|
}
|
|
}
|
|
else {
|
|
if (a1 < a2) {
|
|
return false;
|
|
}
|
|
else {
|
|
return !(a1 > a3);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*f32 calcRotateY(f32 a1, f32 a2) {
|
|
f32 val = JMath::sAtanTable.atan2_(-a2, a1);
|
|
return (minDegree + fmod((maxDegree + ((90.0f + (val * 57.295776f)) - minDegree)), maxDegree));
|
|
}*/
|
|
|
|
|
|
f32 calcDistanceXY(const TVec3f &a1, const TVec3f &a2) {
|
|
f32 x_diff = a1.x - a2.x;
|
|
f32 y_diff = a1.y - a2.y;
|
|
return JGeometry::TUtil<f32>::sqrt((x_diff * x_diff) + (y_diff * y_diff));
|
|
}
|
|
|
|
bool isNearZero(f32 a1, f32 a2) {
|
|
if (a1 < 0.0f) {
|
|
a1 = -a1;
|
|
}
|
|
|
|
if (a1 < a2) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool isNearZero(const TVec3f &rVec, f32 a2) {
|
|
f32 v2 = rVec.x;
|
|
if ( v2 > a2 )
|
|
return 0;
|
|
|
|
f32 v4 = -a2;
|
|
if ( v2 < -a2 )
|
|
return 0;
|
|
|
|
f32 v5 = rVec.y;
|
|
if ( v5 > a2 )
|
|
return 0;
|
|
|
|
if ( v5 < v4 )
|
|
return 0;
|
|
|
|
f32 v6 = rVec.z;
|
|
|
|
if ( v6 > a2 )
|
|
return 0;
|
|
|
|
return !(rVec.z < -a2);
|
|
}
|
|
|
|
|
|
f32 diffAngleAbs(f32 a1, f32 a2) {
|
|
f32 normalize = normalizeAngleAbs(a1 - a2);
|
|
|
|
if (normalize > PI) {
|
|
normalize = (TWO_PI - normalize);
|
|
}
|
|
|
|
return normalize;
|
|
}
|
|
|
|
f32 normalizeAngleAbs(f32 angle) {
|
|
while (1) {
|
|
if (angle < 0.0f) {
|
|
angle += TWO_PI;
|
|
}
|
|
else {
|
|
if (!(angle > TWO_PI)) {
|
|
return angle;
|
|
}
|
|
else {
|
|
angle -= TWO_PI;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isAngleBetween(f32 a1, f32 a2, f32 a3) {
|
|
f32 a1_n = normalizeAngleAbs(a1);
|
|
f32 a2_n = normalizeAngleAbs(a2);
|
|
f32 a3_n = normalizeAngleAbs(a3);
|
|
|
|
if (a3_n > a2_n) {
|
|
f32 val = a3_n;
|
|
a3_n = a2_n;
|
|
a2_n = val;
|
|
}
|
|
|
|
bool res = false;
|
|
|
|
if (a1_n >= a3_n && a1_n <= a2_n) {
|
|
res = true;
|
|
}
|
|
|
|
if ((a2_n - a3_n) > PI) {
|
|
res = !res;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
// register use is wrong, and mull is in wrong order for isAngleBetween
|
|
f32 blendAngle(f32 a1, f32 a2, f32 a3) {
|
|
f32 a1_n = normalizeAngleAbs(a1);
|
|
f32 a2_n = normalizeAngleAbs(a2);
|
|
|
|
if (!isAngleBetween(0.5f * (a1_n + a2_n), a1_n, a2_n)) {
|
|
if (a1_n < a2_n) {
|
|
a2_n += TWO_PI;
|
|
}
|
|
else {
|
|
a1_n += TWO_PI;
|
|
}
|
|
}
|
|
|
|
return normalizeAngleAbs((((1.0f - a3) * a1_n) + (a3 * a2_n)));
|
|
}
|
|
#endif
|
|
|
|
u8 lerp(u8 a1, u8 a2, f32 a3) {
|
|
return JGeometry::TUtil<f32>::clamp(a1 + (a3 * (a2 - a1)), 0.0f, 255.0f);
|
|
}
|
|
|
|
/*#ifdef NON_MATCHING
|
|
_GXColor lerp(_GXColor a1, _GXColor a2, f32 a3) {
|
|
u8 v6 = lerp(a1.a, a2.a, a3);
|
|
u8 v7 = lerp(a1.b, a2.b, a3);
|
|
u8 v8 = lerp(a1.g, a2.b, a3);
|
|
u8 thing = lerp(a1.r, a2.r, a3);
|
|
|
|
return (v6 | ((v7 << 8) & 0xFF00 | ((v8 << 16) & 0xFF000 | thing << 24)) & 0xFFFF00FF) & 0xFFFFFF00;
|
|
}
|
|
#endif*/
|
|
|
|
f32 vecKillElement(const TVec3f &a1, const TVec3f &a2, TVec3f *a3) {
|
|
if (isNearZero(a2, 0.001f)) {
|
|
*a3 = a1;
|
|
return 0.0f;
|
|
}
|
|
|
|
return PSVECKillElement((const Vec*)&a1, (const Vec*)&a2, (const Vec*)a3);
|
|
}
|
|
|
|
void vecScaleAdd(const register TVec3f *a1, const register TVec3f *a2, register f32 a3) {
|
|
__asm {
|
|
psq_l f0, 0(a1), 0, 0
|
|
psq_l f3, 0(a2), 0, 0
|
|
psq_l f2, 8(a1), 1, 0
|
|
psq_l f4, 8(a2), 1, 0
|
|
ps_madds0 f0, f3, a3, f0
|
|
ps_madds0 f2, f4, a3, f2
|
|
psq_st f0, 0(a1), 0, 0
|
|
psq_st f2, 8(a1), 1, 0
|
|
}
|
|
}
|
|
|
|
void PSvecBlend(const register TVec3f *a1, const register TVec3f *a2, register TVec3f *a3, register f32 a4, register f32 a5) {
|
|
__asm {
|
|
psq_l f0, 0(a1), 0, 0
|
|
psq_l f3, 8(a1), 1, 0
|
|
ps_muls0 f4, f0, a4
|
|
psq_l f0, 0(a2), 0, 0
|
|
ps_muls0 f3, f3, a4
|
|
psq_l f1, 8(a2), 1, 0
|
|
ps_madds0 f4, f0, f2, f4
|
|
ps_madds0 f3, f1, f2, f3
|
|
psq_st f4, 0(a3), 0, 0
|
|
psq_st f3, 8(a3), 1, 0
|
|
}
|
|
}
|
|
|
|
void vecBlend(const TVec3f &a1, const TVec3f &a2, TVec3f *a3, f32 a4) {
|
|
PSvecBlend(&a1, &a2, a3, 1.0f - a4, a4);
|
|
}
|
|
|
|
// MR::vecBlendNormal
|
|
// MR::vecBlendSphere
|
|
// MR::vecRotAxis
|
|
|
|
void blendColor(_GXColor *a1, const _GXColor &a2, const _GXColor &a3, f32 a4) {
|
|
a1->r = getInterpolateValue(a4, a2.r, a3.r);
|
|
a1->g = getInterpolateValue(a4, a2.g, a3.g);
|
|
a1->b = getInterpolateValue(a4, a2.b, a3.b);
|
|
a1->a = getInterpolateValue(a4, a2.a, a3.a);
|
|
}
|
|
|
|
void blendVec(Vec *a1, const Vec &a2, const Vec &a3, f32 a4) {
|
|
a1->x = getInterpolateValue(a4, a2.x, a3.x);
|
|
a1->y = getInterpolateValue(a4, a2.y, a3.y);
|
|
a1->z = getInterpolateValue(a4, a2.z, a3.z);
|
|
}
|
|
|
|
// MR::turnVecToPlane
|
|
|
|
int getMinAbsElementIndex(const TVec3f &rVec) {
|
|
f64 abs_x = __fabs(rVec.x);
|
|
f64 abs_y = __fabs(rVec.y);
|
|
f64 abs_z = __fabs(rVec.z);
|
|
|
|
if (abs_x < abs_y && abs_x < abs_z) {
|
|
return 0;
|
|
}
|
|
|
|
if (abs_y < abs_z) {
|
|
return 1;
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
|
|
f32 getMaxElement(const TVec3f &rVec) {
|
|
f32* vec_arr = (f32*)(&rVec);
|
|
return vec_arr[getMaxElementIndex(rVec)];
|
|
}
|
|
|
|
f32 getMaxAbsElement(const TVec3f &rVec) {
|
|
f32* vec_arr = (f32*)(&rVec);
|
|
return vec_arr[getMaxAbsElementIndex(rVec)];
|
|
}
|
|
|
|
int getMaxElementIndex(const TVec3f &rVec) {
|
|
if (rVec.x > rVec.y && rVec.x > rVec.z) {
|
|
return 0;
|
|
}
|
|
|
|
if (rVec.y > rVec.z) {
|
|
return 1;
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
|
|
int getMaxAbsElementIndex(const TVec3f &rVec) {
|
|
f64 abs_x = __fabs(rVec.x);
|
|
f64 abs_y = __fabs(rVec.y);
|
|
f64 abs_z = __fabs(rVec.z);
|
|
|
|
if (abs_x > abs_y && abs_x > abs_z) {
|
|
return 0;
|
|
}
|
|
|
|
if (abs_y > abs_z) {
|
|
return 1;
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
}; |