4322 lines
104 KiB
C
4322 lines
104 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/game_096700.h"
|
|
#include "game/acosfasinf.h"
|
|
#include "game/quaternion.h"
|
|
#include "game/camera.h"
|
|
#include "game/floor.h"
|
|
#include "game/ceil.h"
|
|
#include "game/tex.h"
|
|
#include "game/gfxmemory.h"
|
|
#include "game/bg.h"
|
|
#include "game/file.h"
|
|
#include "bss.h"
|
|
#include "lib/rng.h"
|
|
#include "lib/mtx.h"
|
|
#include "lib/anim.h"
|
|
#include "lib/model.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
u8 var8005efb0_2 = 0;
|
|
#endif
|
|
|
|
u32 var8005efb0 = 0;
|
|
|
|
bool g_ModelDistanceDisabled = false;
|
|
f32 g_ModelDistanceScale = 1;
|
|
bool var8005efbc = false;
|
|
f32 var8005efc0 = 0;
|
|
bool (*var8005efc4)(struct model *model, struct modelnode *node) = NULL;
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
bool var8005efd8_2 = false;
|
|
#endif
|
|
|
|
struct gfxvtx *(*g_ModelVtxAllocatorFunc)(s32 numvertices) = NULL;
|
|
void (*g_ModelJointPositionedFunc)(s32 mtxindex, Mtxf *mtx) = NULL;
|
|
|
|
void modelSetDistanceChecksDisabled(bool disabled)
|
|
{
|
|
g_ModelDistanceDisabled = disabled;
|
|
}
|
|
|
|
void modelSetDistanceScale(f32 scale)
|
|
{
|
|
g_ModelDistanceScale = scale;
|
|
}
|
|
|
|
void modelSetVtxAllocatorFunc(struct gfxvtx *(*fn)(s32 numvertices))
|
|
{
|
|
g_ModelVtxAllocatorFunc = fn;
|
|
}
|
|
|
|
s32 model0001a524(struct modelnode *node, s32 arg1)
|
|
{
|
|
s32 index;
|
|
union modelrodata *rodata1;
|
|
union modelrodata *rodata2;
|
|
union modelrodata *rodata3;
|
|
|
|
while (node) {
|
|
switch (node->type & 0xff) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
rodata1 = node->rodata;
|
|
return rodata1->chrinfo.mtxindex;
|
|
case MODELNODETYPE_POSITION:
|
|
rodata2 = node->rodata;
|
|
return rodata2->position.mtxindexes[arg1 == 0x200 ? 2 : (arg1 == 0x100 ? 1 : 0)];
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
rodata3 = node->rodata;
|
|
return rodata3->positionheld.mtxindex;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
Mtxf *model0001a5cc(struct model *model, struct modelnode *node, s32 arg2)
|
|
{
|
|
s32 index = model0001a524(node, arg2);
|
|
|
|
if (index >= 0) {
|
|
return &model->matrices[index];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Mtxf *model0001a60c(struct model *model)
|
|
{
|
|
return model0001a5cc(model, model->filedata->rootnode, 0);
|
|
}
|
|
|
|
struct modelnode *model0001a634(struct model *model, s32 mtxindex)
|
|
{
|
|
struct modelnode *node = model->filedata->rootnode;
|
|
union modelrodata *rodata1;
|
|
union modelrodata *rodata2;
|
|
union modelrodata *rodata3;
|
|
|
|
while (node) {
|
|
switch (node->type & 0xff) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
rodata1 = node->rodata;
|
|
if (mtxindex == rodata1->chrinfo.mtxindex) {
|
|
return node;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITION:
|
|
rodata2 = node->rodata;
|
|
if (mtxindex == rodata2->position.mtxindexes[0]
|
|
|| mtxindex == rodata2->position.mtxindexes[1]
|
|
|| mtxindex == rodata2->position.mtxindexes[2]) {
|
|
return node;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
rodata3 = node->rodata;
|
|
if (mtxindex == rodata3->positionheld.mtxindex) {
|
|
return node;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node && node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct modelnode *model0001a740(struct modelnode *node)
|
|
{
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO
|
|
|| type == MODELNODETYPE_POSITION
|
|
|| type == MODELNODETYPE_POSITIONHELD) {
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
struct modelnode *model0001a784(struct modelnode *node)
|
|
{
|
|
while ((node = node->parent)) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO
|
|
|| type == MODELNODETYPE_POSITION
|
|
|| type == MODELNODETYPE_POSITIONHELD) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
struct modelnode *model0001a7cc(struct modelnode *basenode)
|
|
{
|
|
struct modelnode *node = basenode->child;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO
|
|
|| type == MODELNODETYPE_POSITION
|
|
|| type == MODELNODETYPE_POSITIONHELD) {
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node == basenode) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
struct modelnode *model0001a85c(struct modelnode *basenode)
|
|
{
|
|
struct modelnode *node = basenode;
|
|
struct modelnode *next;
|
|
u32 type;
|
|
|
|
while (node) {
|
|
if (node != basenode && node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node != basenode) {
|
|
type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO
|
|
|| type == MODELNODETYPE_POSITION
|
|
|| type == MODELNODETYPE_POSITIONHELD) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
|
|
if (!node) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO
|
|
|| type == MODELNODETYPE_POSITION
|
|
|| type == MODELNODETYPE_POSITIONHELD) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
struct modelnode *modelGetPart(struct modelfiledata *modelfiledata, s32 partnum)
|
|
{
|
|
s32 upper;
|
|
s32 lower;
|
|
u32 i;
|
|
s16 *partnums;
|
|
|
|
if (modelfiledata->numparts == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
partnums = (s16 *)&modelfiledata->parts[modelfiledata->numparts];
|
|
lower = 0;
|
|
upper = modelfiledata->numparts;
|
|
|
|
while (upper >= lower) {
|
|
i = (lower + upper) / 2;
|
|
|
|
if (partnum == partnums[i]) {
|
|
return modelfiledata->parts[i];
|
|
}
|
|
|
|
if (partnum < partnums[i]) {
|
|
upper = i - 1;
|
|
} else {
|
|
lower = i + 1;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void *modelGetPartRodata(struct modelfiledata *modelfiledata, s32 partnum)
|
|
{
|
|
struct modelnode *node = modelGetPart(modelfiledata, partnum);
|
|
|
|
if (node) {
|
|
return node->rodata;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
f32 model0001a9e8(struct model *model)
|
|
{
|
|
Mtxf *mtx = model0001a60c(model);
|
|
|
|
if (mtx) {
|
|
return -mtx->m[3][2];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
// ntsc-beta has this function in another file
|
|
void *modelGetNodeRwData(struct model *model, struct modelnode *node)
|
|
{
|
|
u32 index = 0;
|
|
union modelrwdata **rwdatas = model->rwdatas;
|
|
|
|
switch (node->type & 0xff) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
index = node->rodata->chrinfo.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
index = node->rodata->dl.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
index = node->rodata->distance.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
index = node->rodata->toggle.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
index = node->rodata->reorder.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_0B:
|
|
index = node->rodata->type0b.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
index = node->rodata->chrgunfire.rwdataindex;
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
index = node->rodata->headspot.rwdataindex;
|
|
break;
|
|
}
|
|
|
|
while (node->parent) {
|
|
node = node->parent;
|
|
|
|
if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) {
|
|
struct modelrwdata_headspot *tmp = modelGetNodeRwData(model, node);
|
|
rwdatas = tmp->rwdatas;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return &rwdatas[index];
|
|
}
|
|
#endif
|
|
|
|
void modelNodeGetPosition(struct model *model, struct modelnode *node, struct coord *pos)
|
|
{
|
|
switch (node->type & 0xff) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
{
|
|
struct modelrwdata_chrinfo *rwdata = modelGetNodeRwData(model, node);
|
|
pos->x = rwdata->pos.x;
|
|
pos->y = rwdata->pos.y;
|
|
pos->z = rwdata->pos.z;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITION:
|
|
{
|
|
struct modelrodata_position *rodata = &node->rodata->position;
|
|
pos->x = rodata->pos.x;
|
|
pos->y = rodata->pos.y;
|
|
pos->z = rodata->pos.z;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
{
|
|
struct modelrodata_positionheld *rodata = &node->rodata->positionheld;
|
|
pos->x = rodata->pos.x;
|
|
pos->y = rodata->pos.y;
|
|
pos->z = rodata->pos.z;
|
|
}
|
|
break;
|
|
default:
|
|
pos->x = 0;
|
|
pos->y = 0;
|
|
pos->z = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void modelNodeSetPosition(struct model *model, struct modelnode *node, struct coord *pos)
|
|
{
|
|
switch (node->type & 0xff) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
{
|
|
struct modelrwdata_chrinfo *rwdata = modelGetNodeRwData(model, node);
|
|
struct coord diff[1];
|
|
|
|
diff[0].x = pos->x - rwdata->pos.x;
|
|
diff[0].z = pos->z - rwdata->pos.z;
|
|
|
|
rwdata->pos.x = pos->x;
|
|
rwdata->pos.y = pos->y;
|
|
rwdata->pos.z = pos->z;
|
|
|
|
rwdata->unk24.x += diff[0].x; rwdata->unk24.z += diff[0].z;
|
|
rwdata->unk34.x += diff[0].x; rwdata->unk34.z += diff[0].z;
|
|
rwdata->unk40.x += diff[0].x; rwdata->unk40.z += diff[0].z;
|
|
rwdata->unk4c.x += diff[0].x; rwdata->unk4c.z += diff[0].z;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITION:
|
|
{
|
|
struct modelrodata_position *rodata = &node->rodata->position;
|
|
rodata->pos.x = pos->x;
|
|
rodata->pos.y = pos->y;
|
|
rodata->pos.z = pos->z;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
{
|
|
struct modelrodata_positionheld *rodata = &node->rodata->positionheld;
|
|
rodata->pos.x = pos->x;
|
|
rodata->pos.y = pos->y;
|
|
rodata->pos.z = pos->z;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void modelGetRootPosition(struct model *model, struct coord *pos)
|
|
{
|
|
modelNodeGetPosition(model, model->filedata->rootnode, pos);
|
|
}
|
|
|
|
void modelSetRootPosition(struct model *model, struct coord *pos)
|
|
{
|
|
modelNodeSetPosition(model, model->filedata->rootnode, pos);
|
|
}
|
|
|
|
void modelNodeGetModelRelativePosition(struct model *model, struct modelnode *node, struct coord *pos)
|
|
{
|
|
pos->x = 0;
|
|
pos->y = 0;
|
|
pos->z = 0;
|
|
|
|
while (node) {
|
|
struct coord nodepos;
|
|
u32 type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO
|
|
|| type == MODELNODETYPE_POSITION
|
|
|| type == MODELNODETYPE_POSITIONHELD) {
|
|
modelNodeGetPosition(model, node, &nodepos);
|
|
pos->x += nodepos.x;
|
|
pos->y += nodepos.y;
|
|
pos->z += nodepos.z;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
|
|
f32 model0001ae44(struct model *model)
|
|
{
|
|
if ((model->filedata->rootnode->type & 0xff) == MODELNODETYPE_CHRINFO) {
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, model->filedata->rootnode);
|
|
return rwdata->chrinfo.unk14;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void model0001ae90(struct model *model, f32 angle)
|
|
{
|
|
if ((model->filedata->rootnode->type & 0xff) == MODELNODETYPE_CHRINFO) {
|
|
struct modelrwdata_chrinfo *rwdata = modelGetNodeRwData(model, model->filedata->rootnode);
|
|
f32 diff = angle - rwdata->unk14;
|
|
|
|
if (diff < 0) {
|
|
diff += M_BADTAU;
|
|
}
|
|
|
|
rwdata->unk30 += diff;
|
|
|
|
if (rwdata->unk30 >= M_BADTAU) {
|
|
rwdata->unk30 -= M_BADTAU;
|
|
}
|
|
|
|
rwdata->unk20 += diff;
|
|
|
|
if (rwdata->unk20 >= M_BADTAU) {
|
|
rwdata->unk20 -= M_BADTAU;
|
|
}
|
|
|
|
rwdata->unk14 = angle;
|
|
}
|
|
}
|
|
|
|
void modelSetScale(struct model *model, f32 scale)
|
|
{
|
|
model->scale = scale;
|
|
}
|
|
|
|
void modelSetAnimScale(struct model *model, f32 scale)
|
|
{
|
|
if (model->anim) {
|
|
model->anim->animscale = scale;
|
|
}
|
|
}
|
|
|
|
f32 model0001af80(struct model *model)
|
|
{
|
|
return model->filedata->unk10 * model->scale;
|
|
}
|
|
|
|
void model0001af98(struct coord *arg0, struct coord *arg1, f32 frac)
|
|
{
|
|
arg0->x += (arg1->x - arg0->x) * frac;
|
|
arg0->y += (arg1->y - arg0->y) * frac;
|
|
arg0->z += (arg1->z - arg0->z) * frac;
|
|
}
|
|
|
|
f32 model0001afe8(f32 arg0, f32 angle, f32 mult)
|
|
{
|
|
f32 value = angle - arg0;
|
|
|
|
if (angle < arg0) {
|
|
value += M_BADTAU;
|
|
}
|
|
|
|
if (value < M_PI) {
|
|
arg0 += value * mult;
|
|
|
|
if (arg0 >= M_BADTAU) {
|
|
arg0 -= M_BADTAU;
|
|
}
|
|
} else {
|
|
arg0 -= (M_BADTAU - value) * mult;
|
|
|
|
if (arg0 < 0) {
|
|
arg0 += M_BADTAU;
|
|
}
|
|
}
|
|
|
|
return arg0;
|
|
}
|
|
|
|
void model0001b07c(struct coord *arg0, struct coord *arg1, f32 mult)
|
|
{
|
|
arg0->x = model0001afe8(arg0->x, arg1->x, mult);
|
|
arg0->y = model0001afe8(arg0->y, arg1->y, mult);
|
|
arg0->z = model0001afe8(arg0->z, arg1->z, mult);
|
|
}
|
|
|
|
void model0001b0e8(struct model *model, struct modelnode *node)
|
|
{
|
|
union modelrwdata *rwdata;
|
|
struct anim *anim = model->anim;
|
|
struct coord sp34;
|
|
struct coord sp28;
|
|
f32 frac;
|
|
|
|
if (!anim) {
|
|
return;
|
|
}
|
|
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->chrinfo.unk00) {
|
|
return;
|
|
}
|
|
|
|
sp34.x = rwdata->chrinfo.unk34.x;
|
|
sp34.y = rwdata->chrinfo.unk34.y;
|
|
sp34.z = rwdata->chrinfo.unk34.z;
|
|
|
|
rwdata->chrinfo.unk14 = rwdata->chrinfo.unk30;
|
|
|
|
if (g_Vars.in_cutscene && anim->speed > 0.0f) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
frac = floorf(anim->frac / anim->speed + 0.01f) * anim->speed;
|
|
#else
|
|
frac = floorf(anim->frac / anim->speed) * anim->speed;
|
|
#endif
|
|
} else {
|
|
frac = anim->frac;
|
|
}
|
|
|
|
if (frac != 0.0f && rwdata->chrinfo.unk01) {
|
|
model0001af98(&sp34, &rwdata->chrinfo.unk24, frac);
|
|
|
|
rwdata->chrinfo.unk14 = model0001afe8(rwdata->chrinfo.unk30, rwdata->chrinfo.unk20, frac);
|
|
}
|
|
|
|
if (anim->animnum2 || anim->fracmerge) {
|
|
if (rwdata->chrinfo.unk02) {
|
|
f32 y = rwdata->chrinfo.unk4c.y;
|
|
|
|
if (anim->frac2 != 0.0f) {
|
|
y += (rwdata->chrinfo.unk40.y - y) * anim->frac2;
|
|
}
|
|
|
|
sp34.y += (y - sp34.y) * anim->fracmerge;
|
|
}
|
|
}
|
|
|
|
if (anim->unk70 == NULL) {
|
|
rwdata->chrinfo.pos.x = sp34.x;
|
|
rwdata->chrinfo.pos.y = rwdata->chrinfo.ground + sp34.f[1];
|
|
rwdata->chrinfo.pos.z = sp34.z;
|
|
} else {
|
|
sp28.x = sp34.x;
|
|
sp28.y = sp34.y;
|
|
sp28.z = sp34.z;
|
|
|
|
if (anim->unk70(model, &rwdata->chrinfo.pos, &sp28, &rwdata->chrinfo.ground)) {
|
|
rwdata->chrinfo.pos.x = sp28.x;
|
|
rwdata->chrinfo.pos.y = rwdata->chrinfo.ground + sp28.f[1];
|
|
rwdata->chrinfo.pos.z = sp28.z;
|
|
|
|
sp34.x = sp28.x - sp34.x;
|
|
sp34.z = sp28.z - sp34.z;
|
|
|
|
rwdata->chrinfo.unk34.x += sp34.x;
|
|
rwdata->chrinfo.unk34.z += sp34.z;
|
|
|
|
if (rwdata->chrinfo.unk01) {
|
|
rwdata->chrinfo.unk24.x += sp34.x;
|
|
rwdata->chrinfo.unk24.z += sp34.z;
|
|
}
|
|
|
|
if (rwdata->chrinfo.unk02) {
|
|
rwdata->chrinfo.unk4c.x += sp34.x;
|
|
rwdata->chrinfo.unk4c.z += sp34.z;
|
|
|
|
rwdata->chrinfo.unk40.x += sp34.x;
|
|
rwdata->chrinfo.unk40.z += sp34.z;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001b3bc(struct model *model)
|
|
{
|
|
struct modelnode *node = model->filedata->rootnode;
|
|
|
|
if (node && (node->type & 0xff) == MODELNODETYPE_CHRINFO) {
|
|
model0001b0e8(model, node);
|
|
}
|
|
}
|
|
|
|
void model0001b400(struct modelrenderdata *arg0, struct model *model, struct modelnode *node)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
union modelrodata *rodata = node->rodata;
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
f32 scale = model->scale;
|
|
struct coord *sp254 = &rwdata->chrinfo.pos;
|
|
f32 sp250 = rwdata->chrinfo.unk14;
|
|
Mtxf *sp24c;
|
|
u32 stack1;
|
|
Mtxf *mtx = &model->matrices[rodata->chrinfo.mtxindex];
|
|
s32 sp240 = rodata->chrinfo.unk00;
|
|
struct skeleton *skel = model->filedata->skel;
|
|
struct coord sp230;
|
|
struct coord sp224;
|
|
struct coord sp218;
|
|
Mtxf sp1d8;
|
|
Mtxf sp198;
|
|
Mtxf sp158;
|
|
f32 sp154;
|
|
struct coord sp148;
|
|
struct coord sp13c;
|
|
struct coord sp130;
|
|
struct coord sp124;
|
|
struct coord sp118;
|
|
struct coord sp10c;
|
|
f32 spfc[4];
|
|
f32 spec[4];
|
|
u8 stack4[0xc];
|
|
f32 spdc;
|
|
struct coord spd0;
|
|
struct coord spc4;
|
|
struct coord spb8;
|
|
Mtxf sp78;
|
|
Mtxf sp38;
|
|
|
|
if (rodata->chrinfo.mtxindex);
|
|
|
|
if (node->parent) {
|
|
sp24c = model0001a5cc(model, node->parent, 0);
|
|
} else {
|
|
sp24c = arg0->unk00;
|
|
}
|
|
|
|
anim00024050(sp240, anim->flip, skel, anim->animnum, anim->unk04, &sp230, &sp224, &sp218);
|
|
|
|
if (g_Vars.in_cutscene && anim->speed > 0) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
sp154 = floorf(anim->frac / anim->speed + 0.01f) * anim->speed;
|
|
#else
|
|
sp154 = floorf(anim->frac / anim->speed) * anim->speed;
|
|
#endif
|
|
} else {
|
|
sp154 = anim->frac;
|
|
}
|
|
|
|
if (sp154 != 0.0f) {
|
|
anim00024050(sp240, anim->flip, skel, anim->animnum, anim->unk05, &sp148, &sp13c, &sp130);
|
|
model0001b07c(&sp230, &sp148, sp154);
|
|
}
|
|
|
|
if (anim->fracmerge != 0.0f) {
|
|
anim00024050(sp240, anim->flip2, skel, anim->animnum2, anim->unk06, &sp124, &sp118, &sp10c);
|
|
|
|
if (anim->frac2 != 0.0f) {
|
|
anim00024050(sp240, anim->flip2, skel, anim->animnum2, anim->unk07, &spd0, &spc4, &spb8);
|
|
model0001b07c(&sp124, &spd0, anim->frac2);
|
|
}
|
|
|
|
if ((g_Anims[anim->animnum].flags & ANIMFLAG_02) && (g_Anims[anim->animnum2].flags & ANIMFLAG_02) == 0) {
|
|
mtx4LoadYRotation(rwdata->chrinfo.unk14, &sp78);
|
|
mtx4LoadRotation(&sp124, &sp38);
|
|
mtx00015be0(&sp78, &sp38);
|
|
quaternion0f097044(&sp38, spec);
|
|
} else {
|
|
quaternion0f096ca0(&sp124, spec);
|
|
}
|
|
|
|
quaternion0f096ca0(&sp230, spfc);
|
|
quaternion0f0976c0(spfc, spec);
|
|
quaternionSlerp(spfc, spec, anim->fracmerge, &spdc);
|
|
quaternionToMtx(&spdc, &sp1d8);
|
|
} else {
|
|
mtx4LoadRotation(&sp230, &sp1d8);
|
|
}
|
|
|
|
if (g_Anims[anim->animnum].flags & ANIMFLAG_02) {
|
|
mtx4LoadTranslation(sp254, &sp198);
|
|
} else {
|
|
if (rwdata->chrinfo.unk18 != 0.0f) {
|
|
sp250 = model0001afe8(sp250, rwdata->chrinfo.unk1c, rwdata->chrinfo.unk18);
|
|
}
|
|
|
|
mtx4LoadYRotationWithTranslation(sp254, sp250, &sp198);
|
|
}
|
|
|
|
mtx00015be4(&sp198, &sp1d8, &sp158);
|
|
|
|
if (scale != 1.0f) {
|
|
mtx00015f4c(scale, &sp158);
|
|
}
|
|
|
|
if (sp24c) {
|
|
mtx00015be4(sp24c, &sp158, mtx);
|
|
} else {
|
|
mtx4Copy(&sp158, mtx);
|
|
}
|
|
}
|
|
|
|
void modelPositionJointUsingVecRot(struct modelrenderdata *renderdata, struct model *model, struct modelnode *node, struct coord *rot, struct coord *pos, bool allowscale, struct coord *arg6)
|
|
{
|
|
s32 nodetype = node->type;
|
|
struct modelrodata_position *rodata = &node->rodata->position;
|
|
Mtxf *rendermtx;
|
|
u32 stack;
|
|
Mtxf mtx68;
|
|
s32 mtxindex0 = rodata->mtxindex0;
|
|
s32 mtxindex1 = rodata->mtxindex1;
|
|
s32 mtxindex2 = rodata->mtxindex2;
|
|
Mtxf *matrices = model->matrices;
|
|
|
|
if (node->parent != NULL) {
|
|
rendermtx = model0001a5cc(model, node->parent, 0);
|
|
} else {
|
|
rendermtx = renderdata->unk00;
|
|
}
|
|
|
|
if (rendermtx != NULL) {
|
|
Mtxf *nodemtx = &matrices[mtxindex0];
|
|
|
|
mtx4LoadRotationAndTranslation(pos, rot, &mtx68);
|
|
|
|
if (allowscale && model->scale != 1.0f) {
|
|
mtx00015f04(model->scale, &mtx68);
|
|
}
|
|
|
|
if (arg6->x != 1.0f) {
|
|
mtx00015df0(arg6->x, &mtx68);
|
|
}
|
|
|
|
if (arg6->y != 1.0f) {
|
|
mtx00015e4c(arg6->y, &mtx68);
|
|
}
|
|
|
|
if (arg6->z != 1.0f) {
|
|
mtx00015ea8(arg6->z, &mtx68);
|
|
}
|
|
|
|
mtx00015be4(rendermtx, &mtx68, nodemtx);
|
|
|
|
if (g_ModelJointPositionedFunc != NULL) {
|
|
g_ModelJointPositionedFunc(mtxindex0, nodemtx);
|
|
}
|
|
} else {
|
|
Mtxf *nodemtx = &matrices[mtxindex0];
|
|
|
|
mtx4LoadRotationAndTranslation(pos, rot, nodemtx);
|
|
|
|
if (allowscale && model->scale != 1.0f) {
|
|
mtx00015f04(model->scale, nodemtx);
|
|
}
|
|
|
|
if (arg6->x != 1.0f) {
|
|
mtx00015df0(arg6->x, nodemtx);
|
|
}
|
|
|
|
if (arg6->y != 1.0f) {
|
|
mtx00015e4c(arg6->y, nodemtx);
|
|
}
|
|
|
|
if (arg6->z != 1.0f) {
|
|
mtx00015ea8(arg6->z, nodemtx);
|
|
}
|
|
}
|
|
|
|
if (nodetype & MODELNODETYPE_0100) {
|
|
Mtxf *nodemtx = &matrices[mtxindex1];
|
|
f32 sp3c[4];
|
|
f32 sp2c[4];
|
|
|
|
quaternion0f096ca0(rot, sp3c);
|
|
quaternion0f097518(sp3c, 0.5f, sp2c);
|
|
|
|
if (rendermtx != NULL) {
|
|
quaternionToTransformMtx(pos, sp2c, &mtx68);
|
|
mtx00015be4(rendermtx, &mtx68, nodemtx);
|
|
} else {
|
|
quaternionToTransformMtx(pos, sp2c, nodemtx);
|
|
}
|
|
}
|
|
|
|
if (nodetype & MODELNODETYPE_0200) {
|
|
Mtxf *finalmtx = rendermtx ? &mtx68 : &matrices[mtxindex2];
|
|
f32 roty = rot->y;
|
|
|
|
if (roty < M_PI) {
|
|
roty *= 0.5f;
|
|
} else {
|
|
roty = M_BADTAU - (M_BADTAU - roty) * 0.5f;
|
|
}
|
|
|
|
mtx4LoadYRotation(roty, finalmtx);
|
|
|
|
if (roty >= M_PI) {
|
|
roty = M_BADTAU - roty;
|
|
}
|
|
|
|
if (roty < 0.890118f) { // 51 degrees
|
|
roty = func0f096700(roty);
|
|
} else {
|
|
roty = 1.5f;
|
|
}
|
|
|
|
mtx00015edc(roty, finalmtx);
|
|
mtx4SetTranslation(pos, finalmtx);
|
|
|
|
if (rendermtx != NULL) {
|
|
Mtxf *nodemtx = &matrices[mtxindex2];
|
|
mtx00015be4(rendermtx, finalmtx, nodemtx);
|
|
}
|
|
}
|
|
}
|
|
|
|
void modelPositionJointUsingQuatRot(struct modelrenderdata *renderdata, struct model *model, struct modelnode *node, f32 rot[4], struct coord *pos, struct coord *arg5)
|
|
{
|
|
s32 nodetype = node->type;
|
|
struct modelrodata_position *rodata = &node->rodata->position;
|
|
Mtxf *rendermtx;
|
|
u32 stack;
|
|
Mtxf mtx58;
|
|
s32 mtxindex0 = rodata->mtxindex0;
|
|
s32 mtxindex1 = rodata->mtxindex1;
|
|
s32 mtxindex2 = rodata->mtxindex2;
|
|
Mtxf *matrices = model->matrices;
|
|
|
|
if (node->parent != NULL) {
|
|
rendermtx = model0001a5cc(model, node->parent, 0);
|
|
} else {
|
|
rendermtx = renderdata->unk00;
|
|
}
|
|
|
|
if (rendermtx != NULL) {
|
|
Mtxf *nodemtx = &matrices[mtxindex0];
|
|
|
|
quaternionToTransformMtx(pos, rot, &mtx58);
|
|
|
|
if (arg5->x != 1.0f) {
|
|
mtx00015df0(arg5->x, &mtx58);
|
|
}
|
|
|
|
if (arg5->y != 1.0f) {
|
|
mtx00015e4c(arg5->y, &mtx58);
|
|
}
|
|
|
|
if (arg5->z != 1.0f) {
|
|
mtx00015ea8(arg5->z, &mtx58);
|
|
}
|
|
|
|
mtx00015be4(rendermtx, &mtx58, nodemtx);
|
|
|
|
if (g_ModelJointPositionedFunc != NULL) {
|
|
g_ModelJointPositionedFunc(mtxindex0, nodemtx);
|
|
}
|
|
} else {
|
|
Mtxf *nodemtx = &matrices[mtxindex0];
|
|
|
|
quaternionToTransformMtx(pos, rot, nodemtx);
|
|
|
|
if (arg5->x != 1.0f) {
|
|
mtx00015df0(arg5->x, nodemtx);
|
|
}
|
|
|
|
if (arg5->y != 1.0f) {
|
|
mtx00015e4c(arg5->y, nodemtx);
|
|
}
|
|
|
|
if (arg5->z != 1.0f) {
|
|
mtx00015ea8(arg5->z, nodemtx);
|
|
}
|
|
}
|
|
|
|
if (nodetype & MODELNODETYPE_0100) {
|
|
Mtxf *nodemtx = &matrices[mtxindex1];
|
|
f32 sp2c[4];
|
|
|
|
quaternion0f097518(rot, 0.5f, sp2c);
|
|
|
|
if (rendermtx != NULL) {
|
|
quaternionToTransformMtx(pos, sp2c, &mtx58);
|
|
mtx00015be4(rendermtx, &mtx58, nodemtx);
|
|
} else {
|
|
quaternionToTransformMtx(pos, sp2c, nodemtx);
|
|
}
|
|
}
|
|
|
|
if (nodetype & MODELNODETYPE_0200) {
|
|
Mtxf *finalmtx = rendermtx ? &mtx58 : &matrices[mtxindex2];
|
|
f32 roty = 2.0f * acosf(rot[0]);
|
|
|
|
if (roty < M_PI) {
|
|
roty *= 0.5f;
|
|
} else {
|
|
roty = M_BADTAU - (M_BADTAU - roty) * 0.5f;
|
|
}
|
|
|
|
mtx4LoadYRotation(roty, finalmtx);
|
|
|
|
if (roty >= M_PI) {
|
|
roty = M_BADTAU - roty;
|
|
}
|
|
|
|
if (roty < 0.890118f) { // 51 degrees
|
|
roty = func0f096700(roty);
|
|
} else {
|
|
roty = 1.5f;
|
|
}
|
|
|
|
mtx00015edc(roty, finalmtx);
|
|
mtx4SetTranslation(pos, finalmtx);
|
|
|
|
if (rendermtx != NULL) {
|
|
Mtxf *nodemtx = &matrices[mtxindex2];
|
|
mtx00015be4(rendermtx, finalmtx, nodemtx);
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001bfa8(struct modelrenderdata *renderdata, struct model *model, struct modelnode *node)
|
|
{
|
|
struct anim *anim;
|
|
struct modelrodata_position *rodata = &node->rodata->position;
|
|
s32 partnum;
|
|
struct skeleton *skel;
|
|
struct coord sp144;
|
|
struct coord sp138;
|
|
struct coord sp12c;
|
|
bool sp128;
|
|
Mtxf spe8;
|
|
Mtxf *mtx;
|
|
f32 spe0;
|
|
struct coord spd4;
|
|
struct coord spc8;
|
|
struct coord spbc;
|
|
struct coord spb0;
|
|
struct coord spa4;
|
|
struct coord sp98;
|
|
f32 sp88[4];
|
|
f32 sp78[4];
|
|
f32 sp68[4];
|
|
struct coord sp5c;
|
|
struct coord sp50;
|
|
struct coord sp44;
|
|
|
|
anim = model->anim;
|
|
|
|
if (anim != NULL) {
|
|
partnum = rodata->part;
|
|
skel = model->filedata->skel;
|
|
|
|
if (anim->animnum != 0) {
|
|
sp128 = (g_Anims[anim->animnum].flags & ANIMFLAG_02) && node == model->filedata->rootnode;
|
|
|
|
anim00024050(partnum, anim->flip, skel, anim->animnum, anim->unk04, &sp144, &sp138, &sp12c);
|
|
|
|
if (g_Vars.in_cutscene && anim->speed > 0.0f) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
spe0 = floorf(anim->frac / anim->speed + 0.0099999997764826f) * anim->speed;
|
|
#else
|
|
spe0 = floorf(anim->frac / anim->speed) * anim->speed;
|
|
#endif
|
|
} else {
|
|
spe0 = anim->frac;
|
|
}
|
|
|
|
if (spe0 != 0.0f) {
|
|
anim00024050(partnum, anim->flip, skel, anim->animnum, anim->unk05, &spd4, &spc8, &spbc);
|
|
model0001b07c(&sp144, &spd4, spe0);
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
if (sp128 || var8005efd8_2)
|
|
#else
|
|
if (sp128)
|
|
#endif
|
|
{
|
|
model0001af98(&sp138, &spc8, spe0);
|
|
}
|
|
}
|
|
} else {
|
|
sp138.f[0] = sp138.f[1] = sp138.f[2] = 0.0f;
|
|
sp144.f[0] = sp144.f[1] = sp144.f[2] = 0.0f;
|
|
sp12c.f[0] = sp12c.f[1] = sp12c.f[2] = 1.0f;
|
|
|
|
sp128 = false;
|
|
}
|
|
|
|
if (anim->fracmerge != 0.0f) {
|
|
anim00024050(partnum, anim->flip2, skel, anim->animnum2, anim->unk06, &spb0, &spa4, &sp98);
|
|
|
|
if (anim->frac2 != 0.0f) {
|
|
anim00024050(partnum, anim->flip2, skel, anim->animnum2, anim->unk07, &sp5c, &sp50, &sp44);
|
|
model0001b07c(&spb0, &sp5c, anim->frac2);
|
|
}
|
|
|
|
quaternion0f096ca0(&sp144, sp88);
|
|
quaternion0f096ca0(&spb0, sp78);
|
|
quaternion0f0976c0(sp88, sp78);
|
|
quaternionSlerp(sp88, sp78, anim->fracmerge, sp68);
|
|
|
|
if (sp138.f[0] != 0.0f || sp138.f[1] != 0.0f || sp138.f[2] != 0.0f) {
|
|
sp138.x *= anim->animscale;
|
|
sp138.y *= anim->animscale;
|
|
sp138.z *= anim->animscale;
|
|
|
|
if (node != model->filedata->rootnode) {
|
|
sp138.x += rodata->pos.x;
|
|
sp138.y += rodata->pos.y;
|
|
sp138.z += rodata->pos.z;
|
|
}
|
|
|
|
modelPositionJointUsingQuatRot(renderdata, model, node, sp68, &sp138, &sp12c);
|
|
} else if (node != model->filedata->rootnode) {
|
|
modelPositionJointUsingQuatRot(renderdata, model, node, sp68, &rodata->pos, &sp12c);
|
|
} else {
|
|
modelPositionJointUsingQuatRot(renderdata, model, node, sp68, &sp138, &sp12c);
|
|
}
|
|
} else if (sp128) {
|
|
f32 mult = func0f15c888();
|
|
|
|
sp138.x *= mult;
|
|
sp138.y *= mult;
|
|
sp138.z *= mult;
|
|
|
|
modelPositionJointUsingVecRot(renderdata, model, node, &sp144, &sp138, true, &sp12c);
|
|
} else if (sp138.f[0] != 0.0f || sp138.f[1] != 0.0f || sp138.f[2] != 0.0f) {
|
|
sp138.x *= anim->animscale;
|
|
sp138.y *= anim->animscale;
|
|
sp138.z *= anim->animscale;
|
|
|
|
if (node != model->filedata->rootnode) {
|
|
sp138.x += rodata->pos.x;
|
|
sp138.y += rodata->pos.y;
|
|
sp138.z += rodata->pos.z;
|
|
}
|
|
|
|
modelPositionJointUsingVecRot(renderdata, model, node, &sp144, &sp138, false, &sp12c);
|
|
} else if (node != model->filedata->rootnode) {
|
|
modelPositionJointUsingVecRot(renderdata, model, node, &sp144, &rodata->pos, false, &sp12c);
|
|
} else {
|
|
modelPositionJointUsingVecRot(renderdata, model, node, &sp144, &sp138, false, &sp12c);
|
|
}
|
|
} else {
|
|
if (node->parent) {
|
|
mtx = model0001a5cc(model, node->parent, 0);
|
|
} else {
|
|
mtx = renderdata->unk00;
|
|
}
|
|
|
|
if (mtx) {
|
|
mtx4LoadTranslation(&rodata->pos, &spe8);
|
|
mtx00015be4(mtx, &spe8, &model->matrices[rodata->mtxindex0]);
|
|
} else {
|
|
mtx4LoadTranslation(&rodata->pos, &model->matrices[rodata->mtxindex0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001c5b4(struct modelrenderdata *arg0, struct model *model, struct modelnode *node)
|
|
{
|
|
union modelrodata *rodata = node->rodata;
|
|
Mtxf *sp68;
|
|
Mtxf sp28;
|
|
s32 mtxindex = rodata->positionheld.mtxindex;
|
|
Mtxf *matrices = model->matrices;
|
|
|
|
if (node->parent) {
|
|
sp68 = model0001a5cc(model, node->parent, 0);
|
|
} else {
|
|
sp68 = arg0->unk00;
|
|
}
|
|
|
|
if (sp68) {
|
|
mtx4LoadTranslation(&rodata->positionheld.pos, &sp28);
|
|
mtx00015be4(sp68, &sp28, &matrices[mtxindex]);
|
|
} else {
|
|
mtx4LoadTranslation(&rodata->positionheld.pos, &matrices[mtxindex]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* For a distance node, set its target to visible based on distance.
|
|
*/
|
|
void model0001c664(struct model *model, struct modelnode *node)
|
|
{
|
|
union modelrodata *rodata = node->rodata;
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
Mtxf *mtx = model0001a5cc(model, node, 0);
|
|
f32 distance;
|
|
|
|
if (g_ModelDistanceDisabled || !mtx) {
|
|
distance = 0;
|
|
} else {
|
|
distance = -mtx->m[3][2] * camGetLodScaleZ();
|
|
|
|
if (g_ModelDistanceScale != 1) {
|
|
distance *= g_ModelDistanceScale;
|
|
}
|
|
}
|
|
|
|
if (distance > rodata->distance.near * model->scale || rodata->distance.near == 0) {
|
|
if (distance <= rodata->distance.far * model->scale) {
|
|
rwdata->distance.visible = true;
|
|
node->child = rodata->distance.target;
|
|
return;
|
|
}
|
|
}
|
|
|
|
rwdata->distance.visible = false;
|
|
node->child = NULL;
|
|
}
|
|
|
|
void model0001c784(struct model *model, struct modelnode *node)
|
|
{
|
|
struct modelrodata_distance *rodata = &node->rodata->distance;
|
|
struct modelrwdata_distance *rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->visible) {
|
|
node->child = rodata->target;
|
|
} else {
|
|
node->child = NULL;
|
|
}
|
|
}
|
|
|
|
void model0001c7d0(struct model *model, struct modelnode *node)
|
|
{
|
|
struct modelrodata_toggle *rodata = &node->rodata->toggle;
|
|
struct modelrwdata_toggle *rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->visible) {
|
|
node->child = rodata->target;
|
|
} else {
|
|
node->child = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attach a head model to its placeholder on the body model.
|
|
*
|
|
* The given modelnode is assumed to be of type MODELNODETYPE_HEADSPOT.
|
|
*/
|
|
void modelAttachHead(struct model *model, struct modelnode *bodynode)
|
|
{
|
|
struct modelrwdata_headspot *rwdata = modelGetNodeRwData(model, bodynode);
|
|
|
|
if (rwdata->modelfiledata) {
|
|
struct modelnode *headnode = rwdata->modelfiledata->rootnode;
|
|
|
|
bodynode->child = headnode;
|
|
|
|
while (headnode) {
|
|
headnode->parent = bodynode;
|
|
headnode = headnode->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001c868(struct modelnode *basenode, bool visible)
|
|
{
|
|
union modelrodata *rodata = basenode->rodata;
|
|
struct modelnode *node1;
|
|
struct modelnode *node2;
|
|
struct modelnode *loopnode;
|
|
|
|
if (visible) {
|
|
node1 = rodata->reorder.unk18;
|
|
node2 = rodata->reorder.unk1c;
|
|
} else {
|
|
node1 = rodata->reorder.unk1c;
|
|
node2 = rodata->reorder.unk18;
|
|
}
|
|
|
|
if (node1) {
|
|
// I think what's happening here is there's two groups of siblings,
|
|
// where node1 and node2 are the head nodes. Either group can be first,
|
|
// and this is ensuring the node1 group is first.
|
|
// Note that node2 might be NULL.
|
|
|
|
basenode->child = node1;
|
|
node1->prev = NULL;
|
|
|
|
// Skip through node1's siblings until node2 is found or the end is
|
|
// reached
|
|
loopnode = node1;
|
|
|
|
while (loopnode->next && loopnode->next != node2) {
|
|
loopnode = loopnode->next;
|
|
}
|
|
|
|
loopnode->next = node2;
|
|
|
|
if (node2) {
|
|
// Append node2 and its siblings to node1's siblings
|
|
node2->prev = loopnode;
|
|
loopnode = node2;
|
|
|
|
while (loopnode->next && loopnode->next != node1) {
|
|
loopnode = loopnode->next;
|
|
}
|
|
|
|
loopnode->next = NULL;
|
|
}
|
|
} else {
|
|
basenode->child = node2;
|
|
|
|
if (node2) {
|
|
node2->prev = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void modelRenderNodeReorder(struct model *model, struct modelnode *node)
|
|
{
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
|
|
model0001c868(node, rwdata->reorder.visible);
|
|
}
|
|
|
|
void model0001c950(struct model *model, struct modelnode *node)
|
|
{
|
|
union modelrodata *rodata = node->rodata;
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
Mtxf *mtx = model0001a5cc(model, node, 0);
|
|
struct coord sp38;
|
|
struct coord sp2c;
|
|
f32 tmp;
|
|
|
|
if (rodata->reorder.unk20 == 0) {
|
|
sp38.x = rodata->reorder.unk0c[0];
|
|
sp38.y = rodata->reorder.unk0c[1];
|
|
sp38.z = rodata->reorder.unk0c[2];
|
|
mtx4RotateVecInPlace(mtx, &sp38);
|
|
} else if (rodata->reorder.unk20 == 2) {
|
|
sp38.x = mtx->m[1][0] * rodata->reorder.unk0c[1];
|
|
sp38.y = mtx->m[1][1] * rodata->reorder.unk0c[1];
|
|
sp38.z = mtx->m[1][2] * rodata->reorder.unk0c[1];
|
|
} else if (rodata->reorder.unk20 == 3) {
|
|
sp38.x = mtx->m[2][0] * rodata->reorder.unk0c[2];
|
|
sp38.y = mtx->m[2][1] * rodata->reorder.unk0c[2];
|
|
sp38.z = mtx->m[2][2] * rodata->reorder.unk0c[2];
|
|
} else if (rodata->reorder.unk20 == 1) {
|
|
sp38.x = mtx->m[0][0] * rodata->reorder.unk0c[0];
|
|
sp38.y = mtx->m[0][1] * rodata->reorder.unk0c[0];
|
|
sp38.z = mtx->m[0][2] * rodata->reorder.unk0c[0];
|
|
}
|
|
|
|
sp2c.x = rodata->reorder.unk00;
|
|
sp2c.y = rodata->reorder.unk04;
|
|
sp2c.z = rodata->reorder.unk08;
|
|
|
|
mtx4TransformVecInPlace(mtx, &sp2c);
|
|
|
|
tmp = sp38.f[0] * sp2c.f[0] + sp38.f[1] * sp2c.f[1] + sp38.f[2] * sp2c.f[2];
|
|
|
|
if (tmp < 0) {
|
|
rwdata->reorder.visible = true;
|
|
} else {
|
|
rwdata->reorder.visible = false;
|
|
}
|
|
|
|
modelRenderNodeReorder(model, node);
|
|
}
|
|
|
|
void model0001cb0c(struct model *model, struct modelnode *parent)
|
|
{
|
|
struct modelnode *node = parent->child;
|
|
|
|
if (parent);
|
|
|
|
while (node) {
|
|
s32 type = node->type & 0xff;
|
|
bool dochildren = true;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
case MODELNODETYPE_POSITION:
|
|
case MODELNODETYPE_0B:
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
case MODELNODETYPE_0D:
|
|
case MODELNODETYPE_0E:
|
|
case MODELNODETYPE_0F:
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
dochildren = false;
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
model0001c664(model, node);
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
model0001c950(model, node);
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
modelAttachHead(model, node);
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
break;
|
|
}
|
|
|
|
if (dochildren && node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node == parent->parent) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001cc20(struct model *model)
|
|
{
|
|
struct modelnode *node = model->filedata->rootnode;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_DISTANCE:
|
|
model0001c664(model, node);
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
model0001c950(model, node);
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
model0001c7d0(model, node);
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
modelAttachHead(model, node);
|
|
break;
|
|
case MODELNODETYPE_CHRINFO:
|
|
case MODELNODETYPE_DL:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001cd18(struct modelrenderdata *arg0, struct model *model)
|
|
{
|
|
struct modelnode *node = model->filedata->rootnode;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
model0001b400(arg0, model, node);
|
|
break;
|
|
case MODELNODETYPE_POSITION:
|
|
model0001bfa8(arg0, model, node);
|
|
break;
|
|
case MODELNODETYPE_POSITIONHELD:
|
|
model0001c5b4(arg0, model, node);
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
model0001c664(model, node);
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
model0001c950(model, node);
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
model0001c7d0(model, node);
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
modelAttachHead(model, node);
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001ce64(struct modelrenderdata *arg0, struct model *model)
|
|
{
|
|
model->matrices = arg0->unk10;
|
|
|
|
arg0->unk10 += model->filedata->nummatrices;
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
if (var8005efb0_2 || !model00018680()) {
|
|
model0001cd18(arg0, model);
|
|
}
|
|
#else
|
|
if (!model00018680()) {
|
|
model0001cd18(arg0, model);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void model0001cebc(struct modelrenderdata *arg0, struct model *model)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
f32 speed;
|
|
f32 frac;
|
|
f32 frac2;
|
|
|
|
if (anim && anim->animnum) {
|
|
if (PLAYERCOUNT() >= 2) {
|
|
frac = anim->frac;
|
|
frac2 = anim->frac2;
|
|
speed = anim->speed;
|
|
|
|
if (speed < 0) {
|
|
speed = -speed;
|
|
}
|
|
|
|
if (speed > 0.5f) {
|
|
anim->frac = 0;
|
|
anim->frac2 = 0;
|
|
}
|
|
}
|
|
|
|
anim00023d38(anim->animnum);
|
|
anim->unk04 = anim00023ab0(anim->animnum, anim->framea);
|
|
|
|
if (anim->frac != 0) {
|
|
anim->unk05 = anim00023ab0(anim->animnum, anim->frameb);
|
|
}
|
|
|
|
if (anim->animnum2) {
|
|
anim00023d38(anim->animnum2);
|
|
anim->unk06 = anim00023ab0(anim->animnum2, anim->frame2a);
|
|
|
|
if (anim->frac2 != 0) {
|
|
anim->unk07 = anim00023ab0(anim->animnum2, anim->frame2b);
|
|
}
|
|
}
|
|
|
|
anim00023d0c();
|
|
}
|
|
|
|
model0001ce64(arg0, model);
|
|
|
|
if (PLAYERCOUNT() >= 2 && anim && anim->animnum) {
|
|
anim->frac = frac;
|
|
anim->frac2 = frac2;
|
|
}
|
|
}
|
|
|
|
s16 modelGetAnimNum(struct model *model)
|
|
{
|
|
if (model->anim) {
|
|
return model->anim->animnum;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool modelIsFlipped(struct model *model)
|
|
{
|
|
if (model->anim) {
|
|
return model->anim->flip;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
f32 modelGetCurAnimFrame(struct model *model)
|
|
{
|
|
if (model->anim) {
|
|
return model->anim->frame;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
f32 modelGetAnimEndFrame(struct model *model)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
if (anim->endframe >= 0) {
|
|
return anim->endframe;
|
|
}
|
|
|
|
if (anim->animnum) {
|
|
return animGetNumFrames(anim->animnum) - 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
s32 modelGetNumAnimFrames(struct model *model)
|
|
{
|
|
if (model->anim) {
|
|
return animGetNumFrames(modelGetAnimNum(model));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
f32 modelGetAnimSpeed(struct model *model)
|
|
{
|
|
if (model->anim) {
|
|
return model->anim->speed;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
f32 modelGetAbsAnimSpeed(struct model *model)
|
|
{
|
|
f32 speed;
|
|
|
|
if (model->anim) {
|
|
speed = model->anim->speed;
|
|
|
|
if (speed < 0) {
|
|
speed = -speed;
|
|
}
|
|
|
|
return speed;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
f32 modelGetEffectiveAnimSpeed(struct model *model)
|
|
{
|
|
if (model->anim) {
|
|
return modelGetAnimSpeed(model) * model->anim->playspeed;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Constrain the given frame number to the bounds of the animation, unless the
|
|
* animation is looping in which case wrap it to the other side.
|
|
*/
|
|
s32 modelConstrainOrWrapAnimFrame(s32 frame, s16 animnum, f32 endframe)
|
|
{
|
|
if (frame < 0) {
|
|
if (var8005efbc || (g_Anims[animnum].flags & ANIMFLAG_LOOP)) {
|
|
frame = animGetNumFrames(animnum) - (-frame % animGetNumFrames(animnum));
|
|
} else {
|
|
frame = 0;
|
|
}
|
|
} else if (endframe >= 0 && frame > (s32)endframe) {
|
|
frame = ceil(endframe);
|
|
} else if (frame >= animGetNumFrames(animnum)) {
|
|
if (var8005efbc || (g_Anims[animnum].flags & ANIMFLAG_LOOP)) {
|
|
frame = frame % animGetNumFrames(animnum);
|
|
} else {
|
|
frame = animGetNumFrames(animnum) - 1;
|
|
}
|
|
}
|
|
|
|
return frame;
|
|
}
|
|
|
|
void modelCopyAnimForMerge(struct model *model, f32 merge)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
struct modelnode *node;
|
|
u32 nodetype;
|
|
|
|
if (anim) {
|
|
if (merge > 0 && anim->animnum) {
|
|
if (anim->animnum2 && anim->fracmerge == 1) {
|
|
return;
|
|
}
|
|
|
|
node = model->filedata->rootnode;
|
|
nodetype = node->type & 0xff;
|
|
|
|
anim->frame2 = anim->frame;
|
|
anim->frac2 = anim->frac;
|
|
anim->animnum2 = anim->animnum;
|
|
anim->flip2 = anim->flip;
|
|
anim->frame2a = anim->framea;
|
|
anim->frame2b = anim->frameb;
|
|
anim->speed2 = anim->speed;
|
|
anim->newspeed2 = anim->newspeed;
|
|
anim->oldspeed2 = anim->oldspeed;
|
|
anim->timespeed2 = anim->timespeed;
|
|
anim->elapsespeed2 = anim->elapsespeed;
|
|
anim->endframe2 = anim->endframe;
|
|
|
|
if (nodetype == MODELNODETYPE_CHRINFO) {
|
|
struct modelrwdata_chrinfo *rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->unk02 = 1;
|
|
rwdata->unk4c.x = rwdata->unk34.x;
|
|
rwdata->unk4c.y = rwdata->unk34.y;
|
|
rwdata->unk4c.z = rwdata->unk34.z;
|
|
rwdata->unk40.x = rwdata->unk24.x;
|
|
rwdata->unk40.y = rwdata->unk24.y;
|
|
rwdata->unk40.z = rwdata->unk24.z;
|
|
}
|
|
} else {
|
|
anim->animnum2 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001d62c(struct model *model, s16 animnum, s32 flip, f32 fstartframe, f32 speed, f32 merge)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
s32 isfirstanim = !anim->animnum;
|
|
s32 type;
|
|
|
|
if (anim->animnum2) {
|
|
anim->timemerge = merge;
|
|
anim->elapsemerge = 0;
|
|
anim->fracmerge = 1;
|
|
} else {
|
|
anim->timemerge = 0;
|
|
anim->fracmerge = 0;
|
|
}
|
|
|
|
anim->animnum = animnum;
|
|
anim->flip = flip;
|
|
anim->endframe = -1;
|
|
anim->speed = speed;
|
|
anim->timespeed = 0;
|
|
|
|
model0001e018(model, fstartframe);
|
|
|
|
anim->looping = false;
|
|
|
|
type = model->filedata->rootnode->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_CHRINFO) {
|
|
u32 stack;
|
|
struct modelrodata_chrinfo *rodata = &model->filedata->rootnode->rodata->chrinfo;
|
|
struct modelrwdata_chrinfo *rwdata = (struct modelrwdata_chrinfo *) modelGetNodeRwData(model, model->filedata->rootnode);
|
|
s32 spa4 = rodata->unk00;
|
|
struct skeleton *skel = model->filedata->skel;
|
|
f32 scale;
|
|
f32 sp98;
|
|
f32 sp94;
|
|
struct coord sp88 = {0, 0, 0};
|
|
f32 sp84;
|
|
u8 sp83;
|
|
struct coord sp74;
|
|
struct coord sp68;
|
|
f32 sp64;
|
|
struct coord sp58;
|
|
struct coord sp4c;
|
|
f32 angle;
|
|
f32 y;
|
|
f32 x;
|
|
f32 z;
|
|
|
|
if (g_Anims[anim->animnum].flags & ANIMFLAG_02) {
|
|
sp64 = func0f15c888();
|
|
anim00023d38(anim->animnum);
|
|
sp83 = anim00023ab0(anim->animnum, anim->framea);
|
|
anim00023d0c();
|
|
anim00024050(spa4, anim->flip, skel, anim->animnum, sp83, &sp74, &sp88, &sp68);
|
|
|
|
rwdata->unk34.x = sp88.x * sp64;
|
|
rwdata->unk34.y = sp88.y * sp64;
|
|
rwdata->unk34.z = sp88.z * sp64;
|
|
rwdata->unk30 = rwdata->unk14;
|
|
|
|
if (anim->frac == 0) {
|
|
rwdata->unk01 = 0;
|
|
} else {
|
|
anim00023d38(anim->animnum);
|
|
sp83 = anim00023ab0(anim->animnum, anim->frameb);
|
|
anim00023d0c();
|
|
anim00024050(spa4, anim->flip, skel, anim->animnum, sp83, &sp74, &sp88, &sp68);
|
|
|
|
rwdata->unk24.x = sp88.x * sp64;
|
|
rwdata->unk24.y = sp88.y * sp64;
|
|
rwdata->unk24.z = sp88.z * sp64;
|
|
rwdata->unk20 = rwdata->unk14;
|
|
|
|
rwdata->unk01 = 1;
|
|
}
|
|
} else {
|
|
sp84 = anim00024b64(spa4, anim->flip, skel, anim->animnum, anim->frameb, &sp88, anim->average);
|
|
scale = model->scale * anim->animscale;
|
|
|
|
if (scale != 1) {
|
|
sp88.x *= scale;
|
|
sp88.y *= scale;
|
|
sp88.z *= scale;
|
|
}
|
|
|
|
if (anim->average) {
|
|
sp88.y = rwdata->pos.y - rwdata->ground;
|
|
}
|
|
|
|
sp98 = cosf(rwdata->unk14);
|
|
sp94 = sinf(rwdata->unk14);
|
|
|
|
if (anim->frac == 0) {
|
|
rwdata->unk34.x = rwdata->pos.f[0];
|
|
rwdata->unk34.y = rwdata->pos.f[1] - rwdata->ground;
|
|
rwdata->unk34.z = rwdata->pos.f[2];
|
|
|
|
rwdata->unk30 = rwdata->unk14;
|
|
|
|
sp58.x = rwdata->unk34.f[0] + sp88.f[0] * sp98 + sp88.f[2] * sp94;
|
|
sp58.y = sp88.f[1];
|
|
sp58.z = rwdata->unk34.f[2] - sp88.f[0] * sp94 + sp88.f[2] * sp98;
|
|
|
|
rwdata->unk24.x = sp58.f[0];
|
|
rwdata->unk24.y = sp58.f[1];
|
|
rwdata->unk24.z = sp58.f[2];
|
|
|
|
if (rwdata->unk18 == 0) {
|
|
rwdata->unk20 = rwdata->unk30 + sp84;
|
|
|
|
if (rwdata->unk20 >= M_BADTAU) {
|
|
rwdata->unk20 -= M_BADTAU;
|
|
}
|
|
}
|
|
|
|
rwdata->unk01 = 1;
|
|
} else {
|
|
x = sp88.f[0] * sp98 + sp88.f[2] * sp94;
|
|
y = sp88.f[1];
|
|
z = -sp88.f[0] * sp94 + sp88.f[2] * sp98;
|
|
|
|
sp4c.f[0] = rwdata->pos.f[0] + x * (1 - anim->frac);
|
|
sp4c.f[1] = y;
|
|
sp4c.f[2] = rwdata->pos.f[2] + z * (1 - anim->frac);
|
|
|
|
rwdata->unk24.f[0] = sp4c.f[0];
|
|
rwdata->unk24.f[1] = sp4c.f[1];
|
|
rwdata->unk24.f[2] = sp4c.f[2];
|
|
|
|
rwdata->unk34.f[0] = rwdata->unk24.f[0] - x;
|
|
rwdata->unk34.f[1] = (rwdata->pos.f[1] - rwdata->ground) - (y - (rwdata->pos.f[1] - rwdata->ground)) * anim->frac / (1 - anim->frac);
|
|
rwdata->unk34.f[2] = rwdata->unk24.f[2] - z;
|
|
|
|
angle = rwdata->unk14 - sp84;
|
|
|
|
if (angle < 0) {
|
|
angle += M_BADTAU;
|
|
}
|
|
|
|
rwdata->unk30 = model0001afe8(rwdata->unk14, angle, anim->frac);
|
|
|
|
if (rwdata->unk18 == 0) {
|
|
rwdata->unk20 = rwdata->unk30 + sp84;
|
|
|
|
if (rwdata->unk20 >= M_BADTAU) {
|
|
rwdata->unk20 -= M_BADTAU;
|
|
}
|
|
}
|
|
|
|
rwdata->unk01 = 1;
|
|
}
|
|
|
|
if (isfirstanim) {
|
|
rwdata->unk34.f[1] = rwdata->unk24.f[1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool modelIsAnimMerging(struct model *model)
|
|
{
|
|
if (model && model->anim && model->anim->animnum2
|
|
&& model->anim->fracmerge != 0 && model->anim->fracmerge != 1) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void modelSetAnimationWithMerge(struct model *model, s16 animnum, u32 flip, f32 startframe, f32 speed, f32 timemerge, bool domerge)
|
|
{
|
|
if (model) {
|
|
if (model->anim && model->anim->animnum
|
|
&& (g_Anims[model->anim->animnum].flags & ANIMFLAG_02)
|
|
&& (g_Anims[animnum].flags & ANIMFLAG_02) == 0) {
|
|
timemerge = 0;
|
|
}
|
|
|
|
if (domerge) {
|
|
modelCopyAnimForMerge(model, timemerge);
|
|
}
|
|
|
|
model0001d62c(model, animnum, flip, startframe, speed, timemerge);
|
|
}
|
|
}
|
|
|
|
void modelSetAnimation(struct model *model, s16 animnum, s32 flip, f32 startframe, f32 speed, f32 merge)
|
|
{
|
|
if (model) {
|
|
if (model->anim && model->anim->animnum
|
|
&& (g_Anims[model->anim->animnum].flags & ANIMFLAG_02)
|
|
&& (g_Anims[animnum].flags & ANIMFLAG_02) == 0) {
|
|
merge = 0;
|
|
}
|
|
|
|
modelCopyAnimForMerge(model, merge);
|
|
model0001d62c(model, animnum, flip, startframe, speed, merge);
|
|
}
|
|
}
|
|
|
|
void modelCopyAnimData(struct model *src, struct model *dst)
|
|
{
|
|
if (src->anim && dst->anim) {
|
|
*dst->anim = *src->anim;
|
|
}
|
|
}
|
|
|
|
void modelSetAnimLooping(struct model *model, f32 loopframe, f32 loopmerge)
|
|
{
|
|
if (model->anim) {
|
|
model->anim->looping = true;
|
|
model->anim->loopframe = loopframe;
|
|
model->anim->loopmerge = loopmerge;
|
|
}
|
|
}
|
|
|
|
void modelSetAnimEndFrame(struct model *model, f32 endframe)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
if (anim->animnum && endframe < animGetNumFrames(anim->animnum) - 1) {
|
|
anim->endframe = endframe;
|
|
} else {
|
|
anim->endframe = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void modelSetAnimFlipFunction(struct model *model, void *callback)
|
|
{
|
|
if (model->anim) {
|
|
model->anim->flipfunc = callback;
|
|
}
|
|
}
|
|
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
void modelSetAnimUnk6c(struct model *model, s32 value)
|
|
{
|
|
if (model->anim) {
|
|
model->anim->unk6c = value;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void modelSetAnimSpeed(struct model *model, f32 speed, f32 startframe)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
if (startframe > 0) {
|
|
anim->timespeed = startframe;
|
|
anim->newspeed = speed;
|
|
anim->elapsespeed = 0;
|
|
anim->oldspeed = anim->speed;
|
|
} else {
|
|
anim->speed = speed;
|
|
anim->timespeed = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void modelSetAnimSpeedAuto(struct model *model, f32 arg1, f32 startframe)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
f32 tmp;
|
|
f32 speed;
|
|
|
|
if (anim) {
|
|
if (anim->frame <= arg1) {
|
|
tmp = arg1 - anim->frame;
|
|
} else {
|
|
tmp = animGetNumFrames(anim->animnum) - anim->frame + arg1;
|
|
}
|
|
|
|
speed = anim->speed + (tmp + tmp) / startframe;
|
|
|
|
modelSetAnimSpeed(model, speed, startframe);
|
|
}
|
|
}
|
|
|
|
void modelSetAnimPlaySpeed(struct model *model, f32 speed, f32 startframe)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
if (startframe > 0) {
|
|
anim->timeplay = startframe;
|
|
anim->newplay = speed;
|
|
anim->elapseplay = 0;
|
|
anim->oldplay = anim->playspeed;
|
|
} else {
|
|
anim->playspeed = speed;
|
|
anim->timeplay = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void modelSetAnim70(struct model *model, void *callback)
|
|
{
|
|
if (model->anim) {
|
|
model->anim->unk70 = callback;
|
|
}
|
|
}
|
|
|
|
void model0001e018(struct model *model, f32 arg1)
|
|
{
|
|
s32 sp28;
|
|
s32 sp24;
|
|
bool sp20;
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
sp28 = floor(arg1);
|
|
sp20 = anim->speed >= 0;
|
|
|
|
sp24 = (sp20 ? sp28 + 1 : sp28 - 1);
|
|
|
|
anim->framea = modelConstrainOrWrapAnimFrame(sp28, anim->animnum, anim->endframe);
|
|
anim->frameb = modelConstrainOrWrapAnimFrame(sp24, anim->animnum, anim->endframe);
|
|
|
|
if (anim->framea == anim->frameb) {
|
|
anim->frac = 0;
|
|
anim->frame = anim->framea;
|
|
} else if (sp20) {
|
|
anim->frac = arg1 - sp28;
|
|
anim->frame = anim->framea + anim->frac;
|
|
} else {
|
|
anim->frac = 1 - (arg1 - sp24);
|
|
anim->frame = anim->frameb + (1 - anim->frac);
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001e14c(struct model *model, f32 arg1, f32 arg2)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim) {
|
|
model0001e018(model, arg1);
|
|
|
|
if (anim->animnum2) {
|
|
s32 sp28 = floor(arg2);
|
|
s32 sp24;
|
|
bool sp20 = anim->speed2 >= 0;
|
|
|
|
sp24 = (sp20 ? sp28 + 1 : sp28 - 1);
|
|
|
|
anim->frame2a = modelConstrainOrWrapAnimFrame(sp28, anim->animnum2, anim->endframe2);
|
|
anim->frame2b = modelConstrainOrWrapAnimFrame(sp24, anim->animnum2, anim->endframe2);
|
|
|
|
if (anim->frame2a == anim->frame2b) {
|
|
anim->frac2 = 0;
|
|
anim->frame2 = anim->frame2a;
|
|
} else if (sp20) {
|
|
anim->frac2 = arg2 - sp28;
|
|
anim->frame2 = anim->frame2a + anim->frac2;
|
|
} else {
|
|
anim->frac2 = 1 - (arg2 - sp24);
|
|
anim->frame2 = anim->frame2b + (1 - anim->frac2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool var8005efdc = true;
|
|
|
|
void model0001e29c(bool value)
|
|
{
|
|
var8005efdc = value;
|
|
}
|
|
|
|
bool model0001e2a8(void)
|
|
{
|
|
return var8005efdc;
|
|
}
|
|
|
|
void model0001e2b4(struct model *model, f32 curframe, f32 endframe, f32 curframe2, f32 endframe2)
|
|
{
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim != NULL) {
|
|
struct modelnode *rootnode = model->filedata->rootnode;
|
|
u16 nodetype = rootnode->type;
|
|
|
|
if ((nodetype & 0xff) == MODELNODETYPE_CHRINFO) {
|
|
struct modelrodata_chrinfo *rodata = &rootnode->rodata->chrinfo;
|
|
struct modelrwdata_chrinfo *rwdata = modelGetNodeRwData(model, rootnode);
|
|
|
|
if (rwdata->unk00 == 0) {
|
|
s32 sp118 = rodata->unk00;
|
|
struct skeleton *skel = model->filedata->skel;
|
|
f32 scale = model->scale * anim->animscale;
|
|
f32 sine;
|
|
f32 cosine;
|
|
struct coord spfc = {0, 0, 0};
|
|
u8 s0;
|
|
f32 f20;
|
|
s32 floorcur;
|
|
s32 floorend;
|
|
struct coord spe0;
|
|
f32 f30;
|
|
struct coord spd0;
|
|
f32 spcc;
|
|
s32 spc8;
|
|
bool forwards;
|
|
f32 absspeed;
|
|
f32 absspeed2;
|
|
f32 f22;
|
|
s32 s0frame;
|
|
struct coord spa8;
|
|
struct coord sp9c;
|
|
struct coord sp90;
|
|
u32 stack;
|
|
|
|
spe0.x = rwdata->unk34.x;
|
|
spe0.y = rwdata->unk34.y;
|
|
spe0.z = rwdata->unk34.z;
|
|
|
|
f30 = rwdata->unk30;
|
|
|
|
spd0.x = rwdata->unk24.x;
|
|
spd0.y = rwdata->unk24.y;
|
|
spd0.z = rwdata->unk24.z;
|
|
|
|
spcc = rwdata->unk20;
|
|
spc8 = rwdata->unk01;
|
|
|
|
absspeed = anim->speed;
|
|
|
|
if (absspeed < 0.0f) {
|
|
absspeed = -absspeed;
|
|
}
|
|
|
|
absspeed2 = anim->speed2;
|
|
|
|
if (absspeed2 < 0.0f) {
|
|
absspeed2 = -absspeed2;
|
|
}
|
|
|
|
forwards = false;
|
|
|
|
if (curframe <= endframe) {
|
|
forwards = true;
|
|
}
|
|
|
|
if (forwards) {
|
|
floorcur = floor(curframe) + 1;
|
|
floorend = floor(endframe);
|
|
} else {
|
|
floorcur = ceil(curframe) - 1;
|
|
floorend = ceil(endframe);
|
|
}
|
|
|
|
if (g_Anims[anim->animnum].flags & ANIMFLAG_02) {
|
|
f20 = func0f15c888();
|
|
|
|
if (floorend != anim->framea) {
|
|
s0frame = modelConstrainOrWrapAnimFrame(floorend, anim->animnum, anim->endframe);
|
|
|
|
anim->framea = s0frame;
|
|
|
|
if (spc8 && floorend == anim->frameb) {
|
|
spe0.x = spd0.x;
|
|
spe0.y = spd0.y;
|
|
spe0.z = spd0.z;
|
|
} else {
|
|
anim00023d38(anim->animnum);
|
|
s0 = anim00023ab0(anim->animnum, s0frame);
|
|
anim00023d0c();
|
|
anim00024050(sp118, anim->flip, skel, anim->animnum, s0, &spa8, &spfc, &sp9c);
|
|
|
|
spe0.x = spfc.x * f20;
|
|
spe0.y = spfc.y * f20;
|
|
spe0.z = spfc.z * f20;
|
|
}
|
|
|
|
floorcur = floorend;
|
|
|
|
if (forwards) {
|
|
floorcur++;
|
|
} else {
|
|
floorcur--;
|
|
}
|
|
|
|
s0frame = modelConstrainOrWrapAnimFrame(floorcur, anim->animnum, anim->endframe);
|
|
anim->frameb = s0frame;
|
|
|
|
anim00023d38(anim->animnum);
|
|
s0 = anim00023ab0(anim->animnum, s0frame);
|
|
|
|
anim00023d0c();
|
|
anim00024050(sp118, anim->flip, skel, anim->animnum, s0, &spa8, &spfc, &sp9c);
|
|
|
|
spc8 = true;
|
|
|
|
spd0.x = spfc.x * f20;
|
|
spd0.y = spfc.y * f20;
|
|
spd0.z = spfc.z * f20;
|
|
}
|
|
} else {
|
|
while (true) {
|
|
if (forwards) {
|
|
if (floorend < floorcur) {
|
|
break;
|
|
}
|
|
} else {
|
|
if (floorend > floorcur) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
s0frame = modelConstrainOrWrapAnimFrame(floorcur, anim->animnum, anim->endframe);
|
|
|
|
anim->framea = s0frame;
|
|
|
|
if (spc8) {
|
|
spe0.x = spd0.x;
|
|
spe0.y = spd0.y;
|
|
spe0.z = spd0.z;
|
|
|
|
if (rwdata->unk18 == 0.0f) {
|
|
f30 = spcc;
|
|
}
|
|
} else {
|
|
f22 = anim00024b64(sp118, anim->flip, skel, anim->animnum, s0frame, &spfc, anim->average);
|
|
|
|
if (scale != 1.0f) {
|
|
spfc.x *= scale;
|
|
spfc.y *= scale;
|
|
spfc.z *= scale;
|
|
}
|
|
|
|
if (!forwards) {
|
|
spfc.x = -spfc.x;
|
|
spfc.z = -spfc.z;
|
|
|
|
if (f22 > 0.0f) {
|
|
f22 = M_BADTAU - f22;
|
|
}
|
|
}
|
|
|
|
if (anim->average) {
|
|
spfc.y = rwdata->pos.y - rwdata->ground;
|
|
}
|
|
|
|
cosine = cosf(rwdata->unk14);
|
|
sine = sinf(rwdata->unk14);
|
|
|
|
spe0.x += spfc.x * cosine + spfc.z * sine;
|
|
spe0.y = spfc.y;
|
|
spe0.z += (-spfc.x * sine) + (spfc.z * cosine);
|
|
|
|
if (rwdata->unk18 == 0.0f) {
|
|
f30 += f22;
|
|
|
|
if (f30 >= M_BADTAU) {
|
|
f30 -= M_BADTAU;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (forwards) {
|
|
floorcur++;
|
|
} else {
|
|
floorcur--;
|
|
}
|
|
|
|
s0frame = modelConstrainOrWrapAnimFrame(floorcur, anim->animnum, anim->endframe);
|
|
anim->frameb = s0frame;
|
|
|
|
if (anim->frameb != anim->framea) {
|
|
f22 = anim00024b64(sp118, anim->flip, skel, anim->animnum, s0frame, &spfc, anim->average);
|
|
|
|
spc8 = true;
|
|
|
|
if (scale != 1.0f) {
|
|
spfc.x *= scale;
|
|
spfc.y *= scale;
|
|
spfc.z *= scale;
|
|
}
|
|
|
|
if (!forwards) {
|
|
spfc.x = -spfc.x;
|
|
spfc.z = -spfc.z;
|
|
|
|
if (f22 > 0.0f) {
|
|
f22 = M_BADTAU - f22;
|
|
}
|
|
}
|
|
|
|
if (anim->average) {
|
|
spfc.y = rwdata->unk34.y;
|
|
}
|
|
|
|
cosine = cosf(rwdata->unk30);
|
|
sine = sinf(rwdata->unk30);
|
|
|
|
if (var8005efdc && anim->animnum2) {
|
|
spd0.x = spfc.x * cosine + spfc.f[2] * sine;
|
|
spd0.z = -spfc.x * sine + spfc.f[2] * cosine;
|
|
|
|
if (absspeed > 0.0f) {
|
|
f32 f0 = anim->fracmerge - anim->playspeed / (absspeed * anim->timemerge);
|
|
|
|
if (f0 < 0.0f) {
|
|
f0 = 0.0f;
|
|
}
|
|
|
|
f0 = (f0 + anim->fracmerge) / 2.0f;
|
|
|
|
if (1);
|
|
|
|
sp90.f[0] = (rwdata->unk40.x - rwdata->unk4c.x) * absspeed2 / absspeed;
|
|
sp90.f[2] = (rwdata->unk40.z - rwdata->unk4c.z) * absspeed2 / absspeed;
|
|
spd0.x += (sp90.x - spd0.x) * f0;
|
|
spd0.z += (sp90.z - spd0.z) * f0;
|
|
} else {
|
|
spd0.x += (rwdata->unk40.x - rwdata->unk4c.x) * anim->fracmerge;
|
|
spd0.z += (rwdata->unk40.z - rwdata->unk4c.z) * anim->fracmerge;
|
|
}
|
|
|
|
spd0.x += spe0.x;
|
|
spd0.z += spe0.z;
|
|
spd0.y = spfc.y;
|
|
} else {
|
|
spd0.x = spe0.x + spfc.x * cosine + spfc.f[2] * sine;
|
|
spd0.y = spfc.y;
|
|
spd0.z = spe0.z - spfc.x * sine + spfc.f[2] * cosine;
|
|
}
|
|
|
|
if (rwdata->unk5c > 0.0f && absspeed > 0.0f) {
|
|
f32 increment = 1.0f / absspeed;
|
|
|
|
if (increment > rwdata->unk5c) {
|
|
increment = rwdata->unk5c;
|
|
rwdata->unk5c = 0.0f;
|
|
} else {
|
|
rwdata->unk5c -= increment;
|
|
}
|
|
|
|
f22 += rwdata->unk58 * increment;
|
|
|
|
if (f22 < 0.0f) {
|
|
f22 += M_BADTAU;
|
|
} else if (f22 >= M_BADTAU) {
|
|
f22 -= M_BADTAU;
|
|
}
|
|
}
|
|
|
|
if (rwdata->unk18 == 0.0f) {
|
|
spcc = f30 + f22;
|
|
|
|
if (spcc >= M_BADTAU) {
|
|
spcc -= M_BADTAU;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
rwdata->unk34.x = spe0.x;
|
|
rwdata->unk34.y = spe0.y;
|
|
rwdata->unk34.z = spe0.z;
|
|
|
|
rwdata->unk30 = f30;
|
|
|
|
rwdata->unk24.x = spd0.f[0];
|
|
rwdata->unk24.y = spd0.f[1];
|
|
rwdata->unk24.z = spd0.f[2];
|
|
|
|
rwdata->unk20 = spcc;
|
|
rwdata->unk01 = spc8;
|
|
|
|
if (anim->framea == anim->frameb) {
|
|
anim->frac = 0.0f;
|
|
anim->frame = anim->framea;
|
|
} else if (forwards) {
|
|
anim->frac = endframe - floorend;
|
|
anim->frame = anim->framea + anim->frac;
|
|
} else {
|
|
anim->frac = floorend - endframe;
|
|
anim->frame = anim->frameb + (1.0f - anim->frac);
|
|
}
|
|
|
|
if (anim->animnum2 && (g_Anims[anim->animnum].flags & ANIMFLAG_02) == 0) {
|
|
s32 floorcur2 = floor(curframe2);
|
|
s32 floorend2 = floor(endframe2);
|
|
|
|
if ((forwards && floorcur2 < floorend2) || (!forwards && floorend2 < floorcur2)) {
|
|
if (rwdata->unk02 != 0) {
|
|
rwdata->unk4c.f[1] = rwdata->unk40.f[1];
|
|
} else {
|
|
rwdata->unk4c.f[1] = rwdata->unk34.f[1];
|
|
}
|
|
|
|
anim->frame2a = modelConstrainOrWrapAnimFrame(floorend2, anim->animnum2, anim->endframe2);
|
|
|
|
s0frame = modelConstrainOrWrapAnimFrame(floorend2 + 1, anim->animnum2, anim->endframe2);
|
|
anim->frame2b = s0frame;
|
|
|
|
anim00024b64(sp118, anim->flip2, skel, anim->animnum2, s0frame, &spfc, anim->average);
|
|
|
|
if (scale != 1.0f) {
|
|
spfc.y *= scale;
|
|
}
|
|
|
|
if (anim->average) {
|
|
spfc.y = rwdata->unk4c.y;
|
|
}
|
|
|
|
rwdata->unk40.y = spfc.y;
|
|
rwdata->unk02 = 1;
|
|
}
|
|
|
|
if (forwards) {
|
|
anim->frac2 = endframe2 - floorend2;
|
|
anim->frame2 = anim->frame2a + anim->frac2;
|
|
} else {
|
|
anim->frac2 = 1.0f - (endframe2 - floorend2);
|
|
anim->frame2 = anim->frame2b + (1.0f - anim->frac2);
|
|
}
|
|
} else {
|
|
rwdata->unk02 = 0;
|
|
}
|
|
} else {
|
|
model0001e14c(model, endframe, endframe2);
|
|
}
|
|
} else {
|
|
model0001e14c(model, endframe, endframe2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void model0001ee18(struct model *model, s32 lvupdate240, bool arg2)
|
|
{
|
|
f32 frame;
|
|
f32 frame2;
|
|
f32 speed;
|
|
f32 speed2;
|
|
f32 startframe;
|
|
f32 endframe;
|
|
f32 realendframe;
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim && lvupdate240 > 0) {
|
|
frame = anim->frame;
|
|
frame2 = anim->frame2;
|
|
|
|
for (; lvupdate240 > 0; lvupdate240--) {
|
|
if (anim->timeplay > 0) {
|
|
anim->elapseplay += 0.25f;
|
|
|
|
if (anim->elapseplay < anim->timeplay) {
|
|
anim->playspeed = anim->oldplay + (anim->newplay - anim->oldplay) * anim->elapseplay / anim->timeplay;
|
|
} else {
|
|
anim->timeplay = 0;
|
|
anim->playspeed = anim->newplay;
|
|
}
|
|
}
|
|
|
|
if (anim->timemerge > 0) {
|
|
anim->elapsemerge += anim->playspeed * 0.25f;
|
|
|
|
if (anim->elapsemerge == 0) {
|
|
anim->fracmerge = 1;
|
|
} else {
|
|
if (anim->elapsemerge < anim->timemerge) {
|
|
anim->fracmerge = (anim->timemerge - anim->elapsemerge) / anim->timemerge;
|
|
} else {
|
|
anim->timemerge = 0;
|
|
anim->fracmerge = 0;
|
|
anim->animnum2 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (anim->timespeed > 0) {
|
|
anim->elapsespeed += anim->playspeed * 0.25f;
|
|
|
|
if (anim->elapsespeed < anim->timespeed) {
|
|
anim->speed = anim->oldspeed + (anim->newspeed - anim->oldspeed) * anim->elapsespeed / anim->timespeed;
|
|
} else {
|
|
anim->timespeed = 0;
|
|
anim->speed = anim->newspeed;
|
|
}
|
|
}
|
|
|
|
speed = anim->speed;
|
|
frame += anim->playspeed * speed * 0.25f;
|
|
|
|
if (anim->animnum2) {
|
|
if (anim->timespeed2 > 0) {
|
|
anim->elapsespeed2 += anim->playspeed * 0.25f;
|
|
|
|
if (anim->elapsespeed2 < anim->timespeed2) {
|
|
anim->speed2 = anim->oldspeed2 + (anim->newspeed2 - anim->oldspeed2) * anim->elapsespeed2 / anim->timespeed2;
|
|
} else {
|
|
anim->timespeed2 = 0;
|
|
anim->speed2 = anim->newspeed2;
|
|
}
|
|
}
|
|
|
|
speed2 = anim->speed2;
|
|
frame2 += anim->playspeed * speed2 * 0.25f;
|
|
}
|
|
|
|
if (anim->looping) {
|
|
realendframe = anim->endframe;
|
|
|
|
if (speed >= 0) {
|
|
endframe = animGetNumFrames(anim->animnum) - 1;
|
|
startframe = anim->loopframe;
|
|
|
|
if (realendframe >= 0 && endframe > realendframe) {
|
|
endframe = realendframe;
|
|
}
|
|
} else {
|
|
endframe = anim->loopframe;
|
|
startframe = animGetNumFrames(anim->animnum) - 1;
|
|
|
|
if (realendframe >= 0 && startframe > realendframe) {
|
|
startframe = realendframe;
|
|
}
|
|
}
|
|
|
|
if ((speed >= 0 && frame >= endframe) || (speed < 0 && frame <= endframe)) {
|
|
f32 prevnewspeed = anim->newspeed;
|
|
f32 prevoldspeed = anim->oldspeed;
|
|
f32 prevtimespeed = anim->timespeed;
|
|
f32 prevelapsespeed = anim->elapsespeed;
|
|
|
|
if (arg2) {
|
|
model0001e2b4(model, anim->frame, endframe, 0, 0);
|
|
} else {
|
|
model0001e14c(model, endframe, 0);
|
|
}
|
|
|
|
modelSetAnimation(model, anim->animnum, anim->flip, startframe, anim->speed, anim->loopmerge);
|
|
|
|
anim->looping = true;
|
|
anim->endframe = realendframe;
|
|
|
|
anim->newspeed = prevnewspeed;
|
|
anim->oldspeed = prevoldspeed;
|
|
anim->timespeed = prevtimespeed;
|
|
anim->elapsespeed = prevelapsespeed;
|
|
|
|
frame2 = frame;
|
|
frame = startframe + frame - endframe;
|
|
|
|
if (anim->flipfunc) {
|
|
anim->flipfunc();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (arg2) {
|
|
if (anim->animnum2) {
|
|
model0001e2b4(model, anim->frame, frame, anim->frame2, frame2);
|
|
} else {
|
|
model0001e2b4(model, anim->frame, frame, 0, 0);
|
|
}
|
|
} else {
|
|
if (anim->animnum2) {
|
|
model0001e14c(model, frame, frame2);
|
|
} else {
|
|
model0001e14c(model, frame, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if VERSION < VERSION_PAL_BETA
|
|
/**
|
|
* This is identical to the above function but removes the 0.25f multipliers.
|
|
*/
|
|
void model0001f314(struct model *model, s32 lvupdate240, bool arg2)
|
|
{
|
|
f32 frame;
|
|
f32 frame2;
|
|
f32 speed;
|
|
f32 speed2;
|
|
f32 startframe;
|
|
f32 endframe;
|
|
f32 realendframe;
|
|
struct anim *anim = model->anim;
|
|
|
|
if (anim && lvupdate240 > 0) {
|
|
frame = anim->frame;
|
|
frame2 = anim->frame2;
|
|
|
|
for (; lvupdate240 > 0; lvupdate240--) {
|
|
if (anim->timeplay > 0) {
|
|
anim->elapseplay++;
|
|
|
|
if (anim->elapseplay < anim->timeplay) {
|
|
anim->playspeed = anim->oldplay + (anim->newplay - anim->oldplay) * anim->elapseplay / anim->timeplay;
|
|
} else {
|
|
anim->timeplay = 0;
|
|
anim->playspeed = anim->newplay;
|
|
}
|
|
}
|
|
|
|
if (anim->timemerge > 0) {
|
|
anim->elapsemerge += anim->playspeed;
|
|
|
|
if (anim->elapsemerge == 0) {
|
|
anim->fracmerge = 1;
|
|
} else {
|
|
if (anim->elapsemerge < anim->timemerge) {
|
|
anim->fracmerge = (anim->timemerge - anim->elapsemerge) / anim->timemerge;
|
|
} else {
|
|
anim->timemerge = 0;
|
|
anim->fracmerge = 0;
|
|
anim->animnum2 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (anim->timespeed > 0) {
|
|
anim->elapsespeed += anim->playspeed;
|
|
|
|
if (anim->elapsespeed < anim->timespeed) {
|
|
anim->speed = anim->oldspeed + (anim->newspeed - anim->oldspeed) * anim->elapsespeed / anim->timespeed;
|
|
} else {
|
|
anim->timespeed = 0;
|
|
anim->speed = anim->newspeed;
|
|
}
|
|
}
|
|
|
|
speed = anim->speed;
|
|
frame += anim->playspeed * speed;
|
|
|
|
if (anim->animnum2) {
|
|
if (anim->timespeed2 > 0) {
|
|
anim->elapsespeed2 += anim->playspeed;
|
|
|
|
if (anim->elapsespeed2 < anim->timespeed2) {
|
|
anim->speed2 = anim->oldspeed2 + (anim->newspeed2 - anim->oldspeed2) * anim->elapsespeed2 / anim->timespeed2;
|
|
} else {
|
|
anim->timespeed2 = 0;
|
|
anim->speed2 = anim->newspeed2;
|
|
}
|
|
}
|
|
|
|
speed2 = anim->speed2;
|
|
frame2 += anim->playspeed * speed2;
|
|
}
|
|
|
|
if (anim->looping) {
|
|
realendframe = anim->endframe;
|
|
|
|
if (speed >= 0) {
|
|
endframe = animGetNumFrames(anim->animnum) - 1;
|
|
startframe = anim->loopframe;
|
|
|
|
if (realendframe >= 0 && endframe > realendframe) {
|
|
endframe = realendframe;
|
|
}
|
|
} else {
|
|
endframe = anim->loopframe;
|
|
startframe = animGetNumFrames(anim->animnum) - 1;
|
|
|
|
if (realendframe >= 0 && startframe > realendframe) {
|
|
startframe = realendframe;
|
|
}
|
|
}
|
|
|
|
if ((speed >= 0 && frame >= endframe) || (speed < 0 && frame <= endframe)) {
|
|
f32 prevnewspeed = anim->newspeed;
|
|
f32 prevoldspeed = anim->oldspeed;
|
|
f32 prevtimespeed = anim->timespeed;
|
|
f32 prevelapsespeed = anim->elapsespeed;
|
|
|
|
if (arg2) {
|
|
model0001e2b4(model, anim->frame, endframe, 0, 0);
|
|
} else {
|
|
model0001e14c(model, endframe, 0);
|
|
}
|
|
|
|
modelSetAnimation(model, anim->animnum, anim->flip, startframe, anim->speed, anim->loopmerge);
|
|
|
|
anim->looping = true;
|
|
anim->endframe = realendframe;
|
|
|
|
anim->newspeed = prevnewspeed;
|
|
anim->oldspeed = prevoldspeed;
|
|
anim->timespeed = prevtimespeed;
|
|
anim->elapsespeed = prevelapsespeed;
|
|
|
|
frame2 = frame;
|
|
frame = startframe + frame - endframe;
|
|
|
|
if (anim->flipfunc) {
|
|
anim->flipfunc();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (arg2) {
|
|
if (anim->animnum2) {
|
|
model0001e2b4(model, anim->frame, frame, anim->frame2, frame2);
|
|
} else {
|
|
model0001e2b4(model, anim->frame, frame, 0, 0);
|
|
}
|
|
} else {
|
|
if (anim->animnum2) {
|
|
model0001e14c(model, frame, frame2);
|
|
} else {
|
|
model0001e14c(model, frame, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void model0001f7e0(struct modelrenderdata *renderdata)
|
|
{
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_1CYCLE);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
|
|
}
|
|
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_MODULATEIA, G_CC_MODULATEIA);
|
|
}
|
|
|
|
void model0001f890(struct modelrenderdata *renderdata, bool arg1)
|
|
{
|
|
if (renderdata->unk30 == 7) {
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, renderdata->envcolour | 0xff);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL0, ENVIRONMENT, SHADE_ALPHA, ENVIRONMENT, TEXEL0, ENVIRONMENT, SHADE, ENVIRONMENT, COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 8) {
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, renderdata->envcolour);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL0, ENVIRONMENT, SHADE_ALPHA, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 9) {
|
|
if ((renderdata->envcolour & 0xff) == 0) {
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, 0xffffffff);
|
|
gDPSetPrimColor(renderdata->gdl++, 0, 0, 0, 0, 0, (renderdata->envcolour >> 8) & 0xff);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, PRIMITIVE);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else {
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColor(renderdata->gdl++, 0, 0, 0, renderdata->envcolour);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, 1, 0, SHADE, ENVIRONMENT, COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_TEX_EDGE2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_TEX_EDGE2);
|
|
}
|
|
} else {
|
|
gDPSetPrimColor(renderdata->gdl++, 0, 0, 0, 0, 0, (renderdata->envcolour >> 8) & 0xff);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, SHADE, ENVIRONMENT, TEXEL0, 0, COMBINED, 0, SHADE, 0, 1, 0, PRIMITIVE, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_TEX_EDGE2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_TEX_EDGE2);
|
|
}
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 4) {
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->envcolour);
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 5) {
|
|
u8 alpha;
|
|
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
|
|
alpha = renderdata->envcolour & 0xff;
|
|
|
|
if (alpha < 255) {
|
|
gDPSetEnvColor(renderdata->gdl++, 0xff, 0xff, 0xff, alpha);
|
|
|
|
if (renderdata->envcolour & 0xff00) {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, 1, SHADE, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0);
|
|
} else {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, 1, 0, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0);
|
|
}
|
|
} else {
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
}
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
} else {
|
|
alpha = renderdata->envcolour & 0xff;
|
|
|
|
if (alpha < 255) {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL0, 0, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0);
|
|
} else {
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
}
|
|
}
|
|
} else {
|
|
if (arg1) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_PASS, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_PASS, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_PASS, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_PASS, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model00020248(struct modelrenderdata *renderdata, bool arg1)
|
|
{
|
|
if (renderdata->unk30 == 7) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, renderdata->envcolour | 0x000000ff);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL0, ENVIRONMENT, SHADE_ALPHA, ENVIRONMENT, TEXEL0, ENVIRONMENT, SHADE, ENVIRONMENT, COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED);
|
|
|
|
if (arg1) {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 8) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, renderdata->envcolour);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL0, ENVIRONMENT, SHADE_ALPHA, ENVIRONMENT, TEXEL0, 0, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
} else if (renderdata->unk30 == 9) {
|
|
if ((renderdata->envcolour & 0xff) == 0) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, 0xffffffff);
|
|
gDPSetPrimColor(renderdata->gdl++, 0, 0, 0, 0, 0, (renderdata->envcolour >> 8) & 0xff);
|
|
|
|
if (arg1) {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, PRIMITIVE);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, PRIMITIVE);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
gDPSetEnvColorViaWord(renderdata->gdl++, renderdata->envcolour & 0xff);
|
|
|
|
if (arg1) {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, 1, 0, SHADE, ENVIRONMENT, COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_TEX_EDGE2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_TEX_EDGE2);
|
|
}
|
|
} else {
|
|
gDPSetPrimColor(renderdata->gdl++, 0, 0, 0, 0, 0, (renderdata->envcolour >> 8) & 0xff);
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, SHADE, ENVIRONMENT, TEXEL0, 0, COMBINED, 0, SHADE, 0, 1, 0, PRIMITIVE, COMBINED);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_TEX_EDGE2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_TEX_EDGE2);
|
|
}
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 4) {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->envcolour);
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
|
|
if (arg1) {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
} else if (renderdata->unk30 == 5) {
|
|
u8 alpha;
|
|
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, renderdata->fogcolour);
|
|
|
|
alpha = renderdata->envcolour & 0xff;
|
|
|
|
if (alpha < 255) {
|
|
gDPSetEnvColor(renderdata->gdl++, 0xff, 0xff, 0xff, alpha);
|
|
|
|
if (arg1) {
|
|
if (renderdata->envcolour & 0xff00) {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, 1, SHADE, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0);
|
|
} else {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, 1, 0, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0);
|
|
}
|
|
} else {
|
|
gDPSetCombineLERP(renderdata->gdl++, TEXEL1, TEXEL0, LOD_FRACTION, TEXEL0, TEXEL0, 0, ENVIRONMENT, 0, COMBINED, 0, SHADE, 0, COMBINED, 0, SHADE, 0);
|
|
}
|
|
} else {
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
}
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
} else {
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
gDPSetFogColorViaWord(renderdata->gdl++, 0xffffff00);
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
|
|
if (arg1) {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_OPA_SURF2);
|
|
}
|
|
} else {
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_ZB_XLU_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_FOG_PRIM_A, G_RM_AA_XLU_SURF2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model00020bdc(struct modelrenderdata *renderdata)
|
|
{
|
|
gDPPipeSync(renderdata->gdl++);
|
|
gDPSetCycleType(renderdata->gdl++, G_CYC_2CYCLE);
|
|
|
|
if (renderdata->zbufferenabled) {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_PASS, G_RM_AA_ZB_OPA_SURF2);
|
|
} else {
|
|
gDPSetRenderMode(renderdata->gdl++, G_RM_PASS, G_RM_AA_OPA_SURF2);
|
|
}
|
|
|
|
gDPSetCombineMode(renderdata->gdl++, G_CC_TRILERP, G_CC_MODULATEIA2);
|
|
}
|
|
|
|
void modelApplyCullMode(struct modelrenderdata *renderdata)
|
|
{
|
|
if (renderdata->cullmode == CULLMODE_NONE) {
|
|
gSPClearGeometryMode(renderdata->gdl++, G_CULL_BOTH);
|
|
} else if (renderdata->cullmode == CULLMODE_FRONT) {
|
|
gSPSetGeometryMode(renderdata->gdl++, G_CULL_FRONT);
|
|
} else if (renderdata->cullmode == CULLMODE_BACK) {
|
|
gSPSetGeometryMode(renderdata->gdl++, G_CULL_BACK);
|
|
}
|
|
}
|
|
|
|
void modelRenderNodeGundl(struct modelrenderdata *renderdata, struct model *model, struct modelnode *node)
|
|
{
|
|
struct modelrodata_gundl *rodata = &node->rodata->gundl;
|
|
|
|
if (var8005efc4 && !var8005efc4(model, node)) {
|
|
return;
|
|
}
|
|
|
|
if ((renderdata->flags & 1) && rodata->primary) {
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL1, osVirtualToPhysical(rodata->baseaddr));
|
|
|
|
if (renderdata->cullmode) {
|
|
modelApplyCullMode(renderdata);
|
|
}
|
|
|
|
switch (rodata->unk12) {
|
|
case 1:
|
|
model0001f7e0(renderdata);
|
|
break;
|
|
case 3:
|
|
model0001f890(renderdata, true);
|
|
break;
|
|
case 4:
|
|
model00020248(renderdata, true);
|
|
break;
|
|
case 2:
|
|
model00020bdc(renderdata);
|
|
break;
|
|
}
|
|
|
|
gSPDisplayList(renderdata->gdl++, rodata->primary);
|
|
|
|
if (rodata->unk12 == 3 && rodata->secondary) {
|
|
model0001f890(renderdata, false);
|
|
|
|
gSPDisplayList(renderdata->gdl++, rodata->secondary);
|
|
}
|
|
}
|
|
|
|
if ((renderdata->flags & 2) && rodata->primary && rodata->unk12 == 4 && rodata->secondary) {
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL1, osVirtualToPhysical(rodata->baseaddr));
|
|
|
|
if (renderdata->cullmode) {
|
|
modelApplyCullMode(renderdata);
|
|
}
|
|
|
|
model00020248(renderdata, false);
|
|
|
|
gSPDisplayList(renderdata->gdl++, rodata->secondary);
|
|
}
|
|
}
|
|
|
|
void modelRenderNodeDl(struct modelrenderdata *renderdata, struct model *model, struct modelnode *node)
|
|
{
|
|
union modelrodata *rodata = node->rodata;
|
|
|
|
if (var8005efc4 && !var8005efc4(model, node)) {
|
|
return;
|
|
}
|
|
|
|
if (renderdata->flags & 1) {
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->dl.gdl) {
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL1, osVirtualToPhysical(rodata->dl.colourtable));
|
|
|
|
if (renderdata->cullmode) {
|
|
modelApplyCullMode(renderdata);
|
|
}
|
|
|
|
switch (rodata->dl.mcount) {
|
|
case 1:
|
|
model0001f7e0(renderdata);
|
|
break;
|
|
case 3:
|
|
model0001f890(renderdata, true);
|
|
break;
|
|
case 4:
|
|
model00020248(renderdata, true);
|
|
break;
|
|
case 2:
|
|
model00020bdc(renderdata);
|
|
break;
|
|
}
|
|
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_VTX, osVirtualToPhysical(rwdata->dl.vertices));
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL2, osVirtualToPhysical(rwdata->dl.colours));
|
|
|
|
gSPDisplayList(renderdata->gdl++, rwdata->dl.gdl);
|
|
|
|
if (rodata->dl.mcount == 3 && rodata->dl.secondary) {
|
|
model0001f890(renderdata, false);
|
|
|
|
gSPDisplayList(renderdata->gdl++, rodata->dl.secondary);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (renderdata->flags & 2) {
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->dl.gdl && rodata->dl.mcount == 4 && rodata->dl.secondary) {
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL1, osVirtualToPhysical(rodata->dl.colourtable));
|
|
|
|
if (renderdata->cullmode) {
|
|
modelApplyCullMode(renderdata);
|
|
}
|
|
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_VTX, osVirtualToPhysical(rwdata->dl.vertices));
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL2, osVirtualToPhysical(rwdata->dl.colours));
|
|
|
|
model00020248(renderdata, false);
|
|
|
|
gSPDisplayList(renderdata->gdl++, rodata->dl.secondary);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Star gunfire is a muzzle flash in a first person perspective, where the
|
|
* muzzle flash has 3 or 4 "arms" that flare out from the main body.
|
|
*
|
|
* Some weapons that use this are the Cyclone, Dragon, K7 Avenger, AR34,
|
|
* SuperDragon and RC-P45.
|
|
*
|
|
* This function reads vertices from the model definition, tweaks them randomly,
|
|
* writes them to a newly allocated vertices table and queues the node's
|
|
* displaylist to the renderdata's DL.
|
|
*/
|
|
void modelRenderNodeStarGunfire(struct modelrenderdata *renderdata, struct modelnode *node)
|
|
{
|
|
if (renderdata->flags & 2) {
|
|
struct modelrodata_stargunfire *rodata = &node->rodata->stargunfire;
|
|
s32 i;
|
|
|
|
if (rodata->gdl) {
|
|
struct gfxvtx *src = (struct gfxvtx *) rodata->vertices;
|
|
struct gfxvtx *dst = g_ModelVtxAllocatorFunc(rodata->unk00 * 4);
|
|
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_VTX, osVirtualToPhysical(dst));
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL2, osVirtualToPhysical((void *)ALIGN8((u32)&rodata->vertices[rodata->unk00 << 2])));
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL1, osVirtualToPhysical(rodata->baseaddr));
|
|
|
|
gDPSetFogColor(renderdata->gdl++, 0x00, 0x00, 0x00, 0x00);
|
|
gSPDisplayList(renderdata->gdl++, rodata->gdl);
|
|
|
|
for (i = 0; i < rodata->unk00; i++) {
|
|
u16 rand1 = (random() << 10) & 0xffff;
|
|
s32 s4 = ((coss(rand1) << 5) * 181) >> 18;
|
|
s32 s3 = ((sins(rand1) << 5) * 181) >> 18;
|
|
s32 s1 = random() >> 31;
|
|
s32 mult = 0x10000 - (random() & 0x3fff);
|
|
s32 corner1 = 0x200 + s3;
|
|
s32 corner2 = 0x200 - s3;
|
|
s32 corner3 = 0x200 - s4;
|
|
s32 corner4 = 0x200 + s4;
|
|
|
|
dst[0] = src[0];
|
|
dst[1] = src[1];
|
|
dst[2] = src[2];
|
|
dst[3] = src[3];
|
|
|
|
dst[0].s = corner3;
|
|
dst[0].t = corner2;
|
|
dst[0].x = (src[(s1 + 0) % 4].x * mult) >> 16;
|
|
dst[0].y = (src[(s1 + 0) % 4].y * mult) >> 16;
|
|
dst[0].z = (src[(s1 + 0) % 4].z * mult) >> 16;
|
|
|
|
dst[1].s = corner1;
|
|
dst[1].t = corner3;
|
|
dst[1].x = (src[(s1 + 1) % 4].x * mult) >> 16;
|
|
dst[1].y = (src[(s1 + 1) % 4].y * mult) >> 16;
|
|
dst[1].z = (src[(s1 + 1) % 4].z * mult) >> 16;
|
|
|
|
dst[2].s = corner4;
|
|
dst[2].t = corner1;
|
|
dst[2].x = (src[(s1 + 2) % 4].x * mult) >> 16;
|
|
dst[2].y = (src[(s1 + 2) % 4].y * mult) >> 16;
|
|
dst[2].z = (src[(s1 + 2) % 4].z * mult) >> 16;
|
|
|
|
dst[3].s = corner2;
|
|
dst[3].t = corner4;
|
|
dst[3].x = (src[(s1 + 3) % 4].x * mult) >> 16;
|
|
dst[3].y = (src[(s1 + 3) % 4].y * mult) >> 16;
|
|
dst[3].z = (src[(s1 + 3) % 4].z * mult) >> 16;
|
|
|
|
src += 4;
|
|
dst += 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void model000216cc(struct modelrenderdata *renderdata, struct textureconfig *tconfig, s32 arg2)
|
|
{
|
|
texSelect(&renderdata->gdl, tconfig, arg2, renderdata->zbufferenabled, 2, 1, NULL);
|
|
}
|
|
|
|
void modelRenderNodeChrGunfire(struct modelrenderdata *renderdata, struct model *model, struct modelnode *node)
|
|
{
|
|
u32 stack[3];
|
|
f32 negspc0;
|
|
struct modelrodata_chrgunfire *rodata = &node->rodata->chrgunfire;
|
|
union modelrwdata *rwdata = modelGetNodeRwData(model, node);
|
|
struct gfxvtx *vertices;
|
|
f32 spf0;
|
|
f32 spec;
|
|
struct coord spe0;
|
|
f32 spdc;
|
|
f32 spd8;
|
|
f32 spd4;
|
|
f32 spd0;
|
|
f32 spcc;
|
|
f32 spc8;
|
|
f32 spc4;
|
|
f32 spc0;
|
|
f32 spbc;
|
|
f32 negspcc;
|
|
f32 negspc8;
|
|
f32 scale;
|
|
Mtxf *mtx;
|
|
f32 tmp;
|
|
struct coord sp9c;
|
|
struct coord sp90;
|
|
struct gfxvtx vtxtemplate = {0};
|
|
struct colour colourtemplate = {0xffffffff};
|
|
struct textureconfig *tconfig;
|
|
struct colour *colours;
|
|
f32 distance;
|
|
|
|
if ((renderdata->flags & 2) && rwdata->chrgunfire.visible) {
|
|
s32 index = model0001a524(node, 0);
|
|
mtx = &model->matrices[index];
|
|
|
|
spe0.x = -(rodata->pos.f[0] * mtx->m[0][0] + rodata->pos.f[1] * mtx->m[1][0] + rodata->pos.f[2] * mtx->m[2][0] + mtx->m[3][0]);
|
|
spe0.y = -(rodata->pos.f[0] * mtx->m[0][1] + rodata->pos.f[1] * mtx->m[1][1] + rodata->pos.f[2] * mtx->m[2][1] + mtx->m[3][1]);
|
|
spe0.z = -(rodata->pos.f[0] * mtx->m[0][2] + rodata->pos.f[1] * mtx->m[1][2] + rodata->pos.f[2] * mtx->m[2][2] + mtx->m[3][2]);
|
|
|
|
distance = sqrtf(spe0.f[0] * spe0.f[0] + spe0.f[1] * spe0.f[1] + spe0.f[2] * spe0.f[2]);
|
|
|
|
if (distance > 0) {
|
|
f32 tmp = 1 / (model->scale * distance);
|
|
spe0.f[0] *= tmp;
|
|
spe0.f[1] *= tmp;
|
|
spe0.f[2] *= tmp;
|
|
} else {
|
|
spe0.f[0] = 0;
|
|
spe0.f[1] = 0;
|
|
spe0.f[2] = 1 / model->scale;
|
|
}
|
|
|
|
spec = acosf(spe0.f[0] * mtx->m[1][0] + spe0.f[1] * mtx->m[1][1] + spe0.f[2] * mtx->m[1][2]);
|
|
spf0 = acosf(-(spe0.f[0] * mtx->m[2][0] + spe0.f[1] * mtx->m[2][1] + spe0.f[2] * mtx->m[2][2]) / sinf(spec));
|
|
|
|
tmp = -(spe0.f[0] * mtx->m[0][0] + spe0.f[1] * mtx->m[0][1] + spe0.f[2] * mtx->m[0][2]);
|
|
|
|
if (tmp < 0) {
|
|
spf0 = M_BADTAU - spf0;
|
|
}
|
|
|
|
spdc = cosf(spf0);
|
|
spd8 = sinf(spf0);
|
|
spd4 = cosf(spec);
|
|
spd0 = sinf(spec);
|
|
|
|
scale = 0.75f + (random() % 128) * (1.0f / 256.0f); // 0.75 to 1.25
|
|
|
|
sp9c.f[0] = rodata->dim.f[0] * scale;
|
|
sp9c.f[1] = rodata->dim.f[1] * scale;
|
|
sp9c.f[2] = rodata->dim.f[2] * scale;
|
|
|
|
spcc = sp9c.f[0] * spdc * 0.5f;
|
|
spc8 = sp9c.f[2] * spd8 * 0.5f;
|
|
spc4 = sp9c.f[1] * spd0 * 0.5f;
|
|
|
|
spc0 = sp9c.f[0] * spd4 * spd8 * 0.5f;
|
|
spbc = sp9c.f[2] * spd4 * spdc * 0.5f;
|
|
|
|
negspcc = -spcc;
|
|
negspc8 = -spc8;
|
|
negspc0 = -spc0;
|
|
|
|
sp90.f[0] = rodata->pos.f[0] - sp9c.f[0] * 0.5f;
|
|
sp90.f[1] = rodata->pos.f[1];
|
|
sp90.f[2] = rodata->pos.f[2];
|
|
|
|
vertices = g_ModelVtxAllocatorFunc(4);
|
|
|
|
colours = (struct colour *) gfxAllocateColours(1);
|
|
|
|
vertices[0] = vtxtemplate;
|
|
vertices[1] = vtxtemplate;
|
|
vertices[2] = vtxtemplate;
|
|
vertices[3] = vtxtemplate;
|
|
|
|
colours[0] = colourtemplate;
|
|
|
|
vertices[0].x = sp90.f[0] + negspcc + negspc0;
|
|
vertices[0].y = sp90.f[1] - spc4;
|
|
vertices[0].z = sp90.f[2] - negspc8 + -spbc;
|
|
vertices[1].x = sp90.f[0] + negspcc - negspc0;
|
|
vertices[1].y = sp90.f[1] + spc4;
|
|
vertices[1].z = sp90.f[2] - negspc8 - -spbc;
|
|
vertices[2].x = sp90.f[0] - negspcc - negspc0;
|
|
vertices[2].y = sp90.f[1] + spc4;
|
|
vertices[2].z = sp90.f[2] + negspc8 - -spbc;
|
|
vertices[3].x = sp90.f[0] - negspcc + negspc0;
|
|
vertices[3].y = sp90.f[1] - spc4;
|
|
vertices[3].z = sp90.f[2] + negspc8 + -spbc;
|
|
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_COL1, osVirtualToPhysical(rodata->baseaddr));
|
|
|
|
if (rodata->texture) {
|
|
s32 centre;
|
|
u16 sp62;
|
|
s32 sp5c;
|
|
s32 sp58;
|
|
|
|
tconfig = rodata->texture;
|
|
|
|
sp62 = (random() * 1024) & 0xffff;
|
|
sp5c = (coss(sp62) * tconfig->width * 0xb5) >> 18;
|
|
sp58 = (sins(sp62) * tconfig->width * 0xb5) >> 18;
|
|
|
|
centre = tconfig->width << 4;
|
|
|
|
vertices[0].s = centre - sp5c;
|
|
vertices[0].t = centre - sp58;
|
|
vertices[1].s = centre + sp58;
|
|
vertices[1].t = centre - sp5c;
|
|
vertices[2].s = centre + sp5c;
|
|
vertices[2].t = centre + sp58;
|
|
vertices[3].s = centre - sp58;
|
|
vertices[3].t = centre + sp5c;
|
|
|
|
model000216cc(renderdata, tconfig, 4);
|
|
} else {
|
|
model000216cc(renderdata, NULL, 1);
|
|
}
|
|
|
|
gSPSetGeometryMode(renderdata->gdl++, G_CULL_BACK);
|
|
gSPMatrix(renderdata->gdl++, osVirtualToPhysical(mtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
gDPSetColorArray(renderdata->gdl++, osVirtualToPhysical(colours), 1);
|
|
gDPSetVerticeArray(renderdata->gdl++, osVirtualToPhysical(vertices), 4);
|
|
gDPTri2(renderdata->gdl++, 0, 1, 2, 2, 3, 0);
|
|
}
|
|
}
|
|
|
|
void modelRender(struct modelrenderdata *renderdata, struct model *model)
|
|
{
|
|
union modelrodata *rodata;
|
|
union modelrwdata *rwdata;
|
|
u32 type;
|
|
struct modelnode *node = model->filedata->rootnode;
|
|
|
|
gSPSegment(renderdata->gdl++, SPSEGMENT_MODEL_MTX, osVirtualToPhysical(model->matrices));
|
|
|
|
while (node) {
|
|
type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_DISTANCE:
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_DISTANCE:
|
|
node->child = rwdata->distance.visible ? rodata->distance.target : NULL;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
node->child = rwdata->toggle.visible ? rodata->toggle.target : NULL;
|
|
break;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->headspot.modelfiledata) {
|
|
struct modelnode *loopnode = rwdata->headspot.modelfiledata->rootnode;
|
|
node->child = loopnode;
|
|
|
|
while (loopnode) {
|
|
loopnode->parent = node;
|
|
loopnode = loopnode->next;
|
|
}
|
|
}
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
modelRenderNodeReorder(model, node);
|
|
break;
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
modelRenderNodeChrGunfire(renderdata, model, node);
|
|
break;
|
|
case MODELNODETYPE_GUNDL:
|
|
modelRenderNodeGundl(renderdata, model, node);
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
modelRenderNodeDl(renderdata, model, node);
|
|
break;
|
|
case MODELNODETYPE_STARGUNFIRE:
|
|
modelRenderNodeStarGunfire(renderdata, node);
|
|
break;
|
|
case MODELNODETYPE_CHRINFO:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool model000220fc(struct modelrodata_bbox *bbox, Mtxf *mtx, struct coord *arg2, struct coord *arg3)
|
|
{
|
|
f32 xthingx;
|
|
f32 xthingy;
|
|
f32 xthingz;
|
|
u32 stack1[3];
|
|
f32 xsum1;
|
|
f32 xsum2;
|
|
f32 xsum3;
|
|
|
|
f32 f0;
|
|
u32 stack;
|
|
|
|
f32 ythingx;
|
|
f32 ythingy;
|
|
f32 ythingz;
|
|
u32 stack2[3];
|
|
f32 ysum1;
|
|
f32 ysum2;
|
|
f32 ysum3;
|
|
|
|
f32 mult1;
|
|
f32 mult2;
|
|
|
|
f32 bestsum2;
|
|
f32 bestsum1;
|
|
f32 anotherbestsum3;
|
|
f32 anotherbestsum1;
|
|
|
|
f32 xmin = bbox->xmin;
|
|
f32 xmax = bbox->xmax;
|
|
f32 ymin = bbox->ymin;
|
|
f32 ymax = bbox->ymax;
|
|
f32 zmin = bbox->zmin;
|
|
f32 zmax = bbox->zmax;
|
|
|
|
f32 mult3;
|
|
f32 mult4;
|
|
|
|
f32 zthingx;
|
|
f32 zthingy;
|
|
f32 zthingz;
|
|
u32 stack3[3];
|
|
f32 zsum1;
|
|
f32 zsum2;
|
|
f32 zsum3;
|
|
|
|
if (var8005efc0 != 0.0f) {
|
|
xmin -= var8005efc0;
|
|
xmax += var8005efc0;
|
|
ymin -= var8005efc0;
|
|
ymax += var8005efc0;
|
|
zmin -= var8005efc0;
|
|
zmax += var8005efc0;
|
|
}
|
|
|
|
// x
|
|
xthingx = mtx->m[0][0] * mtx->m[0][0];
|
|
xthingy = mtx->m[0][1] * mtx->m[0][1];
|
|
xthingz = mtx->m[0][2] * mtx->m[0][2];
|
|
|
|
xsum1 = mtx->m[0][0] * arg3->f[0] + mtx->m[0][1] * arg3->f[1] + mtx->m[0][2] * arg3->f[2];
|
|
xsum2 = mtx->m[0][0] * (arg2->f[0] - mtx->m[3][0]) + mtx->m[0][1] * (arg2->f[1] - mtx->m[3][1]) + mtx->m[0][2] * (arg2->f[2] - mtx->m[3][2]);
|
|
|
|
f0 = -(xthingx + xthingy + xthingz) * xmax;
|
|
xsum3 = -(xsum2 + f0);
|
|
f0 = -(xthingx + xthingy + xthingz) * xmin;
|
|
xsum2 = -(xsum2 + f0);
|
|
|
|
if (xsum1 < 0.0f) {
|
|
xsum1 = -xsum1;
|
|
xsum2 = -xsum2;
|
|
xsum3 = -xsum3;
|
|
}
|
|
|
|
if (xsum2 < 0.0f && xsum3 < 0.0f) {
|
|
return false;
|
|
}
|
|
|
|
if (xsum3 < xsum2) {
|
|
f32 tmp = xsum2;
|
|
xsum2 = xsum3;
|
|
xsum3 = tmp;
|
|
}
|
|
|
|
// y
|
|
ythingx = mtx->m[1][0] * mtx->m[1][0];
|
|
ythingy = mtx->m[1][1] * mtx->m[1][1];
|
|
ythingz = mtx->m[1][2] * mtx->m[1][2];
|
|
|
|
ysum1 = mtx->m[1][0] * arg3->f[0] + mtx->m[1][1] * arg3->f[1] + mtx->m[1][2] * arg3->f[2];
|
|
ysum2 = mtx->m[1][0] * (arg2->f[0] - mtx->m[3][0]) + mtx->m[1][1] * (arg2->f[1] - mtx->m[3][1]) + mtx->m[1][2] * (arg2->f[2] - mtx->m[3][2]);
|
|
|
|
f0 = -(ythingx + ythingy + ythingz) * ymax;
|
|
ysum3 = -(ysum2 + f0);
|
|
f0 = -(ythingx + ythingy + ythingz) * ymin;
|
|
ysum2 = -(ysum2 + f0);
|
|
|
|
if (ysum1 < 0.0f) {
|
|
ysum1 = -ysum1;
|
|
ysum2 = -ysum2;
|
|
ysum3 = -ysum3;
|
|
}
|
|
|
|
if (ysum2 < 0.0f && ysum3 < 0.0f) {
|
|
return false;
|
|
}
|
|
|
|
if (ysum3 < ysum2) {
|
|
f32 tmp = ysum2;
|
|
ysum2 = ysum3;
|
|
ysum3 = tmp;
|
|
}
|
|
|
|
// Do x and y comparison things
|
|
mult1 = ysum2 * xsum1;
|
|
mult2 = xsum2 * ysum1;
|
|
mult3 = xsum3 * ysum1;
|
|
mult4 = ysum3 * xsum1;
|
|
|
|
if (mult1 < mult2) {
|
|
if (mult4 < mult2) {
|
|
return false;
|
|
}
|
|
|
|
bestsum2 = xsum2;
|
|
bestsum1 = xsum1;
|
|
} else {
|
|
if (mult3 < mult1) {
|
|
return false;
|
|
}
|
|
|
|
bestsum2 = ysum2;
|
|
bestsum1 = ysum1;
|
|
}
|
|
|
|
if (mult3 < mult4) {
|
|
anotherbestsum3 = xsum3;
|
|
anotherbestsum1 = xsum1;
|
|
} else {
|
|
anotherbestsum3 = ysum3;
|
|
anotherbestsum1 = ysum1;
|
|
}
|
|
|
|
// z
|
|
zthingx = mtx->m[2][0] * mtx->m[2][0];
|
|
zthingy = mtx->m[2][1] * mtx->m[2][1];
|
|
zthingz = mtx->m[2][2] * mtx->m[2][2];
|
|
|
|
zsum1 = mtx->m[2][0] * arg3->f[0] + mtx->m[2][1] * arg3->f[1] + mtx->m[2][2] * arg3->f[2];
|
|
zsum2 = mtx->m[2][0] * (arg2->f[0] - mtx->m[3][0]) + mtx->m[2][1] * (arg2->f[1] - mtx->m[3][1]) + mtx->m[2][2] * (arg2->f[2] - mtx->m[3][2]);
|
|
|
|
f0 = -(zthingx + zthingy + zthingz) * zmax;
|
|
zsum3 = -(zsum2 + f0);
|
|
f0 = -(zthingx + zthingy + zthingz) * zmin;
|
|
zsum2 = -(zsum2 + f0);
|
|
|
|
if (zsum1 < 0.0f) {
|
|
zsum1 = -zsum1;
|
|
zsum2 = -zsum2;
|
|
zsum3 = -zsum3;
|
|
}
|
|
|
|
if (zsum2 < 0.0f && zsum3 < 0.0f) {
|
|
return false;
|
|
}
|
|
|
|
if (zsum3 < zsum2) {
|
|
f32 tmp = zsum2;
|
|
zsum2 = zsum3;
|
|
zsum3 = tmp;
|
|
}
|
|
|
|
// Do z comparison things with the result of the x/y comparison thing
|
|
if (bestsum2 * zsum1 < zsum2 * bestsum1) {
|
|
if (anotherbestsum3 * zsum1 < zsum2 * anotherbestsum1) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (zsum3 * bestsum1 < bestsum2 * zsum1) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
s32 model000225d4(struct model *model, struct coord *arg1, struct coord *arg2, struct modelnode **startnode)
|
|
{
|
|
struct modelnode *node;
|
|
bool dochildren = true;
|
|
Mtxf *mtx;
|
|
union modelrodata *rodata;
|
|
union modelrwdata *rwdata;
|
|
u32 type;
|
|
|
|
if (model);
|
|
|
|
if (*startnode) {
|
|
node = *startnode;
|
|
*startnode = NULL;
|
|
} else {
|
|
node = model->filedata->rootnode;
|
|
}
|
|
|
|
while (node) {
|
|
if (dochildren && node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
|
|
if (!node) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
dochildren = true;
|
|
type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_BBOX:
|
|
rodata = node->rodata;
|
|
mtx = model0001a5cc(model, node, 0);
|
|
|
|
if (model000220fc(&rodata->bbox, mtx, arg1, arg2)) {
|
|
*startnode = node;
|
|
return rodata->bbox.hitpart;
|
|
}
|
|
|
|
dochildren = false;
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
node->child = rwdata->distance.visible ? rodata->distance.target : NULL;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
node->child = rwdata->toggle.visible ? rodata->toggle.target : NULL;
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
|
|
if (rwdata->headspot.modelfiledata) {
|
|
struct modelnode *loopnode = rwdata->headspot.modelfiledata->rootnode;
|
|
|
|
node->child = loopnode;
|
|
|
|
while (loopnode) {
|
|
loopnode->parent = node;
|
|
loopnode = loopnode->next;
|
|
}
|
|
}
|
|
break;
|
|
case MODELNODETYPE_CHRINFO:
|
|
case MODELNODETYPE_DL:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define PROMOTE(var) \
|
|
if (var) \
|
|
var = (void *)((u32)var + diff)
|
|
|
|
void modelPromoteNodeOffsetsToPointers(struct modelnode *node, u32 vma, u32 fileramaddr)
|
|
{
|
|
union modelrodata *rodata;
|
|
s32 diff = fileramaddr - vma;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
PROMOTE(node->rodata);
|
|
PROMOTE(node->parent);
|
|
PROMOTE(node->next);
|
|
PROMOTE(node->prev);
|
|
PROMOTE(node->child);
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
break;
|
|
case MODELNODETYPE_POSITION:
|
|
break;
|
|
case MODELNODETYPE_GUNDL:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->gundl.vertices);
|
|
rodata->gundl.baseaddr = (void *)fileramaddr;
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->dl.vertices);
|
|
rodata->dl.colourtable = (void *)fileramaddr;
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->distance.target);
|
|
node->child = rodata->distance.target;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->toggle.target);
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->reorder.unk18);
|
|
PROMOTE(rodata->reorder.unk1c);
|
|
break;
|
|
case MODELNODETYPE_11:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->type11.unk14);
|
|
break;
|
|
case MODELNODETYPE_0B:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->type0b.unk3c);
|
|
rodata->type0b.baseaddr = (void *)fileramaddr;
|
|
break;
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->chrgunfire.texture);
|
|
rodata->chrgunfire.baseaddr = (void *)fileramaddr;
|
|
break;
|
|
case MODELNODETYPE_0D:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->type0d.unk10);
|
|
PROMOTE(rodata->type0d.unk14);
|
|
rodata->type0d.baseaddr = (void *)fileramaddr;
|
|
break;
|
|
case MODELNODETYPE_STARGUNFIRE:
|
|
rodata = node->rodata;
|
|
PROMOTE(rodata->stargunfire.vertices);
|
|
rodata->stargunfire.baseaddr = (void *)fileramaddr;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a model file's file-relative offsets to global pointers,
|
|
* and sort the part numbers list so they can be looked up using bisection.
|
|
*
|
|
* Offsets in model files are based from virtual memory address 0x0f000000.
|
|
* This vma address is specified as an argument to the function.
|
|
*/
|
|
void modelPromoteOffsetsToPointers(struct modelfiledata *filedata, u32 vma, u32 fileramaddr)
|
|
{
|
|
s32 diff = fileramaddr - vma;
|
|
s32 i;
|
|
s16 *partnums;
|
|
|
|
PROMOTE(filedata->rootnode);
|
|
PROMOTE(filedata->parts);
|
|
PROMOTE(filedata->texconfigs);
|
|
|
|
for (i = 0; i < filedata->numparts; i++) {
|
|
PROMOTE(filedata->parts[i]);
|
|
}
|
|
|
|
modelPromoteNodeOffsetsToPointers(filedata->rootnode, vma, fileramaddr);
|
|
|
|
// Sort parts by part number so they can be bisected during lookup
|
|
partnums = (s16 *)&filedata->parts[filedata->numparts];
|
|
|
|
if (filedata->numparts) {
|
|
struct modelnode *tmpnode;
|
|
s16 tmpnum;
|
|
bool changed;
|
|
|
|
do {
|
|
changed = false;
|
|
|
|
for (i = 0; i < filedata->numparts - 1; i++) {
|
|
if (partnums[i] > partnums[i + 1]) {
|
|
tmpnum = partnums[i];
|
|
partnums[i] = partnums[i + 1];
|
|
partnums[i + 1] = tmpnum;
|
|
|
|
tmpnode = filedata->parts[i];
|
|
filedata->parts[i] = filedata->parts[i + 1];
|
|
filedata->parts[i + 1] = tmpnode;
|
|
|
|
changed = true;
|
|
}
|
|
}
|
|
} while (changed == true);
|
|
}
|
|
}
|
|
|
|
s32 modelCalculateRwDataIndexes(struct modelnode *basenode)
|
|
{
|
|
u16 len = 0;
|
|
struct modelnode *node = basenode;
|
|
union modelrodata *rodata;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
rodata = node->rodata;
|
|
rodata->chrinfo.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_chrinfo) / 4;
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
rodata = node->rodata;
|
|
rodata->distance.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_distance) / 4;
|
|
node->child = rodata->distance.target;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
rodata->toggle.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_toggle) / 4;
|
|
node->child = rodata->toggle.target;
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
rodata = node->rodata;
|
|
rodata->headspot.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_headspot) / 4;
|
|
node->child = NULL;
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
rodata = node->rodata;
|
|
rodata->reorder.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_reorder) / 4;
|
|
model0001c868(node, false);
|
|
break;
|
|
case MODELNODETYPE_0B:
|
|
rodata = node->rodata;
|
|
rodata->type0b.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_0b) / 4;
|
|
break;
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
rodata = node->rodata;
|
|
rodata->chrgunfire.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_chrgunfire) / 4;
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
rodata = node->rodata;
|
|
rodata->dl.rwdataindex = len;
|
|
len += sizeof(struct modelrwdata_dl) / 4;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node == basenode->parent) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
void modelCalculateRwDataLen(struct modelfiledata *filedata)
|
|
{
|
|
filedata->rwdatalen = modelCalculateRwDataIndexes(filedata->rootnode);
|
|
}
|
|
|
|
void modelInitRwData(struct model *model, struct modelnode *startnode)
|
|
{
|
|
struct modelnode *node = startnode;
|
|
union modelrodata *rodata;
|
|
union modelrwdata *rwdata;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_CHRINFO:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
|
|
rwdata->chrinfo.unk00 = 0;
|
|
rwdata->chrinfo.ground = 0;
|
|
rwdata->chrinfo.pos.x = 0;
|
|
rwdata->chrinfo.pos.y = 0;
|
|
rwdata->chrinfo.pos.z = 0;
|
|
rwdata->chrinfo.unk14 = 0;
|
|
rwdata->chrinfo.unk18 = 0;
|
|
rwdata->chrinfo.unk1c = 0;
|
|
|
|
rwdata->chrinfo.unk01 = 0;
|
|
rwdata->chrinfo.unk34.x = 0;
|
|
rwdata->chrinfo.unk34.y = 0;
|
|
rwdata->chrinfo.unk34.z = 0;
|
|
rwdata->chrinfo.unk30 = 0;
|
|
rwdata->chrinfo.unk24.x = 0;
|
|
rwdata->chrinfo.unk24.y = 0;
|
|
rwdata->chrinfo.unk24.z = 0;
|
|
rwdata->chrinfo.unk20 = 0;
|
|
|
|
rwdata->chrinfo.unk02 = 0;
|
|
rwdata->chrinfo.unk4c.x = 0;
|
|
rwdata->chrinfo.unk4c.y = 0;
|
|
rwdata->chrinfo.unk4c.z = 0;
|
|
rwdata->chrinfo.unk40.x = 0;
|
|
rwdata->chrinfo.unk40.y = 0;
|
|
rwdata->chrinfo.unk40.z = 0;
|
|
rwdata->chrinfo.unk5c = 0;
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->distance.visible = false;
|
|
node->child = rodata->distance.target;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->toggle.visible = true;
|
|
node->child = rodata->toggle.target;
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->headspot.modelfiledata = NULL;
|
|
rwdata->headspot.rwdatas = NULL;
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->reorder.visible = false;
|
|
modelRenderNodeReorder(model, node);
|
|
break;
|
|
case MODELNODETYPE_0B:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->type0b.unk00 = 0;
|
|
break;
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->chrgunfire.visible = false;
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->dl.vertices = rodata->dl.vertices;
|
|
rwdata->dl.gdl = rodata->dl.primary;
|
|
rwdata->dl.colours = (void *) ALIGN8((u32)(rodata->dl.vertices + rodata->dl.numvertices));
|
|
if (rodata->dl.numvertices);
|
|
if (rodata->dl.numvertices);
|
|
if (rodata->dl.numvertices);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node == startnode->parent) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void modelInit(struct model *model, struct modelfiledata *filedata, union modelrwdata **rwdatas, bool resetanim)
|
|
{
|
|
struct modelnode *node;
|
|
|
|
model->unk00 = 0;
|
|
model->filedata = filedata;
|
|
model->rwdatas = rwdatas;
|
|
model->unk02 = -1;
|
|
model->scale = 1;
|
|
model->attachedtomodel = NULL;
|
|
model->attachedtonode = NULL;
|
|
|
|
node = filedata->rootnode;
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
if (type == MODELNODETYPE_HEADSPOT) {
|
|
model->unk00 |= 1;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node == filedata->rootnode->parent) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rwdatas != NULL) {
|
|
modelInitRwData(model, filedata->rootnode);
|
|
}
|
|
|
|
if (resetanim) {
|
|
model->anim = NULL;
|
|
}
|
|
}
|
|
|
|
void animInit(struct anim *anim)
|
|
{
|
|
anim->animnum = 0;
|
|
anim->animnum2 = 0;
|
|
anim->looping = 0;
|
|
anim->flipfunc = NULL;
|
|
anim->unk6c = 0;
|
|
anim->unk70 = NULL;
|
|
anim->average = 0;
|
|
anim->frac = 0;
|
|
anim->timespeed = 0;
|
|
anim->frac2 = 0;
|
|
anim->timespeed2 = 0;
|
|
anim->fracmerge = 0;
|
|
anim->timemerge = 0;
|
|
anim->timeplay = 0;
|
|
anim->endframe = -1;
|
|
anim->endframe2 = -1;
|
|
anim->speed = 1;
|
|
anim->speed2 = 1;
|
|
anim->playspeed = 1;
|
|
anim->animscale = 1;
|
|
}
|
|
|
|
void model00023108(struct model *pmodel, struct modelfiledata *pmodeldef, struct modelnode *pnode, struct modelfiledata *cmodeldef)
|
|
{
|
|
struct modelrwdata_headspot *rwdata = modelGetNodeRwData(pmodel, pnode);
|
|
struct modelnode *node;
|
|
|
|
rwdata->modelfiledata = cmodeldef;
|
|
rwdata->rwdatas = &pmodel->rwdatas[pmodeldef->rwdatalen];
|
|
|
|
pnode->child = cmodeldef->rootnode;
|
|
|
|
node = pnode->child;
|
|
|
|
while (node) {
|
|
node->parent = pnode;
|
|
node = node->next;
|
|
}
|
|
|
|
pmodeldef->rwdatalen += modelCalculateRwDataIndexes(pnode->child);
|
|
}
|
|
|
|
/**
|
|
* This function can be called repeatedly to iterate a model's display lists.
|
|
*
|
|
* On the first call, the value passed as nodeptr should point to a NULL value.
|
|
* Each time the function is called, it will update *gdlptr to point to the next
|
|
* display list, and will update *nodeptr to point to the current node. On
|
|
* subsequent calls, the same values should be passed as nodeptr and gdlptr so
|
|
* the function can continue correctly.
|
|
*
|
|
* Note that some node types support multiple display lists, so the function
|
|
* may return the same node while it iterates the display lists for that node.
|
|
*/
|
|
void modelIterateDisplayLists(struct modelfiledata *filedata, struct modelnode **nodeptr, Gfx **gdlptr)
|
|
{
|
|
struct modelnode *node = *nodeptr;
|
|
union modelrodata *rodata;
|
|
Gfx *gdl = NULL;
|
|
|
|
if (node == NULL) {
|
|
node = filedata->rootnode;
|
|
}
|
|
|
|
while (node) {
|
|
u32 type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_GUNDL:
|
|
rodata = node->rodata;
|
|
|
|
if (node != *nodeptr) {
|
|
gdl = rodata->gundl.primary;
|
|
} else if (rodata->gundl.secondary != *gdlptr) {
|
|
gdl = rodata->gundl.secondary;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
rodata = node->rodata;
|
|
|
|
if (node != *nodeptr) {
|
|
gdl = rodata->dl.primary;
|
|
} else if (rodata->dl.secondary != *gdlptr) {
|
|
gdl = rodata->dl.secondary;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_STARGUNFIRE:
|
|
rodata = node->rodata;
|
|
|
|
if (node != *nodeptr) {
|
|
gdl = rodata->stargunfire.gdl;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_DISTANCE:
|
|
rodata = node->rodata;
|
|
node->child = rodata->distance.target;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
node->child = rodata->toggle.target;
|
|
break;
|
|
case MODELNODETYPE_REORDER:
|
|
model0001c868(node, true);
|
|
break;
|
|
}
|
|
|
|
if (gdl) {
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
*gdlptr = gdl;
|
|
*nodeptr = node;
|
|
}
|
|
|
|
void modelNodeReplaceGdl(u32 arg0, struct modelnode *node, Gfx *find, Gfx *replacement)
|
|
{
|
|
union modelrodata *rodata;
|
|
u32 type = node->type & 0xff;
|
|
|
|
switch (type) {
|
|
case MODELNODETYPE_GUNDL:
|
|
rodata = node->rodata;
|
|
|
|
if (rodata->gundl.primary == find) {
|
|
rodata->gundl.primary = replacement;
|
|
return;
|
|
}
|
|
|
|
if (rodata->gundl.secondary == find) {
|
|
rodata->gundl.secondary = replacement;
|
|
return;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
rodata = node->rodata;
|
|
|
|
if (rodata->dl.primary == find) {
|
|
rodata->dl.primary = replacement;
|
|
return;
|
|
}
|
|
|
|
if (rodata->dl.secondary == find) {
|
|
rodata->dl.secondary = replacement;
|
|
return;
|
|
}
|
|
break;
|
|
case MODELNODETYPE_STARGUNFIRE:
|
|
rodata = node->rodata;
|
|
|
|
if (rodata->stargunfire.gdl == find) {
|
|
rodata->stargunfire.gdl = replacement;
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|