diff --git a/configure.py b/configure.py index 6460232ba..19869c542 100644 --- a/configure.py +++ b/configure.py @@ -418,7 +418,7 @@ def MatchingFor(*versions): Object(Matching, "SB/Core/x/xCollideFast.cpp"), Object(Matching, "SB/Core/x/xColor.cpp"), Object(Matching, "SB/Core/x/xCounter.cpp"), - Object(NonMatching, "SB/Core/x/xCutscene.cpp"), + Object(NonMatching, "SB/Core/x/xCutscene.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Core/x/xDebug.cpp", extra_cflags=["-sym on"]), Object(Equivalent, "SB/Core/x/xEnt.cpp", extra_cflags=["-sym on"]), Object(Equivalent, "SB/Core/x/xEntDrive.cpp", extra_cflags=["-sym on"]), diff --git a/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath b/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath index 48173d423..70e0fd02a 100644 --- a/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath +++ b/src/PowerPC_EABI_Support/include/PowerPC_EABI_Support/MSL_C/MSL_Common/cmath @@ -9,6 +9,7 @@ namespace std #ifndef INLINE float atan2f(float y, float x); + float atan(float x); float sinf(float x); float cosf(float x); float tanf(float x); @@ -25,6 +26,11 @@ namespace std return (float)atan2((double)y, (double)x); } + inline float atan(float x) + { + return (float)atan((double)x); + } + inline float sinf(float x) { return (float)sin((double)x); diff --git a/src/SB/Core/gc/iCutscene.cpp b/src/SB/Core/gc/iCutscene.cpp index 973bf9f2e..79011b3f0 100644 --- a/src/SB/Core/gc/iCutscene.cpp +++ b/src/SB/Core/gc/iCutscene.cpp @@ -232,7 +232,7 @@ S32 iCSLoadStep(xCutscene* csn) while (csn->DataLoading < (S32)csn->Info->NumData) { - if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_JDELTAMODEL) { foundModel = NULL; } @@ -260,7 +260,7 @@ S32 iCSLoadStep(xCutscene* csn) if (csn->GotData) { - if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_6) + if (csn->Data[csn->DataLoading].DataType == XCUTSCENEDATA_TYPE_JDELTAMODEL) { csn->Data[csn->DataLoading].DataPtr = RwMalloc(csn->Data[csn->DataLoading].ChunkSize); diff --git a/src/SB/Core/x/xCamera.h b/src/SB/Core/x/xCamera.h index c12240f5e..a1e72caf3 100644 --- a/src/SB/Core/x/xCamera.h +++ b/src/SB/Core/x/xCamera.h @@ -66,6 +66,7 @@ extern RpAtomic* sInvisWallHack; extern xMat4x3 sCameraFXMatOld; extern cameraFX sCameraFX[10]; extern cameraFXTableEntry sCameraFXTable[3]; +extern F32 gCameraLastFov; struct xScene; diff --git a/src/SB/Core/x/xCutscene.cpp b/src/SB/Core/x/xCutscene.cpp index 02c6921f7..107ded1dd 100644 --- a/src/SB/Core/x/xCutscene.cpp +++ b/src/SB/Core/x/xCutscene.cpp @@ -7,6 +7,9 @@ #include "iCutscene.h" #include "iModel.h" +#include "zCamera.h" +#include "zGlobals.h" +#include "iAnim.h" #include #include @@ -144,6 +147,37 @@ S32 xCutscene_LoadStart(xCutscene* csn) return 1; } +F32 xCutsceneConvertBreak(float param_1, xCutsceneBreak* param_2, U32 param_3, int param_4) +{ + int i = 0; + if (param_3 == 0) + { + return param_1; + } + while (true) + { + if (param_4 != param_2[i].Index) + { + break; + } + if (param_2[i].Time - param_1 <= 0.0f) + { + break; + } + if (0.03333333f <= param_2[i].Time - param_1) + { + break; + } + i++; + param_3--; + if (param_3 == 0) + { + return param_1; + } + } + return param_2[i].Time - 0.03333333f; +} + S32 xCutscene_Update(xCutscene* csn, F32 dt) { if ((csn->SndStarted == FALSE) && (csn->SndNumChannel != 0)) @@ -231,7 +265,7 @@ void xCutscene_SetSpeed(xCutscene* csn, F32 speed) csn->PlaybackSpeed = speed; F32 semitones; - if (speed != 0.0f) + if (speed) { semitones = xlog(speed) / 0.057762269f; } @@ -256,42 +290,154 @@ float std::logf(float x) return (float)log((double)x); } -void xVec3Lerp(xVec3* out, const xVec3* a, const xVec3* b, float alpha) +// TODO: general pointer/index mismatching in here +// instructions and control flow should be close match though +void xCutscene_SetCamera(xCutscene* csn, xCamera* cam) { - out->x = a->x + (b->x - a->x) * alpha; - out->y = a->y + (b->y - a->y) * alpha; - out->z = a->z + (b->z - a->z) * alpha; + xCutsceneData* data = (xCutsceneData*)&csn->Play[1]; + for (U32 i = 0; i < csn->Play->NumData; i++) + { + if (data[i].DataType == XCUTSCENEDATA_TYPE_CAMERA) + { + U32 dataIndex = data[i + 1].DataType; + S32 frame = std::floorf(30.0f * csn->CamTime); + zFlyKey* keys = (zFlyKey*)((char*)&data[i] + 0x14); + + F32 lerp; + if (keys[i + 1].frame < frame) + { + lerp = 0.0f; + } + else if (keys[i].frame >= frame) + { + lerp = 1.0f; + keys += keys[i].frame - 2; + } + else + { + lerp = 30.0f * csn->CamTime - std::floorf(30.0f * csn->CamTime); + keys += keys[i].frame - frame; + } + + F32 invlerp = 1.0f - lerp; + + xMat4x3 camMat; + xMat3x3 tmpMat; + xQuat quats[2]; + for (U32 j = 0; j < 2; j++) + { + tmpMat.right.x = -keys[j].matrix[0]; + tmpMat.right.y = -keys[j].matrix[1]; + tmpMat.right.z = -keys[j].matrix[2]; + tmpMat.up.x = keys[j].matrix[3]; + tmpMat.up.y = keys[j].matrix[4]; + tmpMat.up.z = keys[j].matrix[5]; + tmpMat.at.x = -keys[j].matrix[6]; + tmpMat.at.y = -keys[j].matrix[7]; + tmpMat.at.z = -keys[j].matrix[8]; + xQuatFromMat(&quats[j], &tmpMat); + } + + xQuat qresult; + xQuatSlerp(&qresult, &quats[0], &quats[1], lerp); + xQuatToMat(&qresult, &camMat); + xVec3Lerp(&camMat.pos, (xVec3*)&keys[0].matrix[9], (xVec3*)&keys[1].matrix[9], lerp); + + U32 count; + + F32 camFOV = 114.59155f * + std::atan((12.7f * (keys[0].aperture[0] * lerp + keys[1].aperture[0] * invlerp)) / + (keys[0].focal * lerp + keys[1].focal * invlerp)); + cam->mat = camMat; + gCameraLastFov = 0.0f; + xCameraSetFOV(&xglobals->camera, camFOV); + } + } } -F32 xCutsceneConvertBreak(float param_1, xCutsceneBreak* param_2, U32 param_3, int param_4) +static void xcsCalcAnimMatrices(RwMatrixTag* animMat, RpAtomic* model, xCutsceneAnimHdr* ahdr, + F32 time, U32 tworoot) { - int i = 0; - if (param_3 == 0) - { - return param_1; - } - while (true) + xQuat quatresult[65]; + xVec3 tranresult[65]; + + void* afile = &ahdr[1]; + iAnimEval(afile, time, 0x0, tranresult, quatresult); + + if (iModelNumBones(model) != 0) { - if (param_4 != param_2[i].Index) - { - break; - } - if (param_2[i].Time - param_1 <= 0.0f) - { - break; - } - if (0.03333333f <= param_2[i].Time - param_1) + xMat4x3Identity((xMat4x3*)animMat); + animMat->pos.x = ahdr->Translate[0]; + animMat->pos.y = ahdr->Translate[1]; + animMat->pos.z = ahdr->Translate[2]; + + if (tworoot) { - break; + xMat4x3 m1; + xMat4x3 m2; + + quatresult[1].s = -quatresult[1].s; + quatresult[2].s = -quatresult[2].s; + xQuatToMat(&quatresult[1], &m1); + xQuatToMat(&quatresult[2], &m2); + + m1.pos = tranresult[1]; + m2.pos = tranresult[2]; + + xMat4x3Mul(&m1, &m2, &m1); + + tranresult[2].x = 0.0f; + tranresult[2].y = 0.0f; + tranresult[2].z = 0.0f; + quatresult[2].v.x = 0.0f; + quatresult[2].v.y = 0.0f; + quatresult[2].v.z = 0.0f; + quatresult[2].s = 1.0f; + + xQuatFromMat(&quatresult[1], &m1); + + quatresult[1].s = -quatresult[1].s; + m1.pos = tranresult[1]; } - i++; - param_3--; - if (param_3 == 0) + + U32 numbone = iModelNumBones(model); + U32 boneidx = 0; + xQuat* qqq = quatresult; + xVec3* ttt = tranresult; + while (boneidx < numbone && boneidx <= ahdr->RootIndex) { - return param_1; + animMat->pos.x += tranresult[boneidx].x; + animMat->pos.y += tranresult[boneidx].y; + animMat->pos.z += tranresult[boneidx].z; + + tranresult[boneidx].x = 0.0f; + tranresult[boneidx].y = 0.0f; + tranresult[boneidx].z = 0.0f; + + if (FABS(quatresult[boneidx].s) < 0.9999f) + { + break; + } + + boneidx++; } + + iModelAnimMatrices(model, quatresult, tranresult, &animMat[1]); + } + else + { + xQuatToMat(quatresult, (xMat4x3*)animMat); + animMat->pos.x = tranresult[0].x + ahdr->Translate[0]; + animMat->pos.y = tranresult[0].y + ahdr->Translate[1]; + animMat->pos.z = tranresult[0].z + ahdr->Translate[2]; } - return param_2[i].Time - 0.03333333f; +} + +void xVec3Lerp(xVec3* out, const xVec3* a, const xVec3* b, float alpha) +{ + out->x = a->x + (b->x - a->x) * alpha; + out->y = a->y + (b->y - a->y) * alpha; + out->z = a->z + (b->z - a->z) * alpha; } void CutsceneShadowRender(CutsceneShadowModel* smod) @@ -310,7 +456,7 @@ void CutsceneShadowRender(CutsceneShadowModel* smod) } } -void xCutscene_Render(xCutscene*, xEnt**, S32*, F32*) +void xCutscene_Render(xCutscene* csn, xEnt**, S32*, F32*) { } @@ -318,11 +464,3 @@ xCutscene* xCutscene_CurrentCutscene() { return &sActiveCutscene; } - -void XCSNNosey::CanRenderNow() -{ -} - -void XCSNNosey::UpdatedAnimated(RpAtomic*, RwMatrixTag*, U32, U32) -{ -} diff --git a/src/SB/Core/x/xCutscene.h b/src/SB/Core/x/xCutscene.h index c9f9352ad..682ac35e3 100644 --- a/src/SB/Core/x/xCutscene.h +++ b/src/SB/Core/x/xCutscene.h @@ -3,6 +3,20 @@ #include "xFile.h" #include "rpworld.h" +#include "xCamera.h" + +#define XCUTSCENEDATA_TYPE_RW_MODEL 1 +#define XCUTSCENEDATA_TYPE_ANIMATION 2 +#define XCUTSCENEDATA_TYPE_CAMERA 3 +#define XCUTSCENEDATA_TYPE_MORPHTARGET 4 +#define XCUTSCENEDATA_TYPE_SOUND 5 +#define XCUTSCENEDATA_TYPE_JDELTAMODEL 6 +#define XCUTSCENEDATA_TYPE_JDELTAANIM 7 + +struct xCutsceneAnimHdr { + U32 RootIndex; + F32 Translate[3]; +}; struct xCutsceneInfo { @@ -34,9 +48,6 @@ struct xCutsceneData }; }; -#define XCUTSCENEDATA_TYPE_SOUND 5 -#define XCUTSCENEDATA_TYPE_6 6 - struct xCutsceneBreak { F32 Time; @@ -56,8 +67,13 @@ struct XCSNNosey void* userdata; S32 flg_nosey; - void CanRenderNow(); - void UpdatedAnimated(RpAtomic*, RwMatrixTag*, U32, U32); + void CanRenderNow() + { + } + + void UpdatedAnimated(RpAtomic*, RwMatrixTag*, U32, U32) + { + } }; struct xCutscene @@ -115,6 +131,7 @@ xCutscene* xCutscene_Create(U32 id); S32 xCutscene_Destroy(xCutscene* csn); S32 xCutscene_LoadStart(xCutscene* csn); void xCutscene_SetSpeed(xCutscene* csn, F32 speed); +void xCutscene_SetCamera(xCutscene* csn, xCamera* cam); F32 xCutsceneConvertBreak(float time, xCutsceneBreak* breaklist, U32 breakcount, int idx); S32 xCutscene_Update(xCutscene* csn, F32 dt); void CutsceneShadowRender(CutsceneShadowModel* smod);