diff options
| -rw-r--r-- | include/m_camera2.h | 8 | ||||
| -rw-r--r-- | include/m_olib.h | 33 | ||||
| -rw-r--r-- | include/macros.h | 2 | ||||
| -rw-r--r-- | include/z64math.h | 20 | ||||
| -rw-r--r-- | src/code/m_olib.c | 212 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Koinobori/ac_koinobori.c | 6 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Toudai/ac_toudai.c | 18 | ||||
| -rw-r--r-- | yamls/jp/code.yaml | 4 |
8 files changed, 278 insertions, 25 deletions
diff --git a/include/m_camera2.h b/include/m_camera2.h new file mode 100644 index 0000000..fa9d81b --- /dev/null +++ b/include/m_camera2.h @@ -0,0 +1,8 @@ +#ifndef M_CAMERA_H +#define M_CAMERA_H + +// these two angle conversion macros are slightly inaccurate +#define CAM_DEG_TO_BINANG(degrees) (s16)((degrees) * ((f32)0xFFFF / 360) + .5f) +#define CAM_BINANG_TO_DEG(binang) ((f32)(binang) * (360.0001525f / 0xFFFF)) + +#endif diff --git a/include/m_olib.h b/include/m_olib.h index 1f25530..0c10d46 100644 --- a/include/m_olib.h +++ b/include/m_olib.h @@ -2,21 +2,24 @@ #define M_OLIB_H #include "ultra64.h" +#include "m_lib.h" +#include "libc64/math64.h" +#include "m_camera2.h" -// void distance_between(); -// void distance_between2(); -// void distance_2d(); -// void never_zero(); -// void limiter(); -// void unitvector_by_2pos(); -// void spolar2world(); -// void sglobe2world(); -// void world2spolar(); -// void world2sglobe(); -// void spolar_by_2pos(); -// void sglobe_by_2pos(); -// void radianxy_by_2pos(); -// void degreexy_by_2pos(); -// void sanglexy_by_2pos(); +f32 distance_between(xyz_t* a, xyz_t* b); +f32 distance_between2(xyz_t* a, xyz_t* b, xyz_t* dest); +f32 distance_2d(xyz_t* a, xyz_t* b); +f32 never_zero(f32 val, f32 min); +f32 limiter(f32 val, f32 max); +xyz_t unitvector_by_2pos(xyz_t* a, xyz_t* b); +xyz_t spolar2world(VecSph* sph); +xyz_t sglobe2world(VecGeo* geo); +VecSph world2spolar(xyz_t* vec); +VecGeo world2sglobe(xyz_t* vec); +VecSph spolar_by_2pos(xyz_t* a, xyz_t* b); +VecGeo sglobe_by_2pos(xyz_t* a, xyz_t* b); +xyz_t radianxy_by_2pos(xyz_t* a, xyz_t* b); +xyz_t degreexy_by_2pos(xyz_t* a, xyz_t* b); +s_xyz sanglexy_by_2pos(xyz_t* a, xyz_t* b); #endif diff --git a/include/macros.h b/include/macros.h index 7b4df6b..b855eb3 100644 --- a/include/macros.h +++ b/include/macros.h @@ -24,6 +24,8 @@ #define ABS(x) (((x) >= 0) ? (x): -(x)) #define CLAMP(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x)) +#define CLAMP_MAX(x, max) ((x) > (max) ? (max) : (x)) +#define CLAMP_MIN(x, min) ((x) < (min) ? (min) : (x)) #define DECR(x) ((x) == 0 ? 0 : --(x)) diff --git a/include/z64math.h b/include/z64math.h index 4187622..b533ba2 100644 --- a/include/z64math.h +++ b/include/z64math.h @@ -42,6 +42,20 @@ typedef struct { /* 0x8 */ s32 z; } Vec3i; // size = 0xC +typedef struct { + /* 0x0 */ f32 r; // radius + /* 0x4 */ s16 pitch; // depends on coordinate system. See below. + /* 0x6 */ s16 yaw; // azimuthal angle +} VecSphGeo; // size = 0x8 + +// Defines a point in the spherical coordinate system. +// Pitch is 0 along the positive y-axis (up) +typedef VecSphGeo VecSph; + +// Defines a point in the geographic coordinate system. +// Pitch is 0 along the xz-plane (horizon) +typedef VecSphGeo VecGeo; + typedef float MtxF_t[4][4]; typedef union { MtxF_t mf; @@ -86,4 +100,10 @@ typedef union { #define BINANG_SUB(a, b) ((s16)(a - b)) #define BINANG_ADD(a, b) ((s16)(a + b)) +// Vector macros +#define SQXZ(vec) ((vec.x) * (vec.x) + (vec.z) * (vec.z)) +#define DOTXZ(vec1, vec2) ((vec1.x) * (vec2.x) + (vec1.z) * (vec2.z)) +#define SQXYZ(vec) ((vec.x) * (vec.x) + (vec.y) * (vec.y) + (vec.z) * (vec.z)) +#define DOTXYZ(vec1, vec2) ((vec1.x) * (vec2.x) + (vec1.y) * (vec2.y) + (vec1.z) * (vec2.z)) + #endif diff --git a/src/code/m_olib.c b/src/code/m_olib.c new file mode 100644 index 0000000..7dc7058 --- /dev/null +++ b/src/code/m_olib.c @@ -0,0 +1,212 @@ +#include "global.h" +#include "m_olib.h" + +/** + * Calculates the distances between `a` and `b` + */ +f32 distance_between(xyz_t* a, xyz_t* 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 distance_between2(xyz_t* a, xyz_t* b, xyz_t* 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 distance_2d(xyz_t* a, xyz_t* 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 never_zero(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 limiter(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 + */ +xyz_t unitvector_by_2pos(xyz_t* a, xyz_t* b) { + xyz_t v1; + xyz_t v2; + f32 dist; + + v1.x = b->x - a->x; + v1.y = b->y - a->y; + v1.z = b->z - a->z; + + dist = never_zero(sqrtf(SQXYZ(v1)), 0.01f); + + v2.x = v1.x / dist; + v2.y = v1.y / dist; + v2.z = v1.z / dist; + + return v2; +} + +/** + * Takes the spherical coordinate `sph`, and converts it into a x,y,z position + */ +xyz_t spolar2world(VecSph* sph) { + xyz_t v; + f32 sinPitch; + f32 cosPitch = cos_s(sph->pitch); + f32 sinYaw; + f32 cosYaw = cos_s(sph->yaw); + + sinPitch = sin_s(sph->pitch); + sinYaw = sin_s(sph->yaw); + + v.x = sph->r * sinPitch * sinYaw; + v.y = sph->r * cosPitch; + v.z = sph->r * sinPitch * cosYaw; + + return v; +} + +/** + * Takes the geographic point `geo` and converts it into a x,y,z position + */ +xyz_t sglobe2world(VecGeo* geo) { + VecSph sph; + + sph.r = geo->r; + sph.pitch = 0x3FFF - geo->pitch; + sph.yaw = geo->yaw; + + return spolar2world(&sph); +} + +/** + * Takes the point `vec`, and converts it into a spherical coordinate + */ +VecSph world2spolar(xyz_t* vec) { + VecSph sph; + f32 distXZSq = SQ(vec->x) + SQ(vec->z); + f32 distXZ = sqrtf(distXZSq); + + if ((distXZ == 0.0f) && (vec->y == 0.0f)) { + sph.pitch = 0; + } else { + sph.pitch = CAM_DEG_TO_BINANG(RAD_TO_DEG(fatan2(distXZ, vec->y))); + } + + sph.r = sqrtf(SQ(vec->y) + distXZSq); + if ((vec->x == 0.0f) && (vec->z == 0.0f)) { + sph.yaw = 0; + } else { + sph.yaw = CAM_DEG_TO_BINANG(RAD_TO_DEG(fatan2(vec->x, vec->z))); + } + + return sph; +} + +/** + * Takes the point `vec`, and converts it to a geographic coordinate + */ +VecGeo world2sglobe(xyz_t* vec) { + VecSph sph = world2spolar(vec); + + sph.pitch = 0x3FFF - sph.pitch; + + return sph; +} + +/** + * Takes the differences of positions `a` and `b`, and converts them to spherical coordinates + */ +VecSph spolar_by_2pos(xyz_t* a, xyz_t* b) { + xyz_t diff; + + diff.x = b->x - a->x; + diff.y = b->y - a->y; + diff.z = b->z - a->z; + + return world2spolar(&diff); +} + +/** + * Takes the difference of positions `a` and `b`, and converts them to geographic coordinates + */ +VecGeo sglobe_by_2pos(xyz_t* a, xyz_t* b) { + xyz_t diff; + + diff.x = b->x - a->x; + diff.y = b->y - a->y; + diff.z = b->z - a->z; + + return world2sglobe(&diff); +} + +/** + * Gets the pitch/yaw of the vector formed from `b`-`a`, result is in radians + */ +xyz_t radianxy_by_2pos(xyz_t* a, xyz_t* b) { + xyz_t anglesRad; + + anglesRad.x = fatan2(b->z - a->z, b->y - a->y); + anglesRad.y = fatan2(b->x - a->x, b->z - a->z); + anglesRad.z = 0.0f; + + return anglesRad; +} + +/** + * Gets the pitch/yaw of the vector formed from `b`-`a`, result is in degrees + */ +xyz_t degreexy_by_2pos(xyz_t* a, xyz_t* b) { + xyz_t anglesRad = radianxy_by_2pos(a, b); + xyz_t anglesDegrees; + + anglesDegrees.x = RAD_TO_DEG(anglesRad.x); + anglesDegrees.y = RAD_TO_DEG(anglesRad.y); + anglesDegrees.z = 0.0f; + + return anglesDegrees; +} + +/** + * Gets the pitch/yaw of the vector formed from `b`-`a`, result is in binary degrees + */ +s_xyz sanglexy_by_2pos(xyz_t* a, xyz_t* b) { + xyz_t anglesRad = radianxy_by_2pos(a, b); + s_xyz anglesBinAng; + + anglesBinAng.x = CAM_DEG_TO_BINANG(RAD_TO_DEG(anglesRad.x)); + anglesBinAng.y = CAM_DEG_TO_BINANG(RAD_TO_DEG(anglesRad.y)); + anglesBinAng.z = 0.0f; + + return anglesBinAng; +} diff --git a/src/overlays/actors/ovl_Koinobori/ac_koinobori.c b/src/overlays/actors/ovl_Koinobori/ac_koinobori.c index 11bad7a..e12ef87 100644 --- a/src/overlays/actors/ovl_Koinobori/ac_koinobori.c +++ b/src/overlays/actors/ovl_Koinobori/ac_koinobori.c @@ -112,13 +112,15 @@ void aKOI_actor_init(Actor* thisx, Game_Play* game_play) { { \ Gfx* __polyOpa = __gfxCtx->polyOpa.p; \ int __opa_opened = 0; \ - while (0) + do { \ + } while (0) #define CLOSE_POLY_OPA_DISPS() \ __gfxCtx->polyOpa.p = __polyOpa; \ (void)__opa_opened; \ } \ - while (0) + do { \ + } while (0) extern u16 aKOI_obj_e_koinobori_a_pal[]; extern u16 obj_e_koinobori_b_pal[]; diff --git a/src/overlays/actors/ovl_Toudai/ac_toudai.c b/src/overlays/actors/ovl_Toudai/ac_toudai.c index c128db3..abbcffa 100644 --- a/src/overlays/actors/ovl_Toudai/ac_toudai.c +++ b/src/overlays/actors/ovl_Toudai/ac_toudai.c @@ -209,37 +209,43 @@ s32 aTOU_actor_draw_before(Game_Play* game_play UNUSED, SkeletonInfoR* skeletonI { \ Gfx* __polyOpa = __gfxCtx->polyOpa.p; \ int __opa_opened = 0; \ - while (0) + do { \ + } while (0) #define CLOSE_POLY_OPA_DISPS() \ __gfxCtx->polyOpa.p = __polyOpa; \ (void)__opa_opened; \ } \ - while (0) + do { \ + } while (0) #define OPEN_POLY_XLU_DISPS() \ { \ Gfx* __polyXlu = __gfxCtx->polyXlu.p; \ int __xlu_opened = 0; \ - while (0) + do { \ + } while (0) #define CLOSE_POLY_XLU_DISPS() \ __gfxCtx->polyXlu.p = __polyXlu; \ (void)__xlu_opened; \ } \ - while (0) + do { \ + } while (0); #define OPEN_LIGHT_DISPS() \ { \ Gfx* __light = __gfxCtx->light.p; \ int __light_opened = 0; \ - while (0) + do { \ + } while (0) #define CLOSE_LIGHT_DISPS() \ __gfxCtx->light.p = __light; \ (void)__light_opened; \ } \ - while (0) + do { \ + } while (0) extern Gfx obj_s_toudai_light_model[]; extern Gfx obj_w_toudai_light_model[]; diff --git a/yamls/jp/code.yaml b/yamls/jp/code.yaml index dba9550..e5b6019 100644 --- a/yamls/jp/code.yaml +++ b/yamls/jp/code.yaml @@ -60,7 +60,7 @@ - [0x6D2720, c, code/m_npc_schedule] - [0x6D2A70, c, code/m_npc_walk] - [0x6D3CB0, asm, code/800B0010] - - [0x6D3D20, asm, code/m_olib] + - [0x6D3D20, c, code/m_olib] - [0x6D4440, c, code/m_pause] - [0x6D44F0, asm, code/6D44F0] - [0x6D4C60, c, code/m_player_call] @@ -223,7 +223,7 @@ - [0x73AEF0, rodata, code/m_msg_main] - [0x73AF40, rodata, code/73AF40] - [0x73AF50, .rodata, code/m_npc] - - [0x73B000, rodata, code/m_olib] + - [0x73B000, .rodata, code/m_olib] - [0x73B020, rodata, code/m_player_lib] - [0x73B0F0, rodata, code/73B0F0] - [0x73B130, .rodata, code/m_private] |
