mirror of
https://github.com/pret/pokeplatinum.git
synced 2026-03-21 17:55:13 -05:00
338 lines
9.7 KiB
C
338 lines
9.7 KiB
C
#include "simple3d.h"
|
|
|
|
#include <nitro.h>
|
|
#include <string.h>
|
|
|
|
#include "easy3d.h"
|
|
#include "fx_util.h"
|
|
#include "graphics.h"
|
|
#include "heap.h"
|
|
#include "narc.h"
|
|
#include "sys_task.h"
|
|
#include "sys_task_manager.h"
|
|
|
|
enum Simple3DAnimationFlags {
|
|
ANIM_OWNS_SET = 1 << 0,
|
|
ANIM_REACHED_END = 1 << 1,
|
|
};
|
|
|
|
static void LoadAnimFromSet(Simple3DAnimation *anim, void *animSet, u32 unused);
|
|
static void LoadAnimFromSet_NewAlloc(Simple3DAnimation *anim, void *animSet, u32 unused);
|
|
static void CreateAnimCopy(Simple3DAnimation *dest, Simple3DAnimation *src, u32 unused);
|
|
static void ZeroOutModel(Simple3DModel *model);
|
|
static void LoadModelFromSet(Simple3DModel *model, NNSG3dResFileHeader *modelSetHeader, u32 modelIndex);
|
|
static void BindModelTexture(Simple3DModel *model);
|
|
static void FreeMdlSetHeader(Simple3DModel *model);
|
|
static void UnloadModelTexture(Simple3DModel *model);
|
|
static void BindAnimToModel(Simple3DAnimation *anim, const NNSG3dResMdl *model, u32 heapID);
|
|
static void InitG3DAnimObject(Simple3DAnimation *anim, const NNSG3dResMdl *model, const NNSG3dResTex *texture);
|
|
static void ZeroOutRenderObj(Simple3DRenderObj *renderObj);
|
|
static void BindModelToRenderObj(Simple3DRenderObj *renderObj, NNSG3dResMdl *model);
|
|
static void BindAnimToRenderObj(Simple3DRenderObj *renderObj, NNSG3dAnmObj *anim);
|
|
|
|
static const VecFx32 sVecOnes = {
|
|
FX32_ONE,
|
|
FX32_ONE,
|
|
FX32_ONE,
|
|
};
|
|
|
|
static const MtxFx33 sIdentity = {
|
|
// clang-format off
|
|
FX32_ONE, 0, 0,
|
|
0, FX32_ONE, 0,
|
|
0, 0, FX32_ONE,
|
|
// clang-format on
|
|
};
|
|
|
|
static void ZeroOutModel(Simple3DModel *model)
|
|
{
|
|
memset(model, 0, sizeof(Simple3DModel));
|
|
}
|
|
|
|
static void LoadModelFromSet(Simple3DModel *dest, NNSG3dResFileHeader *modelSetHeader, u32 modelIndex)
|
|
{
|
|
ZeroOutModel(dest);
|
|
|
|
dest->modelSetHeader = modelSetHeader;
|
|
dest->isTextureBound = FALSE;
|
|
dest->modelSet = NNS_G3dGetMdlSet(modelSetHeader);
|
|
dest->g3DModel = NNS_G3dGetMdlByIdx(dest->modelSet, modelIndex);
|
|
dest->texture = NNS_G3dGetTex(modelSetHeader);
|
|
}
|
|
|
|
void Simple3D_LoadModelFromSet(Simple3DModel *dest, u32 modelIdx, NARC *narc, u32 modelSetNarcIdx, u32 heapID, BOOL allocAtEnd)
|
|
{
|
|
NNSG3dResFileHeader *modelSetHeader = LoadMemberFromOpenNARC(narc, modelSetNarcIdx, FALSE, heapID, allocAtEnd);
|
|
LoadModelFromSet(dest, modelSetHeader, modelIdx);
|
|
}
|
|
|
|
static void BindModelTexture(Simple3DModel *model)
|
|
{
|
|
Easy3D_UploadTextureToVRAM(model->texture);
|
|
NNS_G3dBindMdlSet(model->modelSet, model->texture);
|
|
model->isTextureBound = TRUE;
|
|
}
|
|
|
|
static void BindModelTextureSysTaskCB(SysTask *sysTask, void *_model)
|
|
{
|
|
Simple3DModel *model = _model;
|
|
|
|
BindModelTexture(model);
|
|
SysTask_Done(sysTask);
|
|
}
|
|
|
|
void Simple3D_ScheduleBindModelTexture(Simple3DModel *model)
|
|
{
|
|
SysTask *sysTask = SysTask_ExecuteOnVBlank(BindModelTextureSysTaskCB, model, 0xffff);
|
|
GF_ASSERT(sysTask != NULL);
|
|
}
|
|
|
|
static void FreeMdlSetHeader(Simple3DModel *model)
|
|
{
|
|
if (model->modelSetHeader) {
|
|
Heap_Free(model->modelSetHeader);
|
|
}
|
|
}
|
|
|
|
static void UnloadModelTexture(Simple3DModel *model)
|
|
{
|
|
if (model->texture != NULL) {
|
|
NNSG3dTexKey texKey;
|
|
NNSG3dTexKey tex4x4Key;
|
|
NNSG3dPlttKey plttKey;
|
|
|
|
NNS_G3dTexReleaseTexKey(model->texture, &texKey, &tex4x4Key);
|
|
NNS_GfdFreeTexVram(texKey);
|
|
NNS_GfdFreeTexVram(tex4x4Key);
|
|
|
|
plttKey = NNS_G3dPlttReleasePlttKey(model->texture);
|
|
NNS_GfdFreePlttVram(plttKey);
|
|
|
|
model->texture = NULL;
|
|
}
|
|
}
|
|
|
|
void Simple3D_FreeModel(Simple3DModel *model)
|
|
{
|
|
UnloadModelTexture(model);
|
|
FreeMdlSetHeader(model);
|
|
ZeroOutModel(model);
|
|
}
|
|
|
|
void Simple3D_ZeroOutAnimation(Simple3DAnimation *anim)
|
|
{
|
|
memset(anim, 0, sizeof(Simple3DAnimation));
|
|
}
|
|
|
|
static void LoadAnimFromSet_NewAlloc(Simple3DAnimation *dest, void *animSet, u32 unused)
|
|
{
|
|
LoadAnimFromSet(dest, animSet, unused);
|
|
dest->flags |= ANIM_OWNS_SET;
|
|
}
|
|
|
|
void Simple3D_LoadFromAllocatedSet(Simple3DAnimation *dest, void *animSet, u32 unused)
|
|
{
|
|
LoadAnimFromSet(dest, animSet, unused);
|
|
dest->flags &= ~ANIM_OWNS_SET;
|
|
}
|
|
|
|
static void CreateAnimCopy(Simple3DAnimation *dest, Simple3DAnimation *src, u32 unused)
|
|
{
|
|
void *v0 = src->animSet;
|
|
Simple3D_LoadFromAllocatedSet(dest, v0, unused);
|
|
}
|
|
|
|
void Simple3D_LoadAnimFromOpenNARC(Simple3DAnimation *anim, u32 unused, NARC *narc, u32 animSetNarcIdx, u32 heapID, BOOL allocAtEnd)
|
|
{
|
|
void *v0 = LoadMemberFromOpenNARC(narc, animSetNarcIdx, FALSE, heapID, allocAtEnd);
|
|
LoadAnimFromSet_NewAlloc(anim, v0, unused);
|
|
}
|
|
|
|
static void LoadAnimFromSet(Simple3DAnimation *dest, void *animSet, u32 unused)
|
|
{
|
|
Simple3D_ZeroOutAnimation(dest);
|
|
|
|
dest->animSet = animSet;
|
|
dest->g3DAnim = NNS_G3dGetAnmByIdx(dest->animSet, 0);
|
|
}
|
|
|
|
void Simple3D_FreeAnimationSet(Simple3DAnimation *anim)
|
|
{
|
|
if (anim->flags & ANIM_OWNS_SET) {
|
|
Heap_Free(anim->animSet);
|
|
anim->flags &= ~ANIM_OWNS_SET;
|
|
}
|
|
|
|
anim->animSet = NULL;
|
|
anim->g3DAnim = NULL;
|
|
}
|
|
|
|
static void BindAnimToModel(Simple3DAnimation *anim, const NNSG3dResMdl *model, u32 heapID)
|
|
{
|
|
HeapExp_FndInitAllocator(&anim->allocator, heapID, 4);
|
|
anim->animObj = NNS_G3dAllocAnmObj(&anim->allocator, anim->g3DAnim, model);
|
|
|
|
GF_ASSERT(anim->animObj != NULL);
|
|
}
|
|
|
|
void Simple3D_BindModelToAnim(Simple3DAnimation *anim, const Simple3DModel *model, u32 heapID)
|
|
{
|
|
BindAnimToModel(anim, model->g3DModel, heapID);
|
|
}
|
|
|
|
static void InitG3DAnimObject(Simple3DAnimation *anim, const NNSG3dResMdl *model, const NNSG3dResTex *texture)
|
|
{
|
|
NNS_G3dAnmObjInit(anim->animObj, anim->g3DAnim, model, texture);
|
|
}
|
|
|
|
void Simple3D_InitG3DAnimObject(Simple3DAnimation *anim, const Simple3DModel *model)
|
|
{
|
|
InitG3DAnimObject(anim, model->g3DModel, model->texture);
|
|
}
|
|
|
|
void Simple3D_ApplyAnimCopyToModel(Simple3DAnimation *dest, const Simple3DModel *model, Simple3DAnimation *src, u32 unused, u32 heapID)
|
|
{
|
|
CreateAnimCopy(dest, src, unused);
|
|
Simple3D_BindModelToAnim(dest, model, heapID);
|
|
Simple3D_InitG3DAnimObject(dest, model);
|
|
}
|
|
|
|
void Simple3D_FreeAnimObject(Simple3DAnimation *anim)
|
|
{
|
|
if (anim->animObj) {
|
|
NNS_G3dFreeAnmObj(&anim->allocator, anim->animObj);
|
|
anim->animObj = NULL;
|
|
}
|
|
}
|
|
|
|
void Simple3D_FreeAnimation(Simple3DAnimation *anim)
|
|
{
|
|
Simple3D_FreeAnimObject(anim);
|
|
Simple3D_FreeAnimationSet(anim);
|
|
Simple3D_ZeroOutAnimation(anim);
|
|
}
|
|
|
|
BOOL Simple3D_UpdateAnim(Simple3DAnimation *anim, fx32 frameDelta, BOOL loop)
|
|
{
|
|
u32 reachedEnd = FALSE;
|
|
fx32 animLength = NNS_G3dAnmObjGetNumFrame(anim->animObj);
|
|
|
|
anim->currFrame += frameDelta;
|
|
|
|
if (frameDelta > 0) {
|
|
if (anim->currFrame >= animLength) {
|
|
reachedEnd = TRUE;
|
|
|
|
if (loop == TRUE) {
|
|
anim->currFrame -= animLength;
|
|
} else {
|
|
anim->currFrame = animLength;
|
|
}
|
|
}
|
|
} else {
|
|
if (anim->currFrame <= 0) {
|
|
reachedEnd = TRUE;
|
|
|
|
if (loop == TRUE) {
|
|
anim->currFrame += animLength;
|
|
} else {
|
|
anim->currFrame = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
NNS_G3dAnmObjSetFrame(anim->animObj, anim->currFrame);
|
|
|
|
if (reachedEnd == TRUE) {
|
|
anim->flags |= ANIM_REACHED_END;
|
|
} else {
|
|
anim->flags &= ~ANIM_REACHED_END;
|
|
}
|
|
|
|
return reachedEnd;
|
|
}
|
|
|
|
void Simple3D_SetAnimFrame(Simple3DAnimation *anim, fx32 frame)
|
|
{
|
|
anim->currFrame = frame;
|
|
}
|
|
|
|
fx32 Simple3D_GetAnimFrame(const Simple3DAnimation *anim)
|
|
{
|
|
return anim->currFrame;
|
|
}
|
|
|
|
fx32 Simple3D_GetAnimFrameCount(const Simple3DAnimation *anim)
|
|
{
|
|
GF_ASSERT(anim->animObj != NULL);
|
|
return NNS_G3dAnmObjGetNumFrame(anim->animObj);
|
|
}
|
|
|
|
BOOL Simple3D_HasAnimationReachedEnd(const Simple3DAnimation *anim)
|
|
{
|
|
return (anim->flags & ANIM_REACHED_END) != 0;
|
|
}
|
|
|
|
static void ZeroOutRenderObj(Simple3DRenderObj *renderObj)
|
|
{
|
|
memset(renderObj, 0, sizeof(Simple3DRenderObj));
|
|
}
|
|
|
|
static void BindModelToRenderObj(Simple3DRenderObj *renderObj, NNSG3dResMdl *model)
|
|
{
|
|
ZeroOutRenderObj(renderObj);
|
|
NNS_G3dRenderObjInit(&renderObj->g3DRenderObj, model);
|
|
}
|
|
|
|
void Simple3D_CreateRenderObject(Simple3DRenderObj *renderObj, Simple3DModel *model)
|
|
{
|
|
BindModelToRenderObj(renderObj, model->g3DModel);
|
|
}
|
|
|
|
static void BindAnimToRenderObj(Simple3DRenderObj *renderObj, NNSG3dAnmObj *anim)
|
|
{
|
|
NNS_G3dRenderObjAddAnmObj(&renderObj->g3DRenderObj, anim);
|
|
}
|
|
|
|
void Simple3D_BindAnimToRenderObj(Simple3DRenderObj *renderObj, Simple3DAnimation *anim)
|
|
{
|
|
BindAnimToRenderObj(renderObj, anim->animObj);
|
|
}
|
|
|
|
void Simple3D_CreateRenderObjectWithAnim(Simple3DRenderObj *renderObj, Simple3DModel *model, Simple3DAnimation *anim)
|
|
{
|
|
Simple3D_CreateRenderObject(renderObj, model);
|
|
Simple3D_BindAnimToRenderObj(renderObj, anim);
|
|
}
|
|
|
|
void Simple3D_DrawRenderObj(Simple3DRenderObj *renderObj, const VecFx32 *pos, const VecFx32 *scale, const MtxFx33 *rot)
|
|
{
|
|
Easy3D_DrawRenderObj(&renderObj->g3DRenderObj, pos, rot, scale);
|
|
}
|
|
|
|
void Simple3D_DrawRenderObjWithPos(Simple3DRenderObj *renderObj, const VecFx32 *pos)
|
|
{
|
|
Simple3D_DrawRenderObj(renderObj, pos, &sVecOnes, &sIdentity);
|
|
}
|
|
|
|
void Simple3D_DrawRenderObjRotationAngles(Simple3DRenderObj *renderObj, const VecFx32 *pos, const VecFx32 *scale, const Simple3DRotationAngles *rotAngles)
|
|
{
|
|
MtxFx33 rotMatrix;
|
|
|
|
MTX_Rot33Angles(&rotMatrix, rotAngles->alpha, rotAngles->beta, rotAngles->gamma);
|
|
Simple3D_DrawRenderObj(renderObj, pos, scale, &rotMatrix);
|
|
}
|
|
|
|
void Simple3D_DrawRenderObjWithPosAndRotationAngles(Simple3DRenderObj *renderObj, const VecFx32 *pos, const Simple3DRotationAngles *rotAngles)
|
|
{
|
|
MtxFx33 rotMatrix;
|
|
|
|
MTX_Rot33Angles(&rotMatrix, rotAngles->alpha, rotAngles->beta, rotAngles->gamma);
|
|
Simple3D_DrawRenderObj(renderObj, pos, &sVecOnes, &rotMatrix);
|
|
}
|
|
|
|
void Simple3D_DrawRenderObjSimple(Simple3DRenderObj *renderObj, const VecFx32 *pos, const VecFx32 *scale, const MtxFx33 *rot)
|
|
{
|
|
Easy3D_DrawRenderObjSimple(&renderObj->g3DRenderObj, pos, rot, scale);
|
|
}
|