summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcoco875 <pereira.jannin@gmail.com>2025-05-25 21:52:35 +0200
committercoco875 <pereira.jannin@gmail.com>2025-05-25 21:52:35 +0200
commitc2e913a626e9a5430402a4c64007e0509a530946 (patch)
tree7b970ac12e2cd6c08667e9a9c945baae33073b43 /src
parent20f7601e8d1d747745c816399c8e492c8dcd2736 (diff)
fix player particle interpolation
Diffstat (limited to 'src')
-rw-r--r--src/code_80057C60.c59
-rw-r--r--src/port/Engine.cpp72
-rw-r--r--src/racing/skybox_and_splitscreen.c9
3 files changed, 64 insertions, 76 deletions
diff --git a/src/code_80057C60.c b/src/code_80057C60.c
index 2ce053cac..3a9e65b8e 100644
--- a/src/code_80057C60.c
+++ b/src/code_80057C60.c
@@ -2596,8 +2596,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) {
case 1: /* switch 1 */
CM_ActivateSecondLapLakitu(playerId); // func_80079084(playerId);
func_800C9060(playerId, SOUND_ARG_LOAD(0x19, 0x00, 0xF0, 0x15));
- if ((IsLuigiRaceway()) && (D_80165898 == 0) &&
- (gModeSelection != (s32) TIME_TRIALS)) {
+ if ((IsLuigiRaceway()) && (D_80165898 == 0) && (gModeSelection != (s32) TIME_TRIALS)) {
D_80165898 = 1;
}
break;
@@ -4974,10 +4973,8 @@ void func_800651F4(Player* player, UNUSED s8 arg1, UNUSED s8 arg2, s8 arg3) {
}
}
-s32 D_func_800652D4_counter = 0;
void func_800652D4(Vec3f arg0, Vec3s arg1, f32 arg2) {
Mat4 mtx;
- FrameInterpolation_RecordOpenChild("some_thing", D_func_800652D4_counter++ << 8);
mtxf_translate_rotate(mtx, arg0, arg1);
mtxf_scale(mtx, arg2);
// convert_to_fixed_point_matrix(&gGfxPool->mtxEffect[gMatrixEffectCount], mtx);
@@ -4985,7 +4982,6 @@ void func_800652D4(Vec3f arg0, Vec3s arg1, f32 arg2) {
// G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
AddEffectMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- FrameInterpolation_RecordCloseChild();
}
void func_8006538C(Player* player, s8 arg1, s16 arg2, s8 arg3) {
@@ -5110,7 +5106,6 @@ void func_80065AB0(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3) {
spAC[2] = 0;
// // @port: Tag the transform.
- FrameInterpolation_RecordOpenChild("EEEEEEEEE", player->type << 8 | arg2 | var_s0 << 16);
// @port Skip interpolation
// FrameInterpolation_ShouldInterpolateFrame(false);
@@ -5136,7 +5131,6 @@ void func_80065AB0(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3) {
gMatrixEffectCount += 1;
// @port Pop the transform id.
- FrameInterpolation_RecordCloseChild();
// @port renable interpolation
// FrameInterpolation_ShouldInterpolateFrame(true);
}
@@ -5691,7 +5685,6 @@ void func_800691B8(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3) {
sp54[2] = player->unk_258[30 + arg2].unk_03A;
// @port: Tag the transform.
- FrameInterpolation_RecordOpenChild("func_800691B8", TAG_OBJECT(arg2));
func_800652D4(sp5C, sp54, player->size * 0.5);
gSPDisplayList(gDisplayListHead++, D_0D008D58);
@@ -5706,7 +5699,6 @@ void func_800691B8(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3) {
gMatrixEffectCount++;
// @port Pop the transform id.
- FrameInterpolation_RecordCloseChild();
}
}
@@ -5768,7 +5760,6 @@ void func_800696CC(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3, f32 arg4)
sp54[2] = 0;
// @port: Tag the transform.
- FrameInterpolation_RecordOpenChild("func_800696CC", TAG_OBJECT(arg2));
func_800652D4(sp5C, sp54, player->size * arg4);
gSPDisplayList(gDisplayListHead++, D_0D008D58);
@@ -5783,7 +5774,6 @@ void func_800696CC(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3, f32 arg4)
gMatrixEffectCount += 1;
// @port Pop the transform id.
- FrameInterpolation_RecordCloseChild();
}
}
@@ -5801,9 +5791,6 @@ void func_80069938(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3) {
sp54[1] = player->unk_048[arg3];
sp54[2] = player->unk_258[30 + arg2].unk_038;
- // @port: Tag the transform.
- FrameInterpolation_RecordOpenChild("func_80069938", TAG_OBJECT(arg2));
-
func_800652D4(sp5C, sp54, player->unk_258[30 + arg2].unk_00C * player->size);
gSPDisplayList(gDisplayListHead++, D_0D008D58);
gDPSetTextureLUT(gDisplayListHead++, G_TT_NONE);
@@ -5817,7 +5804,6 @@ void func_80069938(Player* player, UNUSED s8 arg1, s16 arg2, s8 arg3) {
gMatrixEffectCount += 1;
// @port Pop the transform id.
- FrameInterpolation_RecordCloseChild();
}
}
@@ -6618,8 +6604,7 @@ void func_8006D474(Player* player, s8 playerId, s8 screenId) {
if ((player->unk_002 & (8 << (screenId * 4))) == (8 << (screenId * 4))) {
for (var_s2 = 0; var_s2 < 10; var_s2++) {
// @port: Tag the transform.
- FrameInterpolation_RecordOpenChild(
- "SmokeDust", TAG_SMOKE_DUST(((u32) player->unk_258[var_s2].unk_012 << 8) + (playerId << 16) + var_s2));
+ FrameInterpolation_RecordOpenChild("SmokeDust", TAG_SMOKE_DUST((playerId << 8) + var_s2));
switch (player->unk_258[var_s2].unk_012) {
case 1:
@@ -6641,6 +6626,8 @@ void func_8006D474(Player* player, s8 playerId, s8 screenId) {
}
break;
}
+ FrameInterpolation_RecordCloseChild();
+ FrameInterpolation_RecordOpenChild("SmokeDust", TAG_SMOKE_DUST((playerId << 8) + var_s2 + 30));
switch (player->unk_258[var_s2 + 30].unk_012) {
case 1:
case 9:
@@ -6700,6 +6687,8 @@ void func_8006D474(Player* player, s8 playerId, s8 screenId) {
}
break;
}
+ FrameInterpolation_RecordCloseChild();
+ FrameInterpolation_RecordOpenChild("SmokeDust", TAG_SMOKE_DUST((playerId << 8) + var_s2 + 10));
switch (player->unk_258[var_s2 + 10].unk_012) {
case 1:
if (gActiveScreenMode == SCREEN_MODE_3P_4P_SPLITSCREEN) {
@@ -6764,48 +6753,50 @@ void func_8006DC54(Player* player, s8 arg1, s8 arg2) {
}
}
-void func_8006DD3C(Player* arg0, s8 arg1, s8 arg2) {
+void func_8006DD3C(Player* player, s8 playerId, s8 arg2) {
s16 temp_s0;
s32 temp_v0;
temp_v0 = 8 << (arg2 * 4);
- if (temp_v0 == (arg0->unk_002 & temp_v0)) {
+ if (temp_v0 == (player->unk_002 & temp_v0)) {
for (temp_s0 = 0; temp_s0 < 10; ++temp_s0) {
- temp_v0 = arg0->unk_258[temp_s0].unk_012;
+ temp_v0 = player->unk_258[temp_s0].unk_012;
if (temp_v0 != 3) {
if (temp_v0 == 5) {
- func_8006A280(arg0, arg1, temp_s0, arg2);
+ func_8006A280(player, playerId, temp_s0, arg2);
}
} else if (gActiveScreenMode == SCREEN_MODE_3P_4P_SPLITSCREEN) {
- if (arg2 == arg1) {
- func_80066998(arg0, arg1, temp_s0, arg2);
+ if (arg2 == playerId) {
+ func_80066998(player, playerId, temp_s0, arg2);
}
} else {
- func_80066998(arg0, arg1, temp_s0, arg2);
+ func_80066998(player, playerId, temp_s0, arg2);
}
}
- if (((arg0->type & 0x4000) == 0x4000) && (arg2 == arg1)) {
- switch (arg0->unk_258[20].unk_012) {
+ if (((player->type & 0x4000) == 0x4000) && (arg2 == playerId)) {
+ FrameInterpolation_RecordOpenChild("onomatopoeia", TAG_SMOKE_DUST((playerId << 8) + 20));
+ switch (player->unk_258[20].unk_012) {
case 2:
- func_80068310(arg0, arg1, arg0->unk_258[20].unk_00C, arg2, 0);
+ func_80068310(player, playerId, player->unk_258[20].unk_00C, arg2, 0);
break;
case 3:
- func_80067964(arg0, arg1, arg0->unk_258[20].unk_00C, arg2, 0);
+ func_80067964(player, playerId, player->unk_258[20].unk_00C, arg2, 0);
break;
case 4:
- func_80068724(arg0, arg1, arg0->unk_258[20].unk_00C, arg2, 0);
+ func_80068724(player, playerId, player->unk_258[20].unk_00C, arg2, 0);
break;
case 5:
- func_80068AA4(arg0, arg1, arg0->unk_258[20].unk_00C, arg2, 0);
+ func_80068AA4(player, playerId, player->unk_258[20].unk_00C, arg2, 0);
break;
case 6:
- func_80068DA0(arg0, arg1, arg0->unk_258[20].unk_00C, arg2, 0);
+ func_80068DA0(player, playerId, player->unk_258[20].unk_00C, arg2, 0);
break;
}
- if (arg0->unk_258[21].unk_012 == 5) {
- func_80067D3C(arg0, arg2, D_8018D480, 1, 1.6f, 0xFFFFFF);
- func_8006801C(arg0, arg2, D_8018D484, 1, 1.6f, 0xFF);
+ FrameInterpolation_RecordCloseChild();
+ if (player->unk_258[21].unk_012 == 5) {
+ func_80067D3C(player, arg2, D_8018D480, 1, 1.6f, 0xFFFFFF);
+ func_8006801C(player, arg2, D_8018D484, 1, 1.6f, 0xFF);
}
}
}
diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp
index 70ea4054c..7b6246a42 100644
--- a/src/port/Engine.cpp
+++ b/src/port/Engine.cpp
@@ -27,7 +27,7 @@
#include "port/interpolation/FrameInterpolation.h"
#include <graphic/Fast3D/Fast3dWindow.h>
#include <graphic/Fast3D/interpreter.h>
-//#include <Fast3D/gfx_rendering_api.h>
+// #include <Fast3D/gfx_rendering_api.h>
#include <SDL2/SDL.h>
#include <utility>
@@ -52,9 +52,9 @@ float gInterpolationStep = 0.0f;
Fast::Interpreter* GetInterpreter() {
return static_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow())
- ->GetInterpreterWeak()
- .lock()
- .get();
+ ->GetInterpreterWeak()
+ .lock()
+ .get();
}
GameEngine* GameEngine::Instance;
@@ -63,7 +63,7 @@ GameEngine::GameEngine() {
const std::string main_path = Ship::Context::GetPathRelativeToAppDirectory("mk64.o2r");
const std::string assets_path = Ship::Context::LocateFileAcrossAppDirs("spaghetti.o2r");
-
+
std::vector<std::string> archiveFiles;
#ifdef __SWITCH__
@@ -71,7 +71,6 @@ GameEngine::GameEngine() {
Ship::Switch::Init(Ship::PostInitPhase);
#endif
-
#ifdef _WIN32
AllocConsole();
#endif
@@ -80,7 +79,7 @@ GameEngine::GameEngine() {
archiveFiles.push_back(main_path);
} else {
if (ShowYesNoBox("No O2R Files", "No O2R files found. Generate one now?") == IDYES) {
- if(!GenAssetFile()){
+ if (!GenAssetFile()) {
ShowMessage("Error", "An error occured, no O2R file was generated.\n\nExiting...");
exit(1);
} else {
@@ -107,11 +106,11 @@ GameEngine::GameEngine() {
}
}
- this->context =
- Ship::Context::CreateUninitializedInstance("Spaghetti Kart", "spaghettify", "spaghettify.cfg.json");
+ this->context = Ship::Context::CreateUninitializedInstance("Spaghetti Kart", "spaghettify", "spaghettify.cfg.json");
- this->context->InitConfiguration(); // without this line InitConsoleVariables fails at Config::Reload()
- this->context->InitConsoleVariables(); // without this line the controldeck constructor failes in ShipDeviceIndexMappingManager::UpdateControllerNamesFromConfig()
+ this->context->InitConfiguration(); // without this line InitConsoleVariables fails at Config::Reload()
+ this->context->InitConsoleVariables(); // without this line the controldeck constructor failes in
+ // ShipDeviceIndexMappingManager::UpdateControllerNamesFromConfig()
auto controlDeck = std::make_shared<LUS::ControlDeck>();
@@ -121,8 +120,8 @@ GameEngine::GameEngine() {
auto gui = std::make_shared<Ship::SpaghettiGui>(std::vector<std::shared_ptr<Ship::GuiWindow>>({}));
auto wnd = std::make_shared<Fast::Fast3dWindow>(gui);
- //auto wnd = std::make_shared<Fast::Fast3dWindow>(std::vector<std::shared_ptr<Ship::GuiWindow>>({}));
- //auto wnd = std::dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
+ // auto wnd = std::make_shared<Fast::Fast3dWindow>(std::vector<std::shared_ptr<Ship::GuiWindow>>({}));
+ // auto wnd = std::dynamic_pointer_cast<Fast::Fast3dWindow>(Ship::Context::GetInstance()->GetWindow());
this->context->Init(archiveFiles, {}, 3, { 26800, 512, 1100 }, wnd, controlDeck);
@@ -159,8 +158,9 @@ GameEngine::GameEngine() {
loader->RegisterResourceFactory(std::make_shared<Fast::ResourceFactoryXMLVertexV0>(), RESOURCE_FORMAT_XML, "Vertex",
static_cast<uint32_t>(Fast::ResourceType::Vertex), 0);
- loader->RegisterResourceFactory(std::make_shared<Fast::ResourceFactoryBinaryDisplayListV0>(), RESOURCE_FORMAT_BINARY,
- "DisplayList", static_cast<uint32_t>(Fast::ResourceType::DisplayList), 0);
+ loader->RegisterResourceFactory(std::make_shared<Fast::ResourceFactoryBinaryDisplayListV0>(),
+ RESOURCE_FORMAT_BINARY, "DisplayList",
+ static_cast<uint32_t>(Fast::ResourceType::DisplayList), 0);
loader->RegisterResourceFactory(std::make_shared<Fast::ResourceFactoryXMLDisplayListV0>(), RESOURCE_FORMAT_XML,
"DisplayList", static_cast<uint32_t>(Fast::ResourceType::DisplayList), 0);
@@ -179,24 +179,21 @@ GameEngine::GameEngine() {
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryTrackSectionsV0>(),
RESOURCE_FORMAT_BINARY, "TrackSections",
static_cast<uint32_t>(MK64::ResourceType::TrackSection), 0);
- loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryXMLTrackSectionsV0>(),
- RESOURCE_FORMAT_XML, "TrackSections",
- static_cast<uint32_t>(MK64::ResourceType::TrackSection), 0);
+ loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryXMLTrackSectionsV0>(), RESOURCE_FORMAT_XML,
+ "TrackSections", static_cast<uint32_t>(MK64::ResourceType::TrackSection), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryTrackWaypointsV0>(),
RESOURCE_FORMAT_BINARY, "Waypoints",
static_cast<uint32_t>(MK64::ResourceType::Waypoints), 0);
- loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryXMLTrackWaypointsV0>(),
- RESOURCE_FORMAT_XML, "Paths",
- static_cast<uint32_t>(MK64::ResourceType::Waypoints), 0);
+ loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryXMLTrackWaypointsV0>(), RESOURCE_FORMAT_XML,
+ "Paths", static_cast<uint32_t>(MK64::ResourceType::Waypoints), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryActorSpawnDataV0>(),
RESOURCE_FORMAT_BINARY, "SpawnData",
static_cast<uint32_t>(MK64::ResourceType::SpawnData), 0);
loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryUnkActorSpawnDataV0>(),
RESOURCE_FORMAT_BINARY, "UnkSpawnData",
static_cast<uint32_t>(MK64::ResourceType::UnkSpawnData), 0);
- loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryMinimapV0>(),
- RESOURCE_FORMAT_BINARY, "Minimap",
- static_cast<uint32_t>(MK64::ResourceType::Minimap), 0);
+ loader->RegisterResourceFactory(std::make_shared<MK64::ResourceFactoryBinaryMinimapV0>(), RESOURCE_FORMAT_BINARY,
+ "Minimap", static_cast<uint32_t>(MK64::ResourceType::Minimap), 0);
fontMono = CreateFontWithSize(16.0f, "fonts/Inconsolata-Regular.ttf");
fontMonoLarger = CreateFontWithSize(20.0f, "fonts/Inconsolata-Regular.ttf");
@@ -217,11 +214,13 @@ bool GameEngine::GenAssetFile() {
auto game = extractor->ValidateChecksum();
if (!game.has_value()) {
- ShowMessage("Unsupported ROM", "The provided ROM is not supported.\n\nCheck the readme for a list of supported versions.");
+ ShowMessage("Unsupported ROM",
+ "The provided ROM is not supported.\n\nCheck the readme for a list of supported versions.");
exit(1);
}
- ShowMessage(("Found " + game.value()).c_str(), "The extraction process will now begin.\n\nThis may take a few minutes.", SDL_MESSAGEBOX_INFORMATION);
+ ShowMessage(("Found " + game.value()).c_str(),
+ "The extraction process will now begin.\n\nThis may take a few minutes.", SDL_MESSAGEBOX_INFORMATION);
return extractor->GenerateOTR();
}
@@ -239,13 +238,12 @@ uint32_t GameEngine::GetInterpolationFPS() {
return CVarGetInteger("gInterpolationFPS", 30);
}
-uint32_t GameEngine::GetInterpolationFrameCount()
-{
- return ceil((float)GetInterpolationFPS() / (60.0f / 2 /*gVIsPerFrame*/));
+uint32_t GameEngine::GetInterpolationFrameCount() {
+ return ceil((float) GetInterpolationFPS() / (60.0f / 2 /*gVIsPerFrame*/));
}
extern "C" uint32_t GameEngine_GetInterpolationFrameCount() {
- return GameEngine::GetInterpolationFrameCount();
+ return GameEngine::GetInterpolationFrameCount();
}
void GameEngine::ShowMessage(const char* title, const char* message, SDL_MessageBoxFlags type) {
@@ -356,7 +354,7 @@ void GameEngine::RunCommands(Gfx* Commands, const std::vector<std::unordered_map
void GameEngine::ProcessGfxCommands(Gfx* commands) {
std::vector<std::unordered_map<Mtx*, MtxF>> mtx_replacements;
- int target_fps = GameEngine::Instance->GetInterpolationFPS();
+ int target_fps = 200; // GameEngine::Instance->GetInterpolationFPS();
static int last_fps;
static int last_update_rate;
static int time;
@@ -382,7 +380,7 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) {
mtx_replacements.emplace_back();
}
}
- // printf("mtxf size: %d\n", mtx_replacements.size());
+ // printf("mtxf size: %d\n", mtx_replacements.size());
time -= fps;
@@ -512,7 +510,7 @@ ImFont* GameEngine::CreateFontWithSize(float size, std::string fontPath) {
initData->Path = fontPath;
std::shared_ptr<Ship::Font> fontData = std::static_pointer_cast<Ship::Font>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResource(fontPath, false, initData));
- char* fontDataPtr = (char*)malloc(fontData->DataSize);
+ char* fontDataPtr = (char*) malloc(fontData->DataSize);
memcpy(fontDataPtr, fontData->Data, fontData->DataSize);
font = mImGuiIo->Fonts->AddFontFromMemoryTTF(fontDataPtr, fontData->DataSize, size);
}
@@ -705,14 +703,14 @@ extern "C" int16_t OTRGetRectDimensionFromRightEdge(float v) {
/**
* Centers an item in a given area.
- *
+ *
* Adds the number of extended screen pixels to the location to center.
* This allows stretching the game window really wide, and the item will stay in-place.
- *
+ *
* This is not for centering in the direct center of the screen.
- *
+ *
* How to use:
- *
+ *
* s32 center = OTRCalculateCenterOfAreaFromRightEdge((SCREEN_WIDTH / 4) + (SCREEN_WIDTH / 2));
* x = center - (texWidth / 2)
* x2 = center + (texWidth / 2)
diff --git a/src/racing/skybox_and_splitscreen.c b/src/racing/skybox_and_splitscreen.c
index 62399dfea..edbe545c8 100644
--- a/src/racing/skybox_and_splitscreen.c
+++ b/src/racing/skybox_and_splitscreen.c
@@ -767,7 +767,8 @@ void setup_camera(Camera* camera, s32 playerId, s32 cameraId, struct UnkStruct_8
}
// Setup perspective (camera movement)
- FrameInterpolation_RecordOpenChild("camera", (FrameInterpolation_GetCameraEpoch() | (((playerId | cameraId) << 8))));
+ FrameInterpolation_RecordOpenChild("camera",
+ (FrameInterpolation_GetCameraEpoch() | (((playerId | cameraId) << 8))));
guPerspective(&gGfxPool->mtxPersp[cameraId], &perspNorm, gCameraZoom[cameraId], gScreenAspect,
CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
@@ -776,19 +777,17 @@ void setup_camera(Camera* camera, s32 playerId, s32 cameraId, struct UnkStruct_8
// Setup lookAt (camera rotation)
guLookAt(&gGfxPool->mtxLookAt[cameraId], camera->pos[0], camera->pos[1], camera->pos[2], camera->lookAt[0],
- camera->lookAt[1], camera->lookAt[2], camera->up[0], camera->up[1], camera->up[2]);
+ camera->lookAt[1], camera->lookAt[2], camera->up[0], camera->up[1], camera->up[2]);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxLookAt[cameraId]),
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
FrameInterpolation_RecordCloseChild();
}
-extern s32 D_func_800652D4_counter;
void render_screens(s32 mode, s32 cameraId, s32 playerId) {
Mat4 matrix;
s32 screenId = 0;
s32 screenMode = SCREEN_MODE_1P;
-D_func_800652D4_counter = 0;
switch (mode) {
case RENDER_SCREEN_MODE_1P_PLAYER_ONE:
@@ -867,7 +866,7 @@ D_func_800652D4_counter = 0;
// Setup camera perspective and lookAt
setup_camera(camera, playerId, cameraId, screen);
-
+
// Create a matrix for the track and game objects
FrameInterpolation_RecordOpenChild("track", (playerId | cameraId) << 8);
Mat4 trackMatrix;