1653 lines
29 KiB
C
1653 lines
29 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "bss.h"
|
|
#include "data.h"
|
|
#include "lib/model.h"
|
|
#include "lib/mtx.h"
|
|
#include "types.h"
|
|
|
|
struct t0slot {
|
|
u16 unk00;
|
|
u16 unk02;
|
|
u16 unk04;
|
|
u16 unk06;
|
|
};
|
|
|
|
struct t0slot *t0slot;
|
|
u8 *t2ptr8;
|
|
s32 t3;
|
|
u8 *t3ptr8;
|
|
s32 t4;
|
|
u8 *t6ptr8;
|
|
s32 v1;
|
|
s32 s0;
|
|
s32 s1;
|
|
s32 s2;
|
|
s32 s3;
|
|
s32 s4;
|
|
s32 sr8;
|
|
s32 f0int;
|
|
f32 f0;
|
|
f32 f1;
|
|
f32 f2;
|
|
f32 f3;
|
|
f32 f4;
|
|
f32 f5;
|
|
|
|
// f12-f23 are used as rotation matrix
|
|
f32 f12;
|
|
f32 f13;
|
|
f32 f14;
|
|
f32 f15;
|
|
f32 f16;
|
|
f32 f17;
|
|
f32 f18;
|
|
f32 f19;
|
|
f32 f20;
|
|
f32 f21;
|
|
f32 f22;
|
|
f32 f23;
|
|
|
|
s32 gp;
|
|
|
|
static bool modelasm_iterate_things1(void);
|
|
static bool modelasm_iterate_things2(void);
|
|
static u32 modelasm_read_frame_data(void);
|
|
static union modelrwdata *modelasm_get_node_rw_data(struct model *model, struct modelnode *node, bool is_head);
|
|
static void modelasm_math_pain1(f32 f30);
|
|
static void modelasm_math_pain2(void);
|
|
static void modelasm_prepare_rot_mtx180(s32 t2, s32 t3, s32 t4);
|
|
static void modelasm_prepare_rot_mtx360(s32 t2, s32 t3, s32 t4);
|
|
static void modelasm_math_pain3(void);
|
|
static void modelasm_math_pain4(void);
|
|
static void modelasm_mtx_multiply(Mtxf *src, Mtxf *dst);
|
|
static Mtxf *modelasm_find_node_mtx(struct model *model, struct modelnode *node);
|
|
static f32 modelasm_acos_or_asin(f32 f6);
|
|
|
|
/**
|
|
* Reads animation data for the given model and applies matrix transformations
|
|
* for each part. It factors merging between two animations too.
|
|
*
|
|
* The game code is able to set g_ModelJointPositionedFunc to a callback,
|
|
* and this function will execute that callback for every positioned joint.
|
|
*
|
|
* Returns true if succeeded, or false if the caller should do some kind of
|
|
* simple/generic calculation.
|
|
*/
|
|
bool modelasm00018680(struct modelrenderdata *renderdata, struct model *model)
|
|
{
|
|
bool sp7f8 = false;
|
|
f32 sp7e8f32;
|
|
struct t0slot *sp7e8slot;
|
|
f32 sp7f4;
|
|
f32 sp7f0;
|
|
f32 sp7ec;
|
|
bool sp7e4;
|
|
struct t0slot sp00[240];
|
|
struct modelnode *node;
|
|
struct anim *anim;
|
|
struct skeleton *skeleton;
|
|
struct modeldef *modeldef;
|
|
union modelrwdata *rwdata;
|
|
f32 f6;
|
|
f32 f7;
|
|
f32 f8;
|
|
f32 f9;
|
|
f32 f10;
|
|
f32 f30;
|
|
Mtxf *t0mtx;
|
|
Mtxf *t1mtx;
|
|
s32 t1;
|
|
s32 t2;
|
|
u8 *s0ptr8;
|
|
s32 i;
|
|
f32 yrot;
|
|
|
|
for (i = 0; i < model->definition->nummatrices; i++) {
|
|
sp00[i].unk00 = 0;
|
|
}
|
|
|
|
anim = model->anim;
|
|
|
|
if (anim) {
|
|
t0slot = &sp00[0];
|
|
t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]];
|
|
t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]] + g_Anims[anim->animnum].headerlen;
|
|
t4 = g_Anims[anim->animnum].framelen;
|
|
|
|
if (t2ptr8 != t3ptr8) {
|
|
t6ptr8 = g_AnimFrameBytes[anim->frameslot1];
|
|
|
|
if (!modelasm_iterate_things1()) {
|
|
return false;
|
|
}
|
|
|
|
if (anim->frac != 0.0f) {
|
|
for (i = 0; i < model->definition->nummatrices; i++) {
|
|
sp00[120 + i].unk00 = 0;
|
|
}
|
|
|
|
f0int = anim->frac * 4096;
|
|
|
|
t0slot = &sp00[0];
|
|
t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]];
|
|
t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]] + g_Anims[anim->animnum].headerlen;
|
|
t4 = g_Anims[anim->animnum].framelen;
|
|
|
|
if (t2ptr8 != t3ptr8) {
|
|
t6ptr8 = g_AnimFrameBytes[anim->frameslot2];
|
|
|
|
if (!modelasm_iterate_things2()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
f30 = anim->fracmerge;
|
|
|
|
if (anim->fracmerge != 0.0f) {
|
|
t0slot = &sp00[120];
|
|
t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]];
|
|
t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]] + g_Anims[anim->animnum2].headerlen;
|
|
t4 = g_Anims[anim->animnum2].framelen;
|
|
|
|
if (t2ptr8 != t3ptr8) {
|
|
t6ptr8 = g_AnimFrameBytes[anim->frameslot3];
|
|
|
|
if (!modelasm_iterate_things1()) {
|
|
return false;
|
|
}
|
|
|
|
if (anim->frac2 != 0.0f) {
|
|
t0slot = &sp00[120];
|
|
f0int = anim->frac2 * 4096;
|
|
t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]];
|
|
t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]] + g_Anims[anim->animnum2].headerlen;
|
|
t4 = g_Anims[anim->animnum2].framelen;
|
|
|
|
if (t2ptr8 != t3ptr8) {
|
|
t6ptr8 = g_AnimFrameBytes[anim->frameslot4];
|
|
|
|
if (!modelasm_iterate_things2()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
modeldef = model->definition;
|
|
node = modeldef->rootnode;
|
|
skeleton = modeldef->skel;
|
|
|
|
while (node) {
|
|
switch (node->type & 0xff) {
|
|
case MODELNODETYPE_POSITION:
|
|
sp7e4 = false;
|
|
|
|
if (model) {
|
|
t1 = node->rodata->position.part;
|
|
|
|
if (anim) {
|
|
if (f30 != 0.0f) {
|
|
if (anim->flip) {
|
|
t2ptr8 = skeleton->things[t1];
|
|
t0slot = &sp00[t2ptr8[1]];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t4 = t0slot->unk06;
|
|
t3 = t0slot->unk04;
|
|
t2 = t0slot->unk02;
|
|
|
|
if (t4 != 0) {
|
|
t4 = (0x10000 - t4) & 0xffff;
|
|
}
|
|
|
|
if (t3 != 0) {
|
|
t3 = (0x10000 - t3) & 0xffff;
|
|
}
|
|
} else {
|
|
t0slot = &sp00[t1];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t2 = t0slot->unk02;
|
|
t3 = t0slot->unk04;
|
|
t4 = t0slot->unk06;
|
|
}
|
|
|
|
if (anim->flip2) {
|
|
s0ptr8 = skeleton->things[t1];
|
|
t0slot = &sp00[s0ptr8[1]];
|
|
|
|
s4 = t0slot[120].unk06;
|
|
s3 = t0slot[120].unk04;
|
|
s0 = t0slot[0].unk02;
|
|
s2 = t0slot[120].unk02;
|
|
|
|
if (s4 != 0) {
|
|
s4 = (0x10000 - s4) & 0xffff;
|
|
}
|
|
|
|
if (s3 != 0) {
|
|
s3 = (0x10000 - s3) & 0xffff;
|
|
}
|
|
} else {
|
|
t0slot = &sp00[t1];
|
|
|
|
s2 = t0slot[120].unk02;
|
|
s3 = t0slot[120].unk04;
|
|
s4 = t0slot[120].unk06;
|
|
}
|
|
|
|
sp7e8slot = t0slot;
|
|
modelasm_prepare_rot_mtx360(t2, t3, t4);
|
|
modelasm_math_pain2();
|
|
|
|
f16 = f0;
|
|
f17 = f1;
|
|
f18 = f2;
|
|
f19 = f3;
|
|
|
|
t2 = s2;
|
|
t3 = s3;
|
|
t4 = s4;
|
|
|
|
modelasm_prepare_rot_mtx360(t2, t3, t4);
|
|
modelasm_math_pain2();
|
|
modelasm_math_pain1(f30);
|
|
|
|
sp7e4 = true;
|
|
t0slot = sp7e8slot;
|
|
|
|
sp7e8f32 = f0;
|
|
sp7ec = f1;
|
|
sp7f0 = f2;
|
|
sp7f4 = f3;
|
|
|
|
modelasm_math_pain4();
|
|
} else {
|
|
if (anim->flip) {
|
|
t2ptr8 = skeleton->things[t1];
|
|
t0slot = &sp00[t2ptr8[1]];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t4 = t0slot->unk06;
|
|
t3 = t0slot->unk04;
|
|
t2 = t0slot->unk02;
|
|
|
|
if (t4 != 0) {
|
|
t4 = (0x10000 - t4) & 0xffff;
|
|
}
|
|
|
|
if (t3 != 0) {
|
|
t3 = (0x10000 - t3) & 0xffff;
|
|
}
|
|
} else {
|
|
t0slot = &sp00[t1];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t4 = t0slot->unk06;
|
|
t3 = t0slot->unk04;
|
|
t2 = t0slot->unk02;
|
|
}
|
|
|
|
s0 = t2;
|
|
|
|
if ((sr8 & 1) == 0) {
|
|
f12 = 1;
|
|
f13 = 0;
|
|
f14 = 0;
|
|
|
|
f15 = 0;
|
|
f16 = 1;
|
|
f17 = 0;
|
|
|
|
f18 = 0;
|
|
f19 = 0;
|
|
f20 = 1;
|
|
} else {
|
|
s0 = t2;
|
|
s1 = t3;
|
|
s2 = t4;
|
|
|
|
modelasm_prepare_rot_mtx180(t2, t3, t4);
|
|
modelasm_math_pain3();
|
|
}
|
|
}
|
|
} else {
|
|
f12 = 1;
|
|
f13 = 0;
|
|
f14 = 0;
|
|
|
|
f15 = 0;
|
|
f16 = 1;
|
|
f17 = 0;
|
|
|
|
f18 = 0;
|
|
f19 = 0;
|
|
f20 = 1;
|
|
|
|
t0slot = &sp00[t1];
|
|
sr8 = t0slot->unk00;
|
|
}
|
|
|
|
if (sr8 & 2) {
|
|
t2 = *(s16 *) &t0slot[60].unk00;
|
|
t3 = *(s16 *) &t0slot[60].unk02;
|
|
t4 = *(s16 *) &t0slot[60].unk04;
|
|
|
|
if (node == modeldef->rootnode) {
|
|
f21 = t2 * anim->animscale;
|
|
f22 = t3 * anim->animscale;
|
|
f23 = t4 * anim->animscale;
|
|
} else {
|
|
f0 = t2 * anim->animscale;
|
|
f1 = t3 * anim->animscale;
|
|
f2 = t4 * anim->animscale;
|
|
|
|
f21 = f0 + node->rodata->position.pos.x;
|
|
f22 = f1 + node->rodata->position.pos.y;
|
|
f23 = f2 + node->rodata->position.pos.z;
|
|
}
|
|
} else {
|
|
if (node != modeldef->rootnode) {
|
|
f21 = node->rodata->position.pos.x;
|
|
f22 = node->rodata->position.pos.y;
|
|
f23 = node->rodata->position.pos.z;
|
|
} else {
|
|
f21 = 0;
|
|
f22 = 0;
|
|
f23 = 0;
|
|
}
|
|
}
|
|
|
|
t0mtx = node->parent ? modelasm_find_node_mtx(model, node->parent) : renderdata->unk00;
|
|
t1mtx = &model->matrices[node->rodata->position.mtxindex0];
|
|
|
|
modelasm_mtx_multiply(t0mtx, t1mtx);
|
|
|
|
if (g_ModelJointPositionedFunc) {
|
|
g_ModelJointPositionedFunc(node->rodata->position.mtxindex0, &model->matrices[node->rodata->position.mtxindex0]);
|
|
}
|
|
|
|
if (node->type & MODELNODETYPE_0100) {
|
|
if (sp7e4) {
|
|
f0 = sp7e8f32;
|
|
f1 = sp7ec;
|
|
f2 = sp7f0;
|
|
f3 = sp7f4;
|
|
} else {
|
|
t2 = s0;
|
|
t3 = s1;
|
|
t4 = s2;
|
|
modelasm_prepare_rot_mtx360(t2, t3, t4);
|
|
modelasm_math_pain2();
|
|
}
|
|
|
|
f4 = 0;
|
|
f6 = f0;
|
|
f5 = 1;
|
|
|
|
if (f6 < 0.0f) {
|
|
f6 = -f6;
|
|
f5 = -f5;
|
|
}
|
|
|
|
if (f6 < -0.99994999170303f) {
|
|
f0 *= 0.5f;
|
|
f4 = f5 * 0.5f;
|
|
f1 *= 0.5f;
|
|
f2 *= 0.5f;
|
|
f3 *= 0.5f;
|
|
f0 -= f4;
|
|
} else if (f6 > 0.99994999170303f) {
|
|
f0 *= 0.5f;
|
|
f1 *= 0.5f;
|
|
f2 *= 0.5f;
|
|
f3 *= 0.5f;
|
|
f4 = f5 * 0.5f;
|
|
f0 += f4;
|
|
} else {
|
|
f7 = modelasm_acos_or_asin(f6);
|
|
f17 = f0;
|
|
f12 = f6 * 0.5f;
|
|
s1 = t1;
|
|
f0 = sinf(f12);
|
|
f3 *= f0;
|
|
f2 *= f0;
|
|
t1 = s1;
|
|
f1 *= f0;
|
|
f5 *= f0;
|
|
f0 *= f17;
|
|
f0 += f5;
|
|
}
|
|
|
|
modelasm_math_pain4();
|
|
t1mtx = &model->matrices[node->rodata->position.mtxindex1];
|
|
modelasm_mtx_multiply(t0mtx, t1mtx);
|
|
}
|
|
}
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
t0mtx = modelasm_find_node_mtx(model, node);
|
|
|
|
rwdata = modelasm_get_node_rw_data(model, node, sp7f8);
|
|
f0 = 0;
|
|
|
|
if (!g_ModelDistanceDisabled && t0mtx) {
|
|
f0 = -t0mtx->m[3][2] * g_Vars.currentplayer->c_lodscalez * g_ModelDistanceScale;
|
|
}
|
|
|
|
if ((node->rodata->distance.near == 0.0f || f0 > node->rodata->distance.near * model->scale)
|
|
&& f0 <= node->rodata->distance.far * model->scale) {
|
|
rwdata->distance.visible = true;
|
|
node->child = node->rodata->distance.target;
|
|
} else {
|
|
rwdata->distance.visible = false;
|
|
node->child = NULL;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_CHRINFO:
|
|
if (model) {
|
|
t1 = node->rodata->chrinfo.animpart;
|
|
|
|
#ifdef AVOID_UB
|
|
if (anim->animnum)
|
|
#else
|
|
if (anim)
|
|
#endif
|
|
{
|
|
if (f30 != 0.0f) {
|
|
if (anim->flip) {
|
|
t2ptr8 = skeleton->things[t1];
|
|
t0slot = &sp00[t2ptr8[1]];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t4 = t0slot->unk06;
|
|
t3 = t0slot->unk04;
|
|
t2 = t0slot->unk02;
|
|
|
|
if (t4 != 0) {
|
|
t4 = (0x10000 - t4) & 0xffff;
|
|
}
|
|
|
|
if (t3 != 0) {
|
|
t3 = (0x10000 - t3) & 0xffff;
|
|
}
|
|
} else {
|
|
t0slot = &sp00[t1];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t2 = t0slot->unk02;
|
|
t3 = t0slot->unk04;
|
|
t4 = t0slot->unk06;
|
|
}
|
|
|
|
if (anim->flip2) {
|
|
s0ptr8 = skeleton->things[t1];
|
|
t0slot = &sp00[s0ptr8[1]];
|
|
|
|
s4 = t0slot[120].unk06;
|
|
s3 = t0slot[120].unk04;
|
|
s0 = t0slot[0].unk02;
|
|
s2 = t0slot[120].unk02;
|
|
|
|
if (s4 != 0) {
|
|
s4 = (0x10000 - s4) & 0xffff;
|
|
}
|
|
|
|
if (s3 != 0) {
|
|
s3 = (0x10000 - s3) & 0xffff;
|
|
}
|
|
} else {
|
|
t0slot = &sp00[t1];
|
|
|
|
s2 = t0slot[120].unk02;
|
|
s3 = t0slot[120].unk04;
|
|
s4 = t0slot[120].unk06;
|
|
}
|
|
|
|
sp7e8slot = t0slot;
|
|
modelasm_prepare_rot_mtx360(t2, t3, t4);
|
|
modelasm_math_pain2();
|
|
|
|
f16 = f0;
|
|
f17 = f1;
|
|
f18 = f2;
|
|
f19 = f3;
|
|
|
|
t2 = s2;
|
|
t3 = s3;
|
|
t4 = s4;
|
|
|
|
modelasm_prepare_rot_mtx360(t2, t3, t4);
|
|
modelasm_math_pain2();
|
|
modelasm_math_pain1(f30);
|
|
t0slot = sp7e8slot;
|
|
modelasm_math_pain4();
|
|
} else {
|
|
if (anim->flip) {
|
|
t2ptr8 = skeleton->things[t1];
|
|
t0slot = &sp00[t2ptr8[1]];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t4 = t0slot->unk06;
|
|
t3 = t0slot->unk04;
|
|
t2 = t0slot->unk02;
|
|
|
|
if (t4 != 0) {
|
|
t4 = (0x10000 - t4) & 0xffff;
|
|
}
|
|
|
|
if (t3 != 0) {
|
|
t3 = (0x10000 - t3) & 0xffff;
|
|
}
|
|
|
|
modelasm_prepare_rot_mtx180(t2, t3, t4);
|
|
} else {
|
|
t0slot = &sp00[t1];
|
|
|
|
sr8 = t0slot->unk00;
|
|
t4 = t0slot->unk06;
|
|
t3 = t0slot->unk04;
|
|
t2 = t0slot->unk02;
|
|
|
|
modelasm_prepare_rot_mtx180(t2, t3, t4);
|
|
}
|
|
|
|
modelasm_math_pain3();
|
|
}
|
|
} else {
|
|
f12 = 1;
|
|
f13 = 0;
|
|
f14 = 0;
|
|
|
|
f15 = 0;
|
|
f16 = 1;
|
|
f17 = 0;
|
|
|
|
f18 = 0;
|
|
f19 = 0;
|
|
f20 = 1;
|
|
|
|
t0slot = &sp00[t1];
|
|
sr8 = t0slot->unk00;
|
|
}
|
|
|
|
f0 = 0;
|
|
|
|
rwdata = modelasm_get_node_rw_data(model, node, sp7f8);
|
|
|
|
yrot = rwdata->chrinfo.yrot;
|
|
|
|
if (rwdata->chrinfo.unk18 != 0.0f) {
|
|
f5 = rwdata->chrinfo.unk1c - rwdata->chrinfo.yrot;
|
|
|
|
if (f5 < 0.0f) {
|
|
f5 += DTOR(360);
|
|
}
|
|
|
|
if (f5 >= DTOR(180)) {
|
|
f5 *= rwdata->chrinfo.unk18;
|
|
yrot += f5;
|
|
|
|
if (yrot > DTOR(360)) {
|
|
yrot -= DTOR(360);
|
|
}
|
|
} else {
|
|
f5 = DTOR(360) - f5;
|
|
f5 *= rwdata->chrinfo.unk18;
|
|
yrot -= f5;
|
|
|
|
if (yrot < 0.0f) {
|
|
yrot += DTOR(360);
|
|
}
|
|
}
|
|
}
|
|
|
|
f1 = sinf(yrot);
|
|
f0 = sinf(yrot + DTOR(90));
|
|
|
|
f2 = -f1;
|
|
|
|
f21 = rwdata->chrinfo.pos.x;
|
|
f22 = rwdata->chrinfo.pos.y;
|
|
f23 = rwdata->chrinfo.pos.z;
|
|
|
|
f3 = f0 * f12;
|
|
f4 = f1 * f14;
|
|
f5 = f0 * f15;
|
|
f3 = f3 + f4;
|
|
f6 = f1 * f17;
|
|
f7 = f0 * f18;
|
|
f5 = f5 + f6;
|
|
f8 = f1 * f20;
|
|
f9 = f2 * f12;
|
|
f7 = f7 + f8;
|
|
f10 = f0 * f14;
|
|
f4 = f2 * f15;
|
|
f14 = f9 + f10;
|
|
f6 = f0 * f17;
|
|
f8 = f2 * f18;
|
|
f17 = f4 + f6;
|
|
f10 = f0 * f20;
|
|
f12 = f3;
|
|
f20 = f8 + f10;
|
|
f15 = f5;
|
|
f18 = f7;
|
|
|
|
if (model->scale != 1.0f) {
|
|
f12 *= model->scale;
|
|
f13 *= model->scale;
|
|
f14 *= model->scale;
|
|
f15 *= model->scale;
|
|
f16 *= model->scale;
|
|
f17 *= model->scale;
|
|
f18 *= model->scale;
|
|
f19 *= model->scale;
|
|
f20 *= model->scale;
|
|
}
|
|
|
|
t0mtx = renderdata->unk00;
|
|
t1mtx = &model->matrices[node->rodata->chrinfo.mtxindex];
|
|
|
|
modelasm_mtx_multiply(t0mtx, t1mtx);
|
|
}
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
rwdata = modelasm_get_node_rw_data(model, node, sp7f8);
|
|
|
|
if (rwdata->headspot.headmodeldef) {
|
|
struct modelnode *iternode = rwdata->headspot.headmodeldef->rootnode;
|
|
sp7f8 = true;
|
|
node->child = iternode;
|
|
|
|
while (iternode) {
|
|
iternode->parent = node;
|
|
iternode = iternode->next;
|
|
}
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
t0mtx = node->parent ? modelasm_find_node_mtx(model, node->parent) : renderdata->unk00;
|
|
|
|
f12 = 1;
|
|
f13 = 0;
|
|
f14 = 0;
|
|
|
|
f15 = 0;
|
|
f16 = 1;
|
|
f17 = 0;
|
|
|
|
f18 = 0;
|
|
f19 = 0;
|
|
f20 = 1;
|
|
|
|
f21 = node->rodata->positionheld.pos.x;
|
|
f22 = node->rodata->positionheld.pos.y;
|
|
f23 = node->rodata->positionheld.pos.z;
|
|
|
|
t1mtx = &model->matrices[node->rodata->positionheld.mtxindex];
|
|
|
|
modelasm_mtx_multiply(t0mtx, t1mtx);
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rwdata = modelasm_get_node_rw_data(model, node, sp7f8);
|
|
|
|
node->child = rwdata->toggle.visible ? node->rodata->toggle.target : NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (true) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
} else {
|
|
node = node->parent;
|
|
|
|
if (node) {
|
|
if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) {
|
|
// @bug:
|
|
// sp7f8 tracks whether we are under the head node
|
|
// which allows modelasm_get_node_rw_data to avoid
|
|
// searching for the head node if we're already
|
|
// above it. The code here is ascending back out of
|
|
// the head node, so it should be setting it to
|
|
// false here.
|
|
sp7f8 = true;
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Expects:
|
|
* t0 = pointer to stack slots
|
|
* t2 = pointer to anim header bytes
|
|
* t3 = pointer to end of anim header
|
|
* t6 = pointer to anim frame bytes
|
|
*/
|
|
static bool modelasm_iterate_things1(void)
|
|
{
|
|
s32 t7;
|
|
s32 t8;
|
|
u32 v0;
|
|
|
|
gp = 0;
|
|
|
|
do {
|
|
t7 = *t2ptr8;
|
|
t2ptr8++;
|
|
t0slot->unk00 = t7;
|
|
|
|
if (t7 > 15) {
|
|
return false;
|
|
}
|
|
|
|
if (t7 & 2) {
|
|
// 0, 1, 2
|
|
v1 = t2ptr8[2];
|
|
s0 = modelasm_read_frame_data();
|
|
v1 = t2ptr8[2];
|
|
s3 = 1;
|
|
|
|
if (v1 < 16) {
|
|
v0 = v1 - 1;
|
|
s3 <<= v0;
|
|
s4 = 16;
|
|
|
|
if (s0 & s3) {
|
|
s4 -= v1;
|
|
v0 = (1 << s4) - 1;
|
|
v0 <<= v1;
|
|
s0 |= v0;
|
|
}
|
|
}
|
|
|
|
s3 = t2ptr8[0] << 8;
|
|
s4 = t2ptr8[1];
|
|
s3 += s4;
|
|
s0 += s3;
|
|
s0 &= 0xffff;
|
|
|
|
// 3, 4, 5
|
|
v1 = t2ptr8[5];
|
|
s1 = modelasm_read_frame_data();
|
|
v1 = t2ptr8[5];
|
|
s3 = 1;
|
|
|
|
if (v1 < 16) {
|
|
v0 = v1 - 1;
|
|
s3 <<= v0;
|
|
s4 = 16;
|
|
|
|
if (s1 & s3) {
|
|
s4 -= v1;
|
|
v0 = (1 << s4) - 1;
|
|
v0 <<= v1;
|
|
s1 |= v0;
|
|
}
|
|
}
|
|
|
|
s3 = t2ptr8[3] << 8;
|
|
s4 = t2ptr8[4];
|
|
s3 += s4;
|
|
s1 += s3;
|
|
s1 &= 0xffff;
|
|
|
|
// 6, 7, 8
|
|
v1 = t2ptr8[8];
|
|
s2 = modelasm_read_frame_data();
|
|
v1 = t2ptr8[8];
|
|
s3 = 1;
|
|
|
|
if (v1 < 16) {
|
|
v0 = v1 - 1;
|
|
s3 <<= v0;
|
|
s4 = 16;
|
|
|
|
if (s2 & s3) {
|
|
s4 -= v1;
|
|
v0 = (1 << s4) - 1;
|
|
v0 <<= v1;
|
|
s2 |= v0;
|
|
}
|
|
}
|
|
|
|
s3 = t2ptr8[6] << 8;
|
|
s4 = t2ptr8[7];
|
|
s3 += s4;
|
|
s2 += s3;
|
|
s2 &= 0xffff;
|
|
|
|
t2ptr8 += 9;
|
|
|
|
t0slot[60].unk00 = s0;
|
|
t0slot[60].unk02 = s1;
|
|
t0slot[60].unk04 = s2;
|
|
} else {
|
|
s0 = 0;
|
|
s1 = 0;
|
|
s2 = 0;
|
|
|
|
if (t7 & 8) {
|
|
v0 = t2ptr8[2] + t2ptr8[5] + t2ptr8[8] + t2ptr8[11];
|
|
v1 = t2ptr8[11];
|
|
|
|
if (v0 >= gp) {
|
|
v0 -= gp;
|
|
sr8 = 0;
|
|
t8 = v0 >> 3;
|
|
t6ptr8 += t8;
|
|
t8 <<= 3;
|
|
v0 -= t8;
|
|
sr8 = t6ptr8[0];
|
|
gp = 8;
|
|
t6ptr8++;
|
|
gp -= v0;
|
|
}
|
|
|
|
t2ptr8 += 12;
|
|
}
|
|
}
|
|
|
|
if (t7 & 1) {
|
|
v1 = t2ptr8[2];
|
|
s0 = modelasm_read_frame_data();
|
|
s0 += (t2ptr8[0] << 8) + t2ptr8[1];
|
|
v0 = 16 - t4;
|
|
s0 = (s0 << v0) & 0xffff;
|
|
|
|
v1 = t2ptr8[5];
|
|
s1 = modelasm_read_frame_data();
|
|
s1 += (t2ptr8[3] << 8) + t2ptr8[4];
|
|
v0 = 16 - t4;
|
|
s1 = (s1 << v0) & 0xffff;
|
|
|
|
v1 = t2ptr8[8];
|
|
s2 = modelasm_read_frame_data();
|
|
s2 += (t2ptr8[6] << 8) + t2ptr8[7];
|
|
v0 = 16 - t4;
|
|
s2 = (s2 << v0) & 0xffff;
|
|
|
|
t2ptr8 += 9;
|
|
} else {
|
|
s0 = 0;
|
|
s1 = 0;
|
|
s2 = 0;
|
|
}
|
|
|
|
t0slot->unk02 = s0;
|
|
t0slot->unk04 = s1;
|
|
t0slot->unk06 = s2;
|
|
t0slot++;
|
|
} while (t2ptr8 < t3ptr8);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Expects:
|
|
* t0 = pointer to stack slots
|
|
* t2 = pointer to anim header bytes
|
|
* t3 = pointer to end of anim header
|
|
* t4 = frame length
|
|
* t6 = pointer to anim frame bytes
|
|
* f0 containing an integer
|
|
*/
|
|
static bool modelasm_iterate_things2(void)
|
|
{
|
|
s32 t7;
|
|
s32 t8;
|
|
s32 s5;
|
|
u32 v0;
|
|
|
|
gp = 0;
|
|
|
|
do {
|
|
t7 = t2ptr8[0];
|
|
t2ptr8++;
|
|
|
|
if (t7 > 15) {
|
|
return false;
|
|
}
|
|
|
|
if ((t7 & 2) == 0) {
|
|
s0 = 0;
|
|
s1 = 0;
|
|
s2 = 0;
|
|
|
|
if (t7 & 8) {
|
|
v0 = t2ptr8[2] + t2ptr8[5] + t2ptr8[8] + t2ptr8[11];
|
|
|
|
if (v0 >= gp) {
|
|
v0 -= gp;
|
|
sr8 = 0;
|
|
t8 = v0 >> 3;
|
|
t6ptr8 += t8;
|
|
t8 <<= 3;
|
|
v0 -= t8;
|
|
sr8 = t6ptr8[0];
|
|
gp = 8;
|
|
t6ptr8++;
|
|
gp -= v0;
|
|
} else {
|
|
v0 -= gp;
|
|
}
|
|
|
|
t2ptr8 += 12;
|
|
}
|
|
} else {
|
|
v0 = t2ptr8[2] + t2ptr8[5] + t2ptr8[8];
|
|
|
|
if (v0 >= gp) {
|
|
v0 -= gp;
|
|
sr8 = 0;
|
|
t8 = v0 >> 3;
|
|
t6ptr8 += t8;
|
|
t8 <<= 3;
|
|
v0 -= t8;
|
|
sr8 = t6ptr8[0];
|
|
gp = 8;
|
|
t6ptr8++;
|
|
gp -= v0;
|
|
} else {
|
|
v0 -= gp;
|
|
}
|
|
|
|
t2ptr8 += 9;
|
|
}
|
|
|
|
if ((t7 & 1) == 0) {
|
|
s0 = 0;
|
|
s1 = 0;
|
|
s2 = 0;
|
|
} else {
|
|
v1 = t2ptr8[2];
|
|
s0 = modelasm_read_frame_data();
|
|
s0 += (t2ptr8[0] << 8) + t2ptr8[1];
|
|
v0 = 16 - t4;
|
|
s0 = (s0 << v0) & 0xffff;
|
|
|
|
v1 = t2ptr8[5];
|
|
s1 = modelasm_read_frame_data();
|
|
s1 += (t2ptr8[3] << 8) + t2ptr8[4];
|
|
v0 = 16 - t4;
|
|
s1 = (s1 << v0) & 0xffff;
|
|
|
|
v1 = t2ptr8[8];
|
|
s2 = modelasm_read_frame_data();
|
|
s2 += (t2ptr8[6] << 8) + t2ptr8[7];
|
|
v0 = 16 - t4;
|
|
s2 = (s2 << v0) & 0xffff;
|
|
|
|
t2ptr8 += 9;
|
|
}
|
|
|
|
s3 = f0int;
|
|
v1 = 0x10000;
|
|
|
|
// 02
|
|
s4 = t0slot->unk02;
|
|
s5 = s0 - s4;
|
|
|
|
if (s5 < 0) {
|
|
s5 += 0x10000;
|
|
}
|
|
|
|
if (s5 < 0x8000) {
|
|
s5 *= s3;
|
|
s5 >>= 12;
|
|
s0 = s4 + s5;
|
|
|
|
if (s0 >= 0x10000) {
|
|
s0 -= 0x10000;
|
|
}
|
|
} else {
|
|
s5 = 0x10000 - s5;
|
|
s5 *= s3;
|
|
s5 >>= 12;
|
|
s0 = s4 - s5;
|
|
|
|
if (s0 < 0) {
|
|
s0 += 0x10000;
|
|
}
|
|
}
|
|
|
|
// 04
|
|
s4 = t0slot->unk04;
|
|
s5 = s1 - s4;
|
|
|
|
if (s5 < 0) {
|
|
s5 += 0x10000;
|
|
}
|
|
|
|
if (s5 < 0x8000) {
|
|
s5 *= s3;
|
|
s5 >>= 12;
|
|
s1 = s4 + s5;
|
|
|
|
if (s1 >= 0x10000) {
|
|
s1 -= 0x10000;
|
|
}
|
|
} else {
|
|
s5 = 0x10000 - s5;
|
|
s5 *= s3;
|
|
s5 >>= 12;
|
|
s1 = s4 - s5;
|
|
|
|
if (s1 < 0) {
|
|
s1 += 0x10000;
|
|
}
|
|
}
|
|
|
|
// 06
|
|
s4 = t0slot->unk06;
|
|
s5 = s2 - s4;
|
|
|
|
if (s5 < 0) {
|
|
s5 += 0x10000;
|
|
}
|
|
|
|
if (s5 < 0x8000) {
|
|
s5 *= s3;
|
|
s5 >>= 12;
|
|
s2 = s4 + s5;
|
|
|
|
if (s2 >= 0x10000) {
|
|
s2 -= 0x10000;
|
|
}
|
|
} else {
|
|
s5 = 0x10000 - s5;
|
|
s5 *= s3;
|
|
s5 >>= 12;
|
|
s2 = s4 - s5;
|
|
|
|
if (s2 < 0) {
|
|
s2 += 0x10000;
|
|
}
|
|
}
|
|
|
|
t0slot->unk02 = s0;
|
|
t0slot->unk04 = s1;
|
|
t0slot->unk06 = s2;
|
|
t0slot++;
|
|
} while (t2ptr8 < t3ptr8);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Expects: t3 t6 v1 gp s8
|
|
*/
|
|
static u32 modelasm_read_frame_data(void)
|
|
{
|
|
u32 v0 = 0;
|
|
s32 s6;
|
|
|
|
if (!v1) {
|
|
return 0;
|
|
}
|
|
|
|
while (v1 > gp) {
|
|
v1 -= gp;
|
|
v0 |= (((1 << gp) - 1) & sr8) << v1;
|
|
s6 = t3ptr8 - t6ptr8;
|
|
|
|
if (s6 >= 4) {
|
|
s6 = 4;
|
|
}
|
|
|
|
sr8 = ((uintptr_t) t6ptr8 & 3) - 4;
|
|
sr8 = -sr8;
|
|
|
|
if (sr8 != 0 && sr8 < s6) {
|
|
s6 = sr8;
|
|
}
|
|
|
|
switch (s6) {
|
|
case 1: // 19c64
|
|
sr8 = t6ptr8[0];
|
|
t6ptr8++;
|
|
gp = 8;
|
|
break;
|
|
case 2: // 19c70
|
|
sr8 = (t6ptr8[0] << 8) | t6ptr8[1];
|
|
t6ptr8 += 2;
|
|
gp = 16;
|
|
break;
|
|
case 3: // 19c88
|
|
sr8 = (t6ptr8[0] << 16) | (t6ptr8[1] << 8) | t6ptr8[2];
|
|
t6ptr8 += 3;
|
|
gp = 24;
|
|
break;
|
|
case 4: // 19cac
|
|
sr8 = (t6ptr8[0] << 24) | (t6ptr8[1] << 16) | (t6ptr8[2] << 8) | t6ptr8[3];
|
|
t6ptr8 += 4;
|
|
gp = 32;
|
|
break;
|
|
}
|
|
}
|
|
|
|
gp -= v1;
|
|
|
|
if (v1) {
|
|
v0 |= (sr8 >> gp) & ((1 << v1) - 1);
|
|
}
|
|
|
|
return v0;
|
|
}
|
|
|
|
/**
|
|
* Indexed by node type.
|
|
*
|
|
* Each value is the byte offset into the rodata struct where that node type's
|
|
* rwdataindex property can be found, or 0xff is there is none.
|
|
*/
|
|
u8 var8005ef90[] = {
|
|
0xff, 0x08, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff,
|
|
0x0c, 0x22, 0xff, 0x44,
|
|
0x20, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0x04, 0xff,
|
|
0xff, 0xff, 0xff, 0x00,
|
|
0x14, 0x00,
|
|
};
|
|
|
|
static union modelrwdata *modelasm_get_node_rw_data(struct model *model, struct modelnode *node, bool is_head)
|
|
{
|
|
u32 index = 0;
|
|
u32 *rwdatas = model->rwdatas;
|
|
u8 type = node->type & 0xff;
|
|
|
|
if (type < ARRAYCOUNT(var8005ef90)) {
|
|
if (var8005ef90[type] != 0xff) {
|
|
index = *(u16 *) ((uintptr_t) node->rodata + var8005ef90[type]);
|
|
}
|
|
}
|
|
|
|
if (is_head) {
|
|
while (node->parent) {
|
|
node = node->parent;
|
|
|
|
if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) {
|
|
union modelrwdata *tmp = modelasm_get_node_rw_data(model, node, false);
|
|
rwdatas = tmp->headspot.rwdatas;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (union modelrwdata *) &rwdatas[index];
|
|
}
|
|
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
void *model_get_node_rw_data(struct model *model, struct modelnode *node)
|
|
{
|
|
u32 index = 0;
|
|
u32 *rwdatas = model->rwdatas;
|
|
u8 type = node->type & 0xff;
|
|
|
|
if (type < ARRAYCOUNT(var8005ef90)) {
|
|
if (var8005ef90[type] != 0xff) {
|
|
index = *(u16 *) ((uintptr_t) node->rodata + var8005ef90[type]);
|
|
}
|
|
}
|
|
|
|
if (model->unk00) {
|
|
while (node->parent) {
|
|
node = node->parent;
|
|
|
|
if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) {
|
|
struct modelrwdata_headspot *tmp = model_get_node_rw_data(model, node);
|
|
rwdatas = tmp->rwdatas;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return &rwdatas[index];
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Expects: f0-f3, f16-f22
|
|
*/
|
|
static void modelasm_math_pain1(f32 f30)
|
|
{
|
|
f32 f6;
|
|
f32 f7;
|
|
f32 f8;
|
|
f32 f9;
|
|
|
|
f4 = 0;
|
|
|
|
while (true) {
|
|
f5 = f16 * f0;
|
|
f6 = f17 * f1;
|
|
f7 = f18 * f2;
|
|
f6 = f5 + f6;
|
|
f5 = f19 * f3;
|
|
f6 = f6 + f7;
|
|
f6 = f6 + f5;
|
|
|
|
if (f6 >= 0.0f) {
|
|
break;
|
|
}
|
|
|
|
f0 = -f0;
|
|
f1 = -f1;
|
|
f2 = -f2;
|
|
f3 = -f3;
|
|
}
|
|
|
|
if (f6 < -0.99994999170303f) {
|
|
f6 = f30 * f16;
|
|
f5 = f5 - f30;
|
|
f7 = f5 * f0;
|
|
f0 = f7 - f6;
|
|
f6 = f30 * f17;
|
|
f7 = f5 * f1;
|
|
f8 = f30 * f18;
|
|
f1 = f7 - f6;
|
|
f9 = f5 * f2;
|
|
f6 = f30 * f19;
|
|
f2 = f9 - f8;
|
|
f7 = f5 * f3;
|
|
f2 = f7 - f6;
|
|
return;
|
|
}
|
|
|
|
if (f6 <= 0.99994999170303f) {
|
|
f7 = modelasm_acos_or_asin(f6);
|
|
f20 = f0;
|
|
f21 = sinf(f7);
|
|
f22 = sinf((1.0f - f30) * f7);
|
|
f0 = sinf(f7 * f30);
|
|
|
|
f5 = f22 / f21;
|
|
f30 = f0 / f21;
|
|
f0 = f20;
|
|
} else {
|
|
f5 = 1.0f - f30;
|
|
}
|
|
|
|
f6 = f5 * f16;
|
|
f7 = f30 * f0;
|
|
f8 = f5 * f17;
|
|
f0 = f6 + f7;
|
|
f9 = f30 * f1;
|
|
f6 = f5 * f18;
|
|
f1 = f8 + f9;
|
|
f7 = f30 * f2;
|
|
f8 = f5 * f19;
|
|
f2 = f6 + f7;
|
|
f9 = f30 * f3;
|
|
f3 = f8 + f9;
|
|
}
|
|
|
|
/**
|
|
* Expects: f0 f1 f2 f3 f4 f5
|
|
*/
|
|
static void modelasm_math_pain2(void)
|
|
{
|
|
f32 f6;
|
|
f32 f7;
|
|
f32 f8;
|
|
f32 f9;
|
|
f32 f10;
|
|
f32 f11;
|
|
f32 f26;
|
|
|
|
f6 = f0 * f2;
|
|
f7 = f0 * f3;
|
|
f8 = f1 * f2;
|
|
f9 = f1 * f3;
|
|
f0 = f6 * f4;
|
|
f1 = f9 * f5;
|
|
f2 = f8 * f4;
|
|
f0 = f0 + f1;
|
|
f1 = f7 * f5;
|
|
f3 = f7 * f5;
|
|
f10 = f7 * f4;
|
|
f1 = f2 - f1;
|
|
f11 = f8 * f5;
|
|
f26 = f6 * f5;
|
|
f2 = f10 + f11;
|
|
f10 = f9 * f4;
|
|
f3 = f26 - f10;
|
|
}
|
|
|
|
static void modelasm_prepare_rot_mtx180(s32 t2, s32 t3, s32 t4)
|
|
{
|
|
// Very close to: 1.0f / (180 * 180 / M_PI)
|
|
f32 f8 = t4 * 0.000095873801910784f;
|
|
f32 f7 = t3 * 0.000095873801910784f;
|
|
f32 f6 = t2 * 0.000095873801910784f;
|
|
|
|
f5 = sinf(f8);
|
|
f4 = sinf(f8 + DTOR(90));
|
|
f3 = sinf(f7);
|
|
f2 = sinf(f7 + DTOR(90));
|
|
f1 = sinf(f6);
|
|
f0 = sinf(f6 + DTOR(90));
|
|
}
|
|
|
|
static void modelasm_prepare_rot_mtx360(s32 t2, s32 t3, s32 t4)
|
|
{
|
|
// Very close to: 1.0f / (360 * 180 / M_PI)
|
|
f32 f8 = t4 * 0.000047936900955392f;
|
|
f32 f7 = t3 * 0.000047936900955392f;
|
|
f32 f6 = t2 * 0.000047936900955392f;
|
|
|
|
f5 = sinf(f8);
|
|
f4 = sinf(f8 + DTOR(90));
|
|
f3 = sinf(f7);
|
|
f2 = sinf(f7 + DTOR(90));
|
|
f1 = sinf(f6);
|
|
f0 = sinf(f6 + DTOR(90));
|
|
}
|
|
|
|
/**
|
|
* Expects: f0 f1 f2 f3 f4 f5
|
|
*/
|
|
static void modelasm_math_pain3(void)
|
|
{
|
|
f32 f6 = f1 * f5;
|
|
f32 f7 = f0 * f5;
|
|
f32 f8 = f1 * f4;
|
|
f32 f9 = f0 * f4;
|
|
|
|
f12 = f2 * f4;
|
|
f13 = f2 * f5;
|
|
f14 = -f3;
|
|
|
|
f15 = f8 * f3 - f7;
|
|
f16 = f6 * f3 + f9;
|
|
f17 = f1 * f2;
|
|
|
|
f18 = f9 * f3 + f6;
|
|
f19 = f7 * f3 - f8;
|
|
f20 = f0 * f2;
|
|
}
|
|
|
|
/**
|
|
* Expects: f0 f1 f2 f3
|
|
*/
|
|
static void modelasm_math_pain4(void)
|
|
{
|
|
f32 f6;
|
|
f32 f7;
|
|
f32 f8;
|
|
f32 f9;
|
|
f32 f10;
|
|
f32 f11;
|
|
f32 f24;
|
|
f32 f25;
|
|
f32 f26;
|
|
f32 f27;
|
|
f32 f28;
|
|
|
|
f4 = f0 * f0;
|
|
f5 = f1 * f1;
|
|
f6 = f2 * f2;
|
|
f4 = f4 + f5;
|
|
f5 = f3 * f3;
|
|
f4 = f4 + f6;
|
|
f4 = f4 + f5;
|
|
f4 = 2.0f / f4;
|
|
f5 = f1 * f4;
|
|
f6 = f2 * f4;
|
|
f7 = f3 * f4;
|
|
f8 = f0 * f5;
|
|
f9 = f0 * f6;
|
|
f10 = f0 * f7;
|
|
f11 = f1 * f5;
|
|
f24 = f1 * f6;
|
|
f16 = 1.0f - f11;
|
|
f25 = f1 * f7;
|
|
f20 = 1.0f - f11;
|
|
f26 = f2 * f6;
|
|
f13 = f24 + f10;
|
|
f27 = f2 * f7;
|
|
f12 = 1.0f - f26;
|
|
f28 = f3 * f7;
|
|
f14 = f25 - f9;
|
|
f12 = f12 - f28;
|
|
f15 = f24 - f10;
|
|
f16 = f16 - f28;
|
|
f17 = f27 + f8;
|
|
f18 = f25 + f9;
|
|
f19 = f27 - f8;
|
|
f20 = f20 - f26;
|
|
}
|
|
|
|
/**
|
|
* Expects: f12-f23
|
|
*/
|
|
static void modelasm_mtx_multiply(Mtxf *src, Mtxf *dst)
|
|
{
|
|
f32 f0;
|
|
f32 f1;
|
|
f32 f2;
|
|
f32 f3;
|
|
f32 f4;
|
|
f32 f5;
|
|
f32 f6;
|
|
f32 f7;
|
|
f32 f8;
|
|
f32 f9;
|
|
f32 f10;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
f0 = src->m[0][i];
|
|
f1 = src->m[1][i];
|
|
f2 = src->m[2][i];
|
|
f3 = src->m[3][i];
|
|
|
|
f4 = f0 * f12;
|
|
f5 = f1 * f13;
|
|
f6 = f2 * f14;
|
|
|
|
dst->m[0][i] = f4 + f5 + f6;
|
|
|
|
f8 = f0 * f15;
|
|
f9 = f1 * f16;
|
|
f10 = f2 * f17;
|
|
|
|
dst->m[1][i] = f8 + f9 + f10;
|
|
|
|
f4 = f0 * f18;
|
|
f5 = f1 * f19;
|
|
f6 = f2 * f20;
|
|
|
|
dst->m[2][i] = f4 + f5 + f6;
|
|
|
|
f8 = f0 * f21;
|
|
f9 = f1 * f22;
|
|
f10 = f2 * f23;
|
|
|
|
dst->m[3][i] = f8 + f9 + f10 + f3;
|
|
}
|
|
|
|
dst->m[0][3] = 0;
|
|
dst->m[1][3] = 0;
|
|
dst->m[2][3] = 0;
|
|
dst->m[3][3] = 1;
|
|
}
|
|
|
|
static Mtxf *modelasm_find_node_mtx(struct model *model, struct modelnode *node)
|
|
{
|
|
do {
|
|
u8 type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO) {
|
|
return &model->matrices[node->rodata->chrinfo.mtxindex];
|
|
}
|
|
|
|
if (type == MODELNODETYPE_POSITION) {
|
|
return &model->matrices[node->rodata->position.mtxindex0];
|
|
}
|
|
|
|
if (type == MODELNODETYPE_POSITIONHELD) {
|
|
return &model->matrices[node->rodata->positionheld.mtxindex];
|
|
}
|
|
|
|
node = node->parent;
|
|
} while (node);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* See similar function func0f096890.
|
|
*/
|
|
static f32 modelasm_acos_or_asin(f32 f6)
|
|
{
|
|
s32 t2;
|
|
s32 t3;
|
|
u16 *array;
|
|
s32 shiftamount;
|
|
s32 mask;
|
|
s32 s0;
|
|
s32 s1;
|
|
s32 s2;
|
|
s32 s3;
|
|
s32 s4;
|
|
|
|
t2 = f6 * 32767.0f;
|
|
|
|
if (t2 > 32767) {
|
|
t2 = 32767;
|
|
} else if (t2 < -32767) {
|
|
t2 = -32767;
|
|
}
|
|
|
|
t3 = t2;
|
|
|
|
if (t3 < 0) {
|
|
t3 = -t3;
|
|
}
|
|
|
|
if (t3 >= 32736) {
|
|
array = &var8006ae90[126];
|
|
t3 -= 32736;
|
|
shiftamount = 3;
|
|
mask = 0x07;
|
|
} else if (t3 >= 30720) {
|
|
array = &var8006ae90[62];
|
|
t3 -= 30720;
|
|
shiftamount = 5;
|
|
mask = 0x1f;
|
|
} else {
|
|
array = &var8006ae90[0];
|
|
shiftamount = 9;
|
|
mask = 0x1ff;
|
|
}
|
|
|
|
s0 = t3 >> shiftamount;
|
|
array += s0;
|
|
s1 = array[0];
|
|
s2 = array[1];
|
|
s3 = s1 - s2;
|
|
s4 = t3 & mask;
|
|
s3 *= s4;
|
|
s3 >>= shiftamount;
|
|
t3 = s1 - s3;
|
|
|
|
if (t2 < 0) {
|
|
t3 = 0xffff - t3;
|
|
}
|
|
|
|
return 0.000047937632189132f * t3;
|
|
}
|
|
|
|
f32 cosf(f32 radians)
|
|
{
|
|
return sinf(radians + DTOR(90));
|
|
}
|
|
|
|
f32 sinf(f32 radians)
|
|
{
|
|
f32 f0;
|
|
f32 f13;
|
|
f32 f14;
|
|
f32 f15;
|
|
s32 t0;
|
|
s32 t1;
|
|
f32 ret;
|
|
|
|
t0 = *(u32 *) &radians;
|
|
t0 = (t0 >> 22) & 0x1ff;
|
|
|
|
if (t0 < 255) {
|
|
if (t0 >= 230) {
|
|
f14 = radians * radians;
|
|
|
|
ret = 0.0000026057805371238f;
|
|
ret *= f14;
|
|
ret += -0.0001980960223591f;
|
|
ret *= f14;
|
|
ret += 0.0083330664783716f;
|
|
ret *= f14;
|
|
ret += -0.16666659712791f;
|
|
ret *= f14;
|
|
ret *= radians;
|
|
ret += radians;
|
|
} else {
|
|
ret = radians;
|
|
}
|
|
} else {
|
|
if (t0 < 310) {
|
|
f14 = radians * 0.31830987334251f;
|
|
|
|
t1 = (s32) (f14 > 0.0f ? f14 + 0.5f : f14 - 0.5f);
|
|
f14 = t1;
|
|
|
|
f15 = DTOR(180);
|
|
f15 *= f14;
|
|
radians -= f15;
|
|
|
|
f15 = 0.000000031786509424592f;
|
|
f15 *= f14;
|
|
radians -= f15;
|
|
|
|
f14 = radians * radians;
|
|
|
|
ret = 0.0000026057805371238f;
|
|
ret *= f14;
|
|
ret += -0.0001980960223591f;
|
|
ret *= f14;
|
|
ret += 0.0083330664783716f;
|
|
ret *= f14;
|
|
ret += -0.16666659712791f;
|
|
ret *= f14;
|
|
ret *= radians;
|
|
ret += radians;
|
|
|
|
if (t1 & 1) {
|
|
ret = -ret;
|
|
}
|
|
} else {
|
|
ret = 0;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|