mirror of https://github.com/zeldaret/mm.git
295 lines
6.6 KiB
C
295 lines
6.6 KiB
C
#include "global.h"
|
|
|
|
/**
|
|
* Calculates the distances between `a` and `b`
|
|
*/
|
|
f32 OLib_Vec3fDist(Vec3f* a, Vec3f* b) {
|
|
f32 dx = a->x - b->x;
|
|
f32 dy = a->y - b->y;
|
|
f32 dz = a->z - b->z;
|
|
|
|
return sqrtf(SQ(dx) + SQ(dy) + SQ(dz));
|
|
}
|
|
|
|
/**
|
|
* Calculates the distances between `a` and `b`, and outputs the vector
|
|
* created by the difference into `dest`
|
|
*/
|
|
f32 OLib_Vec3fDistOutDiff(Vec3f* a, Vec3f* b, Vec3f* dest) {
|
|
dest->x = a->x - b->x;
|
|
dest->y = a->y - b->y;
|
|
dest->z = a->z - b->z;
|
|
|
|
return sqrtf(SQ(dest->x) + SQ(dest->y) + SQ(dest->z));
|
|
}
|
|
|
|
/**
|
|
* Calculates the distances on the xz plane between `a` and `b`
|
|
*/
|
|
f32 OLib_Vec3fDistXZ(Vec3f* a, Vec3f* b) {
|
|
return sqrtf(SQ(a->x - b->x) + SQ(a->z - b->z));
|
|
}
|
|
|
|
/**
|
|
* Clamps `val` to a maximum of -`min` as `val` approaches zero, and a minimum of
|
|
* `min` as `val` approaches zero
|
|
*/
|
|
f32 OLib_ClampMinDist(f32 val, f32 min) {
|
|
if (val < 0.0f) {
|
|
return CLAMP_MAX(val, -min);
|
|
} else {
|
|
return CLAMP_MIN(val, min);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clamps `val` to a minimum of -`max` as `val` approaches -`max`, and a maximum of `max`
|
|
* as `val` approaches `max`
|
|
*/
|
|
f32 OLib_ClampMaxDist(f32 val, f32 max) {
|
|
if (val < 0.0f) {
|
|
return CLAMP_MIN(val, -max);
|
|
} else {
|
|
return CLAMP_MAX(val, max);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes the difference of points b and a, and creates a normal vector
|
|
*/
|
|
Vec3f* OLib_Vec3fDistNormalize(Vec3f* dest, Vec3f* a, Vec3f* b) {
|
|
Vec3f v1;
|
|
Vec3f v2;
|
|
f32 dist;
|
|
|
|
v1.x = b->x - a->x;
|
|
v1.y = b->y - a->y;
|
|
v1.z = b->z - a->z;
|
|
|
|
dist = OLib_ClampMinDist(sqrtf(SQXYZ(v1)), 0.01f);
|
|
|
|
v2.x = v1.x / dist;
|
|
v2.y = v1.y / dist;
|
|
v2.z = v1.z / dist;
|
|
|
|
*dest = v2;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Takes the spherical coordinate `sph`, and converts it into a x,y,z position
|
|
*/
|
|
Vec3f* OLib_VecSphToVec3f(Vec3f* dest, VecSph* sph) {
|
|
Vec3f v;
|
|
f32 sinPitch;
|
|
f32 cosPitch = Math_CosS(sph->pitch);
|
|
f32 sinYaw;
|
|
f32 cosYaw = Math_CosS(sph->yaw);
|
|
|
|
sinPitch = Math_SinS(sph->pitch);
|
|
sinYaw = Math_SinS(sph->yaw);
|
|
|
|
v.x = sph->r * sinPitch * sinYaw;
|
|
v.y = sph->r * cosPitch;
|
|
v.z = sph->r * sinPitch * cosYaw;
|
|
|
|
*dest = v;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Takes the geographic point `sph` and converts it into a x,y,z position
|
|
*/
|
|
Vec3f* OLib_VecSphGeoToVec3f(Vec3f* dest, VecSph* sph) {
|
|
VecSph geo;
|
|
|
|
geo.r = sph->r;
|
|
geo.pitch = 0x4000 - sph->pitch;
|
|
geo.yaw = sph->yaw;
|
|
|
|
return OLib_VecSphToVec3f(dest, &geo);
|
|
}
|
|
|
|
/**
|
|
* Takes the point `vec`, and converts it into a spherical coordinate
|
|
*/
|
|
VecSph* OLib_Vec3fToVecSph(VecSph* dest, Vec3f* vec) {
|
|
VecSph sph;
|
|
f32 distSquared = SQ(vec->x) + SQ(vec->z);
|
|
f32 dist = sqrtf(distSquared);
|
|
|
|
if ((dist == 0.0f) && (vec->y == 0.0f)) {
|
|
sph.pitch = 0;
|
|
} else {
|
|
sph.pitch = DEGF_TO_BINANG(RADF_TO_DEGF(func_80086B30(dist, vec->y)));
|
|
}
|
|
|
|
sph.r = sqrtf(SQ(vec->y) + distSquared);
|
|
if ((vec->x == 0.0f) && (vec->z == 0.0f)) {
|
|
sph.yaw = 0;
|
|
} else {
|
|
sph.yaw = DEGF_TO_BINANG(RADF_TO_DEGF(func_80086B30(vec->x, vec->z)));
|
|
}
|
|
|
|
*dest = sph;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Takes the point `vec`, and converts it to a geographic coordinate
|
|
*/
|
|
VecSph* OLib_Vec3fToVecSphGeo(VecSph* dest, Vec3f* vec) {
|
|
VecSph sph;
|
|
|
|
OLib_Vec3fToVecSph(&sph, vec);
|
|
sph.pitch = 0x4000 - sph.pitch;
|
|
|
|
*dest = sph;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Takes the differences of positions `a` and `b`, and converts them to spherical coordinates
|
|
*/
|
|
VecSph* OLib_Vec3fDiffToVecSph(VecSph* dest, Vec3f* a, Vec3f* b) {
|
|
Vec3f sph;
|
|
|
|
sph.x = b->x - a->x;
|
|
sph.y = b->y - a->y;
|
|
sph.z = b->z - a->z;
|
|
|
|
return OLib_Vec3fToVecSph(dest, &sph);
|
|
}
|
|
|
|
/**
|
|
* Takes the difference of positions `a` and `b`, and converts them to geographic coordinates
|
|
*/
|
|
VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* dest, Vec3f* a, Vec3f* b) {
|
|
Vec3f sph;
|
|
|
|
sph.x = b->x - a->x;
|
|
sph.y = b->y - a->y;
|
|
sph.z = b->z - a->z;
|
|
|
|
return OLib_Vec3fToVecSphGeo(dest, &sph);
|
|
}
|
|
|
|
/**
|
|
* Takes the sum of positions `a` (x,y,z coordinates) and `sph` (geographic coordinates), result is in x,y,z position
|
|
* Identical to Quake_AddVec from OoT
|
|
*/
|
|
Vec3f* OLib_VecSphAddToVec3f(Vec3f* dest, Vec3f* a, VecSph* sph) {
|
|
Vec3f vec;
|
|
Vec3f b;
|
|
|
|
OLib_VecSphGeoToVec3f(&b, sph);
|
|
vec.x = a->x + b.x;
|
|
vec.y = a->y + b.y;
|
|
vec.z = a->z + b.z;
|
|
|
|
*dest = vec;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Gets the pitch/yaw of the vector formed from `b`-`a`, result is in radians
|
|
*/
|
|
Vec3f* OLib_Vec3fDiffRad(Vec3f* dest, Vec3f* a, Vec3f* b) {
|
|
Vec3f anglesRad;
|
|
|
|
anglesRad.x = func_80086B30(b->z - a->z, b->y - a->y);
|
|
anglesRad.y = func_80086B30(b->x - a->x, b->z - a->z);
|
|
anglesRad.z = 0;
|
|
|
|
*dest = anglesRad;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Gets the pitch/yaw of the vector formed from `b`-`a`, result is in degrees
|
|
*/
|
|
Vec3f* OLib_Vec3fDiffDegF(Vec3f* dest, Vec3f* a, Vec3f* b) {
|
|
Vec3f anglesRad;
|
|
Vec3f anglesDegrees;
|
|
|
|
OLib_Vec3fDiffRad(&anglesRad, a, b);
|
|
|
|
anglesDegrees.x = RADF_TO_DEGF(anglesRad.x);
|
|
anglesDegrees.y = RADF_TO_DEGF(anglesRad.y);
|
|
anglesDegrees.z = 0.0f;
|
|
|
|
*dest = anglesDegrees;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Gets the pitch/yaw of the vector formed from `b`-`a`, result is in binary degrees
|
|
*/
|
|
Vec3s* OLib_Vec3fDiffBinAng(Vec3s* dest, Vec3f* a, Vec3f* b) {
|
|
Vec3f anglesRad;
|
|
Vec3s anglesBinAng;
|
|
|
|
OLib_Vec3fDiffRad(&anglesRad, a, b);
|
|
|
|
anglesBinAng.x = DEGF_TO_BINANG(RADF_TO_DEGF(anglesRad.x));
|
|
anglesBinAng.y = DEGF_TO_BINANG(RADF_TO_DEGF(anglesRad.y));
|
|
anglesBinAng.z = 0.0f;
|
|
|
|
*dest = anglesBinAng;
|
|
|
|
return dest;
|
|
}
|
|
|
|
/**
|
|
* Gets a x,y,z position diff depending on the dbCamera mode
|
|
*/
|
|
void OLib_DbCameraVec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) {
|
|
VecSph sph;
|
|
|
|
switch (mode) {
|
|
case 1:
|
|
OLib_Vec3fDiffToVecSphGeo(&sph, &a->pos, b);
|
|
sph.yaw -= a->rot.y;
|
|
OLib_VecSphGeoToVec3f(dest, &sph);
|
|
break;
|
|
case 2:
|
|
dest->x = b->x - a->pos.x;
|
|
dest->y = b->y - a->pos.y;
|
|
dest->z = b->z - a->pos.z;
|
|
break;
|
|
default:
|
|
*dest = *b;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets a x,y,z position sum depending on the dbCamera mode
|
|
*/
|
|
void OLib_DbCameraVec3fSum(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) {
|
|
VecSph sph;
|
|
|
|
switch (mode) {
|
|
case 1:
|
|
OLib_Vec3fToVecSphGeo(&sph, b);
|
|
sph.yaw += a->rot.y;
|
|
OLib_VecSphAddToVec3f(dest, &a->pos, &sph);
|
|
break;
|
|
case 2:
|
|
dest->x = a->pos.x + b->x;
|
|
dest->y = a->pos.y + b->y;
|
|
dest->z = a->pos.z + b->z;
|
|
break;
|
|
default:
|
|
*dest = *b;
|
|
break;
|
|
}
|
|
}
|