diff --git a/assets/tracks/harbour/data_track_sections b/assets/tracks/harbour/data_track_sections index 8107bc681f..4ab7b7d8b7 100644 --- a/assets/tracks/harbour/data_track_sections +++ b/assets/tracks/harbour/data_track_sections @@ -1,120 +1,12 @@ -
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
- -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- \ No newline at end of file diff --git a/src/ending/code_80280000.c b/src/ending/code_80280000.c index 467bf62bdd..134083225e 100644 --- a/src/ending/code_80280000.c +++ b/src/ending/code_80280000.c @@ -34,7 +34,7 @@ s32 D_802874A0; // s32 D_802874A4[5]; void func_80280000(void) { - func_802966A0(); + CM_TickTrack(); func_80059AC8(); func_80059AC8(); func_8005A070(); diff --git a/src/engine/CoreMath.h b/src/engine/CoreMath.h index 60cf67e5ab..59f4bd83ba 100644 --- a/src/engine/CoreMath.h +++ b/src/engine/CoreMath.h @@ -73,6 +73,10 @@ struct FVector { return FVector(0, 0, 0); } + float Square() const { + return x * x + y * y + z * z; + } + FVector() : x(0), y(0), z(0) {} FVector(float x, float y, float z) : x(x), y(y), z(z) {} NLOHMANN_DEFINE_TYPE_INTRUSIVE(FVector, x, y, z) diff --git a/src/engine/HM_Intro.cpp b/src/engine/HM_Intro.cpp index e5fd4e03be..5158d32eb0 100644 --- a/src/engine/HM_Intro.cpp +++ b/src/engine/HM_Intro.cpp @@ -91,7 +91,7 @@ void HarbourMastersIntro::HM_TickIntro() { } find_and_set_tile_size((uintptr_t) ((void*)mat_water_water1), 0, _water); - find_and_set_tile_size((uintptr_t) ((void*)mat_water_water2), _water, 0);; + find_and_set_tile_size((uintptr_t) ((void*)mat_water_water2), _water, 0); } void HarbourMastersIntro::Bob(FVector& pos, IRotator& rot, f32 bobAmp, f32 bobSpeed, f32 tiltAmp, f32 tiltSpeed, f32 rollAmp, f32 rollSpeed) { diff --git a/src/engine/TrackBrowser.cpp b/src/engine/TrackBrowser.cpp index 184b416b1e..7d7b958c85 100644 --- a/src/engine/TrackBrowser.cpp +++ b/src/engine/TrackBrowser.cpp @@ -1,6 +1,7 @@ #include "TrackBrowser.h" #include "port/Engine.h" #include "engine/editor/SceneManager.h" +#include "engine/tracks/CustomTrack.h" #include TrackBrowser* TrackBrowser::Instance; @@ -32,7 +33,7 @@ void TrackBrowser::FindCustomTracks() { } printf("[TrackBrowser] Added custom track %s\n", info.Name.c_str()); gTrackRegistry.Add(info, [info, archive]() { - auto track = std::make_unique(); + auto track = std::make_unique(); track->ResourceName = info.ResourceName; track->Archive = archive; GetWorld()->SetCurrentTrack(std::move(track)); @@ -55,7 +56,7 @@ void TrackBrowser::FindCustomTracks() { // Create the track auto archive = manager->GetArchiveFromFile(file); - auto track = std::make_unique(); + auto track = std::make_unique(); track->Archive = archive; track->ResourceName = info.ResourceName; TrackEditor::SaveLevel(track.get(), static_cast(&info)); // Write scene file so it will show up in the track browser @@ -63,7 +64,7 @@ void TrackBrowser::FindCustomTracks() { // Passing these through seems kinda bad. But it works? gTrackRegistry.Add(info, [info, archive]() { - auto track = std::make_unique(); + auto track = std::make_unique(); track->Archive = archive; track->ResourceName = info.ResourceName; GetWorld()->SetCurrentTrack(std::move(track)); diff --git a/src/engine/editor/SceneManager.cpp b/src/engine/editor/SceneManager.cpp index 02951e3dc8..af1b1cc2bf 100644 --- a/src/engine/editor/SceneManager.cpp +++ b/src/engine/editor/SceneManager.cpp @@ -341,7 +341,7 @@ namespace TrackEditor { } void LoadPaths(Track* track, const std::string& trackPath) { - SPDLOG_INFO("[SceneManager] [LoadPaths] Loading Paths..."); + SPDLOG_INFO(" Loading Paths..."); std::string path_file = (trackPath + "/data_paths").c_str(); auto res = std::dynamic_pointer_cast(ResourceLoad(path_file.c_str())); @@ -352,23 +352,33 @@ namespace TrackEditor { SPDLOG_ERROR(" In blender you may need to apply transformations and then move the point to 0,0,0"); } - auto& paths = res->PathList; + auto& pathObjs = res->PathObject; - size_t i = 0; + std::unordered_set addedPathIndexes; u16* ptr = &track->Props.PathSizes.unk0; - for (auto& path : paths) { - if (i >= ARRAY_COUNT(track->Props.PathTable2)) { - SPDLOG_INFO(" The game can only import 5 paths. Found more than 5. Skipping the rest"); - break; // Only 5 paths allowed. 4 track, 1 vehicle + for (auto& obj : pathObjs) { + int32_t pathIndex = obj.PathIndex; + if (pathIndex >= 5) { + SPDLOG_INFO(" Path index too high, cannot add path {}", pathIndex + 1); + continue; } - ptr[i] = path.size(); - track->Props.PathTable2[i] = (TrackPathPoint*) path.data(); - SPDLOG_INFO(" Added path {}", i); + if (addedPathIndexes.find(pathIndex) != addedPathIndexes.end()) { + SPDLOG_INFO(" Already added path {}, skipping", pathIndex + 1); + continue; + } + + ptr[pathIndex] = obj.PathList.size(); + track->Props.PathTable2[pathIndex] = (TrackPathPoint*) obj.PathList.data(); + addedPathIndexes.insert(pathIndex); // Mark this path as added + SPDLOG_INFO(" Added path {} with {} points", pathIndex + 1, ptr[pathIndex]); + } - i += 1; + if (nullptr == track->Props.PathTable2[0]) { + SPDLOG_INFO("\n The first track path is not set! Make sure your main path is exported with path type 1\n"); } - gVehiclePathSize = track->Props.PathSizes.unk0; // This is likely incorrect. - SPDLOG_INFO("[SceneManager] [LoadPaths] Path Loading Complete!"); + + gVehiclePathSize = track->Props.PathSizes.unk8; // This is likely incorrect. + SPDLOG_INFO(" Path Loading Complete!"); } void LoadTrackInfoData(TrackInfo& info, nlohmann::json& data) { diff --git a/src/engine/tracks/BansheeBoardwalk.cpp b/src/engine/tracks/BansheeBoardwalk.cpp index 4614f68527..67a5f5e5d1 100644 --- a/src/engine/tracks/BansheeBoardwalk.cpp +++ b/src/engine/tracks/BansheeBoardwalk.cpp @@ -307,7 +307,7 @@ void BansheeBoardwalk::DrawCredits() { gSPDisplayList(gDisplayListHead++, (Gfx*) (d_course_banshee_boardwalk_dl_B308)); } -void BansheeBoardwalk::ScrollingTextures() { +void BansheeBoardwalk::Tick() { D_802B87BC++; if (D_802B87BC >= 0x100) { @@ -328,7 +328,7 @@ void BansheeBoardwalk::Waypoints(Player* player, int8_t playerId) { } } -void BansheeBoardwalk::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, +void BansheeBoardwalk::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { gDPPipeSync(gDisplayListHead++); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); diff --git a/src/engine/tracks/BansheeBoardwalk.h b/src/engine/tracks/BansheeBoardwalk.h index 2b13ddf243..90de15c3d8 100644 --- a/src/engine/tracks/BansheeBoardwalk.h +++ b/src/engine/tracks/BansheeBoardwalk.h @@ -34,9 +34,9 @@ class BansheeBoardwalk : public Track { virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override; virtual void Draw(ScreenContext*) override; virtual void DrawCredits() override; - virtual void ScrollingTextures() override; + virtual void Tick() override; virtual void Waypoints(Player*, int8_t) override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; virtual void CreditsSpawnActors() override; virtual void Destroy() override; }; diff --git a/src/engine/tracks/BowsersCastle.cpp b/src/engine/tracks/BowsersCastle.cpp index 8a5fdf39aa..4317840206 100644 --- a/src/engine/tracks/BowsersCastle.cpp +++ b/src/engine/tracks/BowsersCastle.cpp @@ -304,7 +304,7 @@ void BowsersCastle::Waypoints(Player* player, int8_t playerId) { } } -void BowsersCastle::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, +void BowsersCastle::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { if (gActiveScreenMode != SCREEN_MODE_1P) { return; diff --git a/src/engine/tracks/BowsersCastle.h b/src/engine/tracks/BowsersCastle.h index 1bcb3cbe12..f12ed3b392 100644 --- a/src/engine/tracks/BowsersCastle.h +++ b/src/engine/tracks/BowsersCastle.h @@ -37,7 +37,7 @@ class BowsersCastle : public Track { virtual void DrawCredits() override; virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void Waypoints(Player*, int8_t) override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection); + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection); virtual void CreditsSpawnActors() override; virtual void Destroy() override; }; diff --git a/src/engine/tracks/CustomTrack.cpp b/src/engine/tracks/CustomTrack.cpp new file mode 100644 index 0000000000..76fe21afec --- /dev/null +++ b/src/engine/tracks/CustomTrack.cpp @@ -0,0 +1,306 @@ +#include "CustomTrack.h" +#include "Track.h" + +#include +#include "libultraship/bridge/resourcebridge.h" +#include "align_asset_macro.h" +#include +#include +#include +#include + +#include "engine/Matrix.h" +#include "engine/editor/SceneManager.h" + +extern "C" { +#include "collision.h" +#include "render_courses.h" +#include "actors.h" +#include "math_util.h" +} + +CustomTrack::CustomTrack() { + Props.SetText(Props.Name, "Blank Track", sizeof(Props.Name)); + Props.SetText(Props.DebugName, "blnktrck", sizeof(Props.DebugName)); + Props.SetText(Props.TrackLength, "100m", sizeof(Props.TrackLength)); + ResourceName = "mod:blank_track"; + Props.Minimap.Texture = minimap_mario_raceway; + Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture); + Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture); + Props.Minimap.Pos[0].X = 257; + Props.Minimap.Pos[0].Y = 170; + Props.Minimap.PlayerX = 0; + Props.Minimap.PlayerY = 0; + Props.Minimap.PlayerScaleFactor = 0.22f; + Props.Minimap.FinishlineX = 0; + Props.Minimap.FinishlineY = 0; + Props.Minimap.Colour = { 255, 255, 255 }; + + Props.WaterLevel = FLT_MAX; + + Props.LakituTowType = (s32) OLakitu::LakituTowType::NORMAL; + Props.AIBehaviour = D_0D008F28; + Props.AIMaximumSeparation = 50.0f; + Props.AIMinimumSeparation = 0.3f; + Props.AIDistance = gMarioRacewayAIDistances; + Props.AISteeringSensitivity = 48; + + Props.NearPersp = 3.0f; + Props.FarPersp = 6800.0f; + + Props.PathSizes = { 600, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 }; + + Props.CurveTargetSpeed[0] = 4.1666665f; + Props.CurveTargetSpeed[1] = 5.5833334f; + Props.CurveTargetSpeed[2] = 6.1666665f; + Props.CurveTargetSpeed[3] = 6.75f; + + Props.NormalTargetSpeed[0] = 3.75f; + Props.NormalTargetSpeed[1] = 5.1666665f; + Props.NormalTargetSpeed[2] = 5.75f; + Props.NormalTargetSpeed[3] = 6.3333334f; + + Props.D_0D0096B8[0] = 3.3333332f; + Props.D_0D0096B8[1] = 3.9166667f; + Props.D_0D0096B8[2] = 4.5f; + Props.D_0D0096B8[3] = 5.0833334f; + + Props.OffTrackTargetSpeed[0] = 3.75f; + Props.OffTrackTargetSpeed[1] = 5.1666665f; + Props.OffTrackTargetSpeed[2] = 5.75f; + Props.OffTrackTargetSpeed[3] = 6.3333334f; + + Props.PathTable[0] = NULL; + Props.PathTable[1] = NULL; + Props.PathTable[2] = NULL; + Props.PathTable[3] = NULL; + + Props.PathTable2[0] = NULL; + Props.PathTable2[1] = NULL; + Props.PathTable2[2] = NULL; + Props.PathTable2[3] = NULL; + Props.PathTable2[4] = NULL; + + Props.Clouds = NULL; + Props.CloudList = NULL; + Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN; + + bFog = false; + gFogColour.r = 0; + gFogColour.g = 0; + gFogColour.b = 0; + gFogColour.a = 255; + gFogMin = 995; + gFogMax = 1000; +} + +void CustomTrack::Load() { + /** Get TrackInfo **/ + printf("[CustomTrack] Loading... %s\n", ResourceName.c_str()); + const TrackInfo* info = gTrackRegistry.GetInfo(ResourceName); + if (nullptr == info) { + printf("[CustomTrack] Could not find TrackInfo for %s\n", ResourceName.c_str()); + return; + } + + /** Get Directory to Track files **/ + const std::string& path = info->Path; + if (path.empty()) { + printf("[CustomTrack] No track path\n"); + return; + } + + /** Get Props, Minimap, Actors, Environment settings from scene.json **/ + TrackEditor::LoadTrackDataFromJson(this, path); + + /** Get Track Mesh **/ + const std::string meshPath = (path + "/data_track_sections"); + + TrackSections* meshData = (TrackSections*) LOAD_ASSET_RAW(meshPath.c_str()); + if (!meshData) { + printf("[CustomTrack] No valid mesh found!\n"); + return; + } + + size_t numMesh = ( ResourceGetSizeByName(meshPath.c_str()) / sizeof(TrackSections) ); + + /** Iterate over meshes **/ + for (size_t i = 0; i < numMesh; i++) { + if (gIsMirrorMode != 0) { + CustomTrack::InvertTriangleWindingModdedByName(ResourceGetNameByCrc(meshData[i].crc)); + } + + /** Sort meshes into DrawLayer queues **/ + switch (static_cast(meshData[i].layer)) { + case DrawLayer::DRAW_INVISIBLE: + break; + default: + case DrawLayer::DRAW_OPAQUE: + mOpaqueItems.push_back(meshData[i].crc); + break; + case DrawLayer::DRAW_TRANSLUCENT: + mTranslucentItems.push_back(meshData[i]); + break; + case DrawLayer::DRAW_TRANSLUCENT_NO_ZBUFFER: + mTranslucentNoZBufferItems.push_back(meshData[i]); + break; + } + } + + Track::Init(); // Base class + + /** Generate Collision Mesh **/ + CustomTrack::ParseMeshForCollision(meshData, numMesh); + func_80295C6C(); // generate collision grid + + /** Dumb hack that needs to be removed **/ + if (Props.WaterLevel == FLT_MAX) { + Props.WaterLevel = gTrackMinY - 10.0f; + } +} + +void CustomTrack::InvertTriangleWindingModdedByName(const char* name) { + if (name == nullptr) { + return; + } + Gfx* gfx = (Gfx*)ResourceGetDataByName(name); + InvertTriangleWindingModdedInternal(gfx, name); +} + +// C++ version of parse_track_displaylists() +void CustomTrack::ParseMeshForCollision(TrackSections* sections, size_t numMesh) { + printf("\n[Track] Generating Collision Meshes...\n"); + + // Set configurations to zero + D_8015F59C = 0; + D_8015F5A0 = 0; + D_8015F5A4 = 0; + + for (size_t i = 0; i < numMesh; i++) { + switch(static_cast(sections[i].clip)) { + case SurfaceClip::CLIP_NONE: + continue; + case SurfaceClip::CLIP_SINGLE_SIDED_WALL: + D_8015F59C = 1; + break; + case SurfaceClip::CLIP_SURFACE: + D_8015F5A0 = 1; + break; + case SurfaceClip::CLIP_DOUBLE_SIDED_WALL: + D_8015F5A4 = 1; + break; + } + + const char* name = ResourceGetNameByCrc(sections[i].crc); + printf(" %s\n", name); + generate_collision_mesh((Gfx*) ResourceGetDataByCrc(sections[i].crc), sections[i].surfaceType, + sections[i].sectionId); + } + printf("[Track] Collision Mesh Generation Complete!\n\n"); +} + +void CustomTrack::TestPath() { + // DEBUG ONLY TO VISUALIZE PATH + return; + s16 x; + s16 y; + s16 z; + Vec3s rot = { 0, 0, 0 }; + Vec3f vel = { 0, 0, 0 }; + + for (size_t i = 0; i < gPathCountByPathIndex[0]; i++) { + x = gTrackPaths[0][i].x; + y = gTrackPaths[0][i].y; + z = gTrackPaths[0][i].z; + + if (((x & 0xFFFF) == 0x8000) && ((y & 0xFFFF) == 0x8000) && ((z & 0xFFFF) == 0x8000)) { + break; + } + + f32 height = spawn_actor_on_surface(x, 2000.0f, z); + Vec3f itemPos = { (f32) x, height, (f32) z }; + add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX); + } +} + +void CustomTrack::BeginPlay() { + printf("[Track] BeginPlay\n"); + CustomTrack::TestPath(); + this->SpawnActors(); +} + +void CustomTrack::Draw(ScreenContext* arg0) { + gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); + gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); + + if (bFog) { + gDPSetCycleType(gDisplayListHead++, G_CYC_2CYCLE); + gDPSetRenderMode(gDisplayListHead++, G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2); + gSPSetGeometryMode(gDisplayListHead++, G_FOG); + + gDPSetFogColor(gDisplayListHead++, gFogColour.r, gFogColour.g, gFogColour.b, gFogColour.a); + gSPFogPosition(gDisplayListHead++, gFogMin, gFogMax); + gDPPipeSync(gDisplayListHead++); + } else { + gSPClearGeometryMode(gDisplayListHead++, G_FOG); + } + + set_track_light_direction(D_800DC610, D_802B87D4, 0, 1); + gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); + gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); + + if (func_80290C20(arg0->camera) == 1) { + gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2); + } + + const TrackInfo* info = gTrackRegistry.GetInfo(ResourceName); + if (nullptr == info) { + printf("[Track] [Draw] Resource name did not return a valid TrackInfo %s\n", ResourceName.c_str()); + return; + } + std::string res = info->Path + "/data_track_sections"; + + TrackSections* sections = (TrackSections*) LOAD_ASSET_RAW(res.c_str()); + size_t size = ResourceGetSizeByName(res.c_str()); + size_t totalSections = size / sizeof(TrackSections); + for (uint64_t item : mOpaqueItems) { + gSPDisplayList(gDisplayListHead++, (Gfx*) ResourceGetDataByCrc(item)); + } +} + +void CustomTrack::Tick() { +} + +void CustomTrack::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { + FVector cam = { screen->camera->pos[0], screen->camera->pos[1], screen->camera->pos[2] }; + + std::sort(mTranslucentItems.begin(), mTranslucentItems.end(), + [&](TrackSections a, TrackSections b) { + FVector posA = FVector(a.location[0], a.location[1], a.location[2]); + FVector posB = FVector(b.location[0], b.location[1], b.location[2]);; + + float distA = (posA - cam).Square(); + float distB = (posB - cam).Square(); + + return distA > distB; // farthest first + }); + + for (TrackSections& item : mTranslucentItems) { + Mat4 matrix; + FVector pos = {item.location[0], item.location[1], item.location[2]}; + ApplyMatrixTransformations(matrix, pos, IRotator(0, 0, 0), FVector(1, 1, 1)); + AddObjectMatrix(matrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gDisplayListHead++, (Gfx*) ResourceGetDataByCrc(item.crc)); + } + + gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER); + for (TrackSections& item : mTranslucentNoZBufferItems) { + Mat4 matrix; + FVector pos = {item.location[0], item.location[1], item.location[2]}; + ApplyMatrixTransformations(matrix, pos, IRotator(0, 0, 0), FVector(1, 1, 1)); + AddObjectMatrix(matrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gDisplayListHead++, (Gfx*) ResourceGetDataByCrc(item.crc)); + } + gSPSetGeometryMode(gDisplayListHead++, G_ZBUFFER); +} diff --git a/src/engine/tracks/CustomTrack.h b/src/engine/tracks/CustomTrack.h new file mode 100644 index 0000000000..dfc61754bb --- /dev/null +++ b/src/engine/tracks/CustomTrack.h @@ -0,0 +1,38 @@ +#include +#include "Track.h" + +class CustomTrack : public Track { +public: + explicit CustomTrack(); + + virtual void Load() override; + virtual void BeginPlay() override; + virtual void Draw(ScreenContext*) override; + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; + virtual void Tick() override; + virtual bool IsMod() override { return true; } + void InvertTriangleWindingModdedByName(const char* name); + void ParseMeshForCollision(TrackSections* sections, size_t numMesh); + void TestPath(); + +protected: + +enum class SurfaceClip : uint16_t { + CLIP_NONE, + CLIP_DEFAULT, + CLIP_SINGLE_SIDED_WALL, + CLIP_SURFACE, + CLIP_DOUBLE_SIDED_WALL +}; + +enum class DrawLayer : uint16_t { + DRAW_INVISIBLE, + DRAW_OPAQUE, + DRAW_TRANSLUCENT, + DRAW_TRANSLUCENT_NO_ZBUFFER +}; + // Containers that hold meshes that get drawn + std::vector mOpaqueItems; + std::vector mTranslucentItems; + std::vector mTranslucentNoZBufferItems; +}; diff --git a/src/engine/tracks/DKJungle.cpp b/src/engine/tracks/DKJungle.cpp index 11e8cf6c12..10b564b2a8 100644 --- a/src/engine/tracks/DKJungle.cpp +++ b/src/engine/tracks/DKJungle.cpp @@ -301,7 +301,7 @@ void DKJungle::Waypoints(Player* player, int8_t playerId) { } } -void DKJungle::ScrollingTextures() { +void DKJungle::Tick() { D_802B87BC += 2; if (D_802B87BC > 255) { D_802B87BC = 0; @@ -325,7 +325,7 @@ void DKJungle::ScrollingTextures() { evaluate_collision_players_palm_trees(); } -void DKJungle::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { +void DKJungle::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { gDPPipeSync(gDisplayListHead++); gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); diff --git a/src/engine/tracks/DKJungle.h b/src/engine/tracks/DKJungle.h index 6e3d94491e..da7fb92fdc 100644 --- a/src/engine/tracks/DKJungle.h +++ b/src/engine/tracks/DKJungle.h @@ -37,8 +37,8 @@ class DKJungle : public Track { virtual void DrawCredits() override; virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; virtual void Waypoints(Player* player, int8_t playerId) override; - virtual void ScrollingTextures() override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; + virtual void Tick() override; + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; virtual void CreditsSpawnActors() override; virtual void Destroy() override; }; diff --git a/src/engine/tracks/KoopaTroopaBeach.cpp b/src/engine/tracks/KoopaTroopaBeach.cpp index 63bf80de7f..afa2f64c47 100644 --- a/src/engine/tracks/KoopaTroopaBeach.cpp +++ b/src/engine/tracks/KoopaTroopaBeach.cpp @@ -11,6 +11,7 @@ #include "engine/objects/Crab.h" #include "assets/models/tracks/koopa_troopa_beach/koopa_troopa_beach_data.h" #include "assets/other/tracks/koopa_troopa_beach/koopa_troopa_beach_data.h" +#include "assets/models/tracks/koopa_troopa_beach/koopa_troopa_beach_displaylists.h" #include "engine/objects/Seagull.h" extern "C" { @@ -250,7 +251,7 @@ void KoopaTroopaBeach::SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2 func_8003E37C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -void KoopaTroopaBeach::ScrollingTextures() { +void KoopaTroopaBeach::Tick() { // clang-format off // This flips the velocity from 0.1f to -0.1f if (gWaterVelocity < 0.0f) { @@ -283,10 +284,9 @@ void KoopaTroopaBeach::ScrollingTextures() { // Waterfall bubbling effect? (unused) // d_course_koopa_troopa_beach_packed_dl_2E8 find_and_set_tile_size((uintptr_t) d_course_koopa_troopa_beach_packed_dl_2E8, D_802B87C8, D_802B87CC); - } -void KoopaTroopaBeach::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { +void KoopaTroopaBeach::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { Mat4 matrix; Vec3f vector; diff --git a/src/engine/tracks/KoopaTroopaBeach.h b/src/engine/tracks/KoopaTroopaBeach.h index 15ae3e829b..5366be5a64 100644 --- a/src/engine/tracks/KoopaTroopaBeach.h +++ b/src/engine/tracks/KoopaTroopaBeach.h @@ -37,7 +37,7 @@ class KoopaTroopaBeach : public Track { virtual void Draw(ScreenContext*) override; virtual void DrawCredits() override; virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; - virtual void ScrollingTextures() override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; + virtual void Tick() override; + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; virtual void Destroy() override; }; diff --git a/src/engine/tracks/RainbowRoad.cpp b/src/engine/tracks/RainbowRoad.cpp index 83ca7239ce..8666ae74e9 100644 --- a/src/engine/tracks/RainbowRoad.cpp +++ b/src/engine/tracks/RainbowRoad.cpp @@ -204,8 +204,7 @@ void RainbowRoad::Waypoints(Player* player, int8_t playerId) { player->nearestPathPointId = gCopyNearestWaypointByPlayerId[playerId]; } -void RainbowRoad::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { - +void RainbowRoad::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { gDPPipeSync(gDisplayListHead++); gSPClearGeometryMode(gDisplayListHead++, G_CULL_BACK); render_track_sections(rainbow_road_dls, screen); diff --git a/src/engine/tracks/RainbowRoad.h b/src/engine/tracks/RainbowRoad.h index 07d5632937..47094594a9 100644 --- a/src/engine/tracks/RainbowRoad.h +++ b/src/engine/tracks/RainbowRoad.h @@ -36,7 +36,7 @@ class RainbowRoad : public Track { virtual void Draw(ScreenContext*) override; virtual void DrawCredits() override; virtual void Waypoints(Player* player, int8_t playerId) override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; virtual void CreditsSpawnActors() override; virtual void Destroy() override; }; diff --git a/src/engine/tracks/RoyalRaceway.cpp b/src/engine/tracks/RoyalRaceway.cpp index 510518e5ec..df582ecbbc 100644 --- a/src/engine/tracks/RoyalRaceway.cpp +++ b/src/engine/tracks/RoyalRaceway.cpp @@ -241,7 +241,7 @@ void RoyalRaceway::Waypoints(Player* player, int8_t playerId) { } } -void RoyalRaceway::ScrollingTextures() { +void RoyalRaceway::Tick() { D_802B87BC -= 20; if (D_802B87BC < 0) { D_802B87BC = 0xFF; diff --git a/src/engine/tracks/RoyalRaceway.h b/src/engine/tracks/RoyalRaceway.h index 095330b14f..4343f95a0c 100644 --- a/src/engine/tracks/RoyalRaceway.h +++ b/src/engine/tracks/RoyalRaceway.h @@ -30,7 +30,7 @@ class RoyalRaceway : public Track { virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override; virtual void SetStaffGhost() override; virtual void Draw(ScreenContext*) override; - virtual void DrawCredits() override; - virtual void ScrollingTextures() override; + virtual void DrawCredits() override; virtual void Waypoints(Player* player, int8_t playerId) override; + virtual void Tick() override; }; diff --git a/src/engine/tracks/SherbetLand.cpp b/src/engine/tracks/SherbetLand.cpp index 29b2935c8a..dd4301e754 100644 --- a/src/engine/tracks/SherbetLand.cpp +++ b/src/engine/tracks/SherbetLand.cpp @@ -209,7 +209,7 @@ void SherbetLand::DrawCredits() { gSPDisplayList(gDisplayListHead++, (Gfx*)(d_course_sherbet_land_dl_9AE8)); } -void SherbetLand::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { +void SherbetLand::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { gDPPipeSync(gDisplayListHead++); gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); diff --git a/src/engine/tracks/SherbetLand.h b/src/engine/tracks/SherbetLand.h index 8609210311..bab1edd5ae 100644 --- a/src/engine/tracks/SherbetLand.h +++ b/src/engine/tracks/SherbetLand.h @@ -30,6 +30,6 @@ class SherbetLand : public Track { virtual void DrawTrackObjects(s32 cameraId) override; virtual void Draw(ScreenContext*) override; virtual void DrawCredits() override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; virtual void CreditsSpawnActors() override; }; diff --git a/src/engine/tracks/Track.cpp b/src/engine/tracks/Track.cpp index d2ca6e3c40..bd629bdcec 100644 --- a/src/engine/tracks/Track.cpp +++ b/src/engine/tracks/Track.cpp @@ -189,7 +189,7 @@ static void InvertTriangleWindingInternal(Gfx* gfx, const char* gfxName, bool sh } } -static void InvertTriangleWindingModdedInternal(Gfx* gfx, const char* gfxName) { +void InvertTriangleWindingModdedInternal(Gfx* gfx, const char* gfxName) { if (gfx == nullptr) { return; } @@ -289,14 +289,6 @@ void InvertTriangleWindingByName(const char* name) { InvertTriangleWindingInternal(gfx, name, shouldSwap); } -void InvertTriangleWindingModdedByName(const char* name) { - if (name == nullptr) { - return; - } - Gfx* gfx = (Gfx*)ResourceGetDataByName(name); - InvertTriangleWindingModdedInternal(gfx, name); -} - void RestoreTriangleWinding() { for (const std::string& name : gModifiedGfxSet) { if (strstr(name.c_str(), "packed") == nullptr) { @@ -354,8 +346,6 @@ Track::Track() { Props.SetText(Props.Name, "Blank Track", sizeof(Props.Name)); Props.SetText(Props.DebugName, "blnktrck", sizeof(Props.DebugName)); Props.SetText(Props.TrackLength, "100m", sizeof(Props.TrackLength)); - // Props.Cup = FLOWER_CUP; - // Props.CupIndex = 3; ResourceName = "mod:blank_track"; Props.Minimap.Texture = minimap_mario_raceway; Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture); @@ -432,99 +422,16 @@ void Track::Load(Vtx* vtx, Gfx* gfx) { Track::Init(); } -// Load stock and o2r tracks +// Load stock tracks void Track::Load() { printf("[Track] Loading... %s\n", ResourceName.c_str()); const TrackInfo* info = gTrackRegistry.GetInfo(ResourceName); if (nullptr == info) { - printf("Could not find TrackInfo for %s\n", ResourceName.c_str()); + printf("[Track] Could not find TrackInfo for %s\n", ResourceName.c_str()); return; } - const std::string& trackPath = info->Path; - - if (trackPath.empty()) { - // Load stock track - Track::Init(); - } else { // Load custom track - bIsMod = true; - - TrackEditor::LoadTrackDataFromJson(this, trackPath); - - const std::string trackSectionPath = (trackPath + "/data_track_sections"); - TrackSections* sections = (TrackSections*) LOAD_ASSET_RAW(trackSectionPath.c_str()); - size_t size = ResourceGetSizeByName(trackSectionPath.c_str()); - - size_t totalSections = size / sizeof(TrackSections); - - if (sections != nullptr) { - Track::Init(); - if (gIsMirrorMode != 0) { - for (size_t i = 0; i < totalSections; i++) { - auto name = ResourceGetNameByCrc(sections[i].crc); - InvertTriangleWindingModdedByName(name); - } - } - ParseTrackSections(sections, size); - func_80295C6C(); - - if (Props.WaterLevel == FLT_MAX) { - Props.WaterLevel = gTrackMinY - 10.0f; - } - } else { - printf("Track.cpp: Custom track sections are invalid\n"); - } - } -} - -// C++ version of parse_track_displaylists() -void Track::ParseTrackSections(TrackSections* sections, size_t size) { - printf("\n[Track] Generating Collision Meshes...\n"); - for (size_t i = 0; i < (size / sizeof(TrackSections)); i++) { - if (sections[i].flags & 0x8000) { - D_8015F59C = 1; // single-sided wall - } else { - D_8015F59C = 0; - } - if (sections[i].flags & 0x2000) { - D_8015F5A0 = 1; // surface - } else { - D_8015F5A0 = 0; - } - if (sections[i].flags & 0x4000) { - D_8015F5A4 = 1; // double-sided wall - } else { - D_8015F5A4 = 0; - } - const char* name = ResourceGetNameByCrc(sections[i].crc); - printf(" %s\n", name); - generate_collision_mesh((Gfx*) ResourceGetDataByCrc(sections[i].crc), sections[i].surfaceType, - sections[i].sectionId); - } - printf("[Track] Collision Mesh Generation Complete!\n\n"); -} - -void Track::TestPath() { - // DEBUG ONLY TO VISUALIZE PATH - return; - s16 x; - s16 y; - s16 z; - Vec3s rot = { 0, 0, 0 }; - Vec3f vel = { 0, 0, 0 }; - for (size_t i = 0; i < gPathCountByPathIndex[0]; i++) { - x = gTrackPaths[0][i].x; - y = gTrackPaths[0][i].y; - z = gTrackPaths[0][i].z; - - if (((x & 0xFFFF) == 0x8000) && ((y & 0xFFFF) == 0x8000) && ((z & 0xFFFF) == 0x8000)) { - break; - } - - f32 height = spawn_actor_on_surface(x, 2000.0f, z); - Vec3f itemPos = { (f32) x, height, (f32) z }; - add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX); - } + Track::Init(); } void Track::Init() { @@ -548,7 +455,6 @@ void Track::Init() { void Track::BeginPlay() { printf("[Track] BeginPlay\n"); - TestPath(); this->SpawnActors(); } @@ -680,14 +586,10 @@ f32 Track::GetWaterLevel(FVector pos, Collision* collision) { return found ? highestWater : GetWorld()->GetTrack()->Props.WaterLevel; } -void Track::ScrollingTextures() { +void Track::Tick() { } -void Track::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { +void Track::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { } void Track::Destroy() { } - -bool Track::IsMod() { - return bIsMod; -} diff --git a/src/engine/tracks/Track.h b/src/engine/tracks/Track.h index 2deb20b62b..3bea88ed00 100644 --- a/src/engine/tracks/Track.h +++ b/src/engine/tracks/Track.h @@ -82,7 +82,9 @@ typedef struct { uint64_t crc; u8 surfaceType; // Determines what kind of surface the player drives on (ex. dirt, asphalt, etc.) u8 sectionId; - u16 flags; + u16 clip; // enum in CustomTrack.h + u16 layer; // enum in CustomTrack.h + Vec3f location; } TrackSections; typedef struct Properties { @@ -321,7 +323,6 @@ class Track { std::optional FinishlineSpawnPoint; - bool bIsMod = false; std::vector SpawnList; bool bTourEnabled = false; @@ -335,7 +336,6 @@ class Track { virtual void Load(); // Decompress and load stock tracks or from o2r but TrackSectionsPtr must be set. virtual void Load(Vtx* vtx, Gfx *gfx); // Load custom track from code. Load must be overridden and then call to this base class method impl. - virtual void ParseTrackSections(TrackSections* sections, size_t size); /** * @brief BeginPlay This function is called once at the start of gameplay. @@ -343,7 +343,6 @@ class Track { */ virtual void BeginPlay(); void SpawnActors(); - virtual void TestPath(); virtual void InitClouds(); virtual void TickClouds(s32, Camera*); virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7); @@ -359,17 +358,22 @@ class Track { virtual void DrawCredits(); virtual void Waypoints(Player* player, int8_t playerId); virtual f32 GetWaterLevel(FVector pos, Collision* collision); - virtual void ScrollingTextures(); + virtual void Tick(); // Draw transparent models (water, signs, arrows, etc.) - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection); virtual void Destroy(); - virtual bool IsMod(); + // Note that this will be false for custom tracks made using code + // Probably ok + virtual bool IsMod() { return false; }; - private: + + protected: void Init(); }; +void InvertTriangleWindingModdedInternal(Gfx* gfx, const char* gfxName); + #endif #endif // ENGINE_TRACK_H diff --git a/src/engine/tracks/WarioStadium.cpp b/src/engine/tracks/WarioStadium.cpp index 7dbdf2c857..1fc47c8fb1 100644 --- a/src/engine/tracks/WarioStadium.cpp +++ b/src/engine/tracks/WarioStadium.cpp @@ -301,7 +301,7 @@ void WarioStadium::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Ve func_8003EE2C(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -void WarioStadium::DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, +void WarioStadium::DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { gDPPipeSync(gDisplayListHead++); diff --git a/src/engine/tracks/WarioStadium.h b/src/engine/tracks/WarioStadium.h index 6e8bbc3ef2..71d1d5be86 100644 --- a/src/engine/tracks/WarioStadium.h +++ b/src/engine/tracks/WarioStadium.h @@ -37,7 +37,7 @@ class WarioStadium : public Track { virtual void DrawCredits() override; virtual void SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7) override; - virtual void DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, + virtual void DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) override; virtual void CreditsSpawnActors() override; virtual void Destroy() override; diff --git a/src/engine/tracks/YoshiValley.cpp b/src/engine/tracks/YoshiValley.cpp index 831981858d..9f9547bf41 100644 --- a/src/engine/tracks/YoshiValley.cpp +++ b/src/engine/tracks/YoshiValley.cpp @@ -206,8 +206,6 @@ void YoshiValley::Waypoints(Player* player, int8_t playerId) { player->nearestPathPointId = gCopyNearestWaypointByPlayerId[playerId]; } -void YoshiValley::ScrollingTextures() {} - void YoshiValley::CreditsSpawnActors() { Vec3f position; Vec3f velocity = { 0, 0, 0 }; diff --git a/src/engine/tracks/YoshiValley.h b/src/engine/tracks/YoshiValley.h index 1093ce1b45..be3d8f21ac 100644 --- a/src/engine/tracks/YoshiValley.h +++ b/src/engine/tracks/YoshiValley.h @@ -33,7 +33,6 @@ class YoshiValley : public Track { virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override; virtual void Draw(ScreenContext*) override; virtual void DrawCredits() override; - virtual void ScrollingTextures() override; virtual void Waypoints(Player* player, int8_t playerId) override; virtual void CreditsSpawnActors() override; virtual void Destroy() override; diff --git a/src/main.c b/src/main.c index 518ff6335d..5aa7e13ea7 100644 --- a/src/main.c +++ b/src/main.c @@ -266,8 +266,6 @@ void start_sptask(s32 taskType) { gActiveSPTask->state = SPTASK_STATE_RUNNING; } -extern void Graphics_PushFrame(Gfx* data); - /** * Initializes the Fast3D OSTask structure. * Loads F3DEX or F3DLX based on the number of players @@ -314,7 +312,7 @@ void create_gfx_task_structure(void) { } f32 gDeltaTime = 0.0f; -f32 calculate_delta_time(void) { +void calculate_delta_time(void) { static u32 prevtime = 0; u32 now = osGetCount(); f32 deltaTime; @@ -691,7 +689,7 @@ void process_game_tick(void) { func_80059AC8(); update_course_actors(); CM_TickActors(); - func_802966A0(); + CM_TickTrack(); if (CM_IsTourEnabled() == false) { func_8028FCBC(); } diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp index 8bbd65cab0..5a4b75c39b 100644 --- a/src/port/Engine.cpp +++ b/src/port/Engine.cpp @@ -392,7 +392,7 @@ void GameEngine::StartFrame() const { // Instance->context->GetWindow()->MainLoop(run_one_game_iter); // } -void GameEngine::RunCommands(Gfx* Commands, const std::vector>& mtx_replacements) { +void GameEngine::RunCommands(Gfx* pool, const std::vector>& mtx_replacements) { auto wnd = std::dynamic_pointer_cast(Ship::Context::GetInstance()->GetWindow()); if (wnd == nullptr) { @@ -406,8 +406,8 @@ void GameEngine::RunCommands(Gfx* Commands, const std::vectormInterpolationIndex = 0; - for (const auto& m : mtx_replacements) { - wnd->DrawAndRunGraphicsCommands(Commands, m); + for (const auto& mtxStack : mtx_replacements) { + wnd->DrawAndRunGraphicsCommands(pool, mtxStack); interpreter->mInterpolationIndex++; } @@ -419,7 +419,12 @@ void GameEngine::RunCommands(Gfx* Commands, const std::vector> mtx_replacements; int target_fps = GameEngine::Instance->GetInterpolationFPS(); if (CVarGetInteger("gModifyInterpolationTargetFPS", 0)) { @@ -442,12 +447,13 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { // time_base = fps * original_fps (one second) int next_original_frame = fps; + // Get matrix replacements for intermediate frames while (time + original_fps <= next_original_frame) { time += original_fps; if (time != next_original_frame) { mtx_replacements.push_back(FrameInterpolation_Interpolate((float) time / next_original_frame)); } else { - mtx_replacements.emplace_back(); + mtx_replacements.emplace_back(); // No interpolation for key frames } } // printf("mtxf size: %d\n", mtx_replacements.size()); @@ -459,7 +465,7 @@ void GameEngine::ProcessGfxCommands(Gfx* commands) { wnd->SetTargetFps(GetInterpolationFPS()); wnd->SetMaximumFrameLatency(1); } - RunCommands(commands, mtx_replacements); + RunCommands(pool, mtx_replacements); last_fps = fps; last_update_rate = 2; diff --git a/src/port/Engine.h b/src/port/Engine.h index 16efa2fda3..d837bcaa32 100644 --- a/src/port/Engine.h +++ b/src/port/Engine.h @@ -13,6 +13,7 @@ #include #include #include "ship/Context.h" +#include #ifndef IDYES #define IDYES 6 @@ -68,10 +69,10 @@ class GameEngine { static uint32_t GetInterpolationFPS(); static uint32_t GetInterpolationFrameCount(); void StartFrame() const; - static void RunCommands(Gfx* Commands, const std::vector>& mtx_replacements); + static void RunCommands(Gfx* pool, const std::vector>& mtx_replacements); void ProcessFrame(void (*run_one_game_iter)()) const; static void Destroy(); - static void ProcessGfxCommands(Gfx* commands); + static void ProcessGfxCommands(Gfx* pool); static uint8_t GetBankIdByName(const std::string& name); static int ShowYesNoBox(const char* title, const char* box); static void ShowMessage(const char* title, const char* message, SDL_MessageBoxFlags type = SDL_MESSAGEBOX_ERROR); diff --git a/src/port/Game.cpp b/src/port/Game.cpp index e241fac811..dd4c4b6a51 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -50,8 +50,8 @@ extern "C" { // #include "engine/wasm.h" } -extern "C" void Graphics_PushFrame(Gfx* data) { - GameEngine::ProcessGfxCommands(data); +extern "C" void Graphics_PushFrame(Gfx* pool) { + GameEngine::ProcessGfxCommands(pool); } // Create the world instance @@ -639,16 +639,16 @@ Properties* CM_GetProps() { return NULL; } -void CM_ScrollingTextures() { +void CM_TickTrack() { if (GetWorld()->GetTrack()) { - GetWorld()->GetTrack()->ScrollingTextures(); + GetWorld()->GetTrack()->Tick(); } } -void CM_DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, +void CM_DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection) { if (GetWorld()->GetTrack()) { - GetWorld()->GetTrack()->DrawWater(screen, pathCounter, cameraRot, playerDirection); + GetWorld()->GetTrack()->DrawTransparency(screen, pathCounter, cameraRot, playerDirection); } } diff --git a/src/port/Game.h b/src/port/Game.h index 2fcda177d7..743aecb75d 100644 --- a/src/port/Game.h +++ b/src/port/Game.h @@ -37,6 +37,8 @@ World* GetWorld(void); // Retrieve the world instance #endif // NOLINTBEGIN(readability-identifier-naming) +void Graphics_PushFrame(Gfx* pool); + uintptr_t CM_GetTrack(); Properties* CM_GetProps(); @@ -124,13 +126,13 @@ void CM_SetStaffGhost(); void CM_BombKartsWaypoint(s32 cameraId); -void CM_ScrollingTextures(); +void CM_TickTrack(); s32 CM_GetCrossingOnTriggered(uintptr_t* crossing); void CM_BeginPlay(); -void CM_DrawWater(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, +void CM_DrawTransparency(ScreenContext* screen, uint16_t pathCounter, uint16_t cameraRot, uint16_t playerDirection); void CM_AICrossingBehaviour(s32 playerId); diff --git a/src/port/resource/importers/TrackPathPointFactory.cpp b/src/port/resource/importers/TrackPathPointFactory.cpp index ccb29f2f3b..8c5feab2c1 100644 --- a/src/port/resource/importers/TrackPathPointFactory.cpp +++ b/src/port/resource/importers/TrackPathPointFactory.cpp @@ -48,6 +48,8 @@ ResourceFactoryXMLTrackPathPointsV0::ReadResource(std::shared_ptr fi std::vector waypointPath; // Temporary container for this path + int32_t pathIndex = path->IntAttribute("type", 0); // Default to 0 if not set + auto pointElem = path->FirstChildElement("Point"); while (pointElem != nullptr) { @@ -62,7 +64,7 @@ ResourceFactoryXMLTrackPathPointsV0::ReadResource(std::shared_ptr fi pointElem = pointElem->NextSiblingElement("Point"); } - paths->PathList.push_back(waypointPath); // Push full path to outer list + paths->PathObject.push_back({waypointPath, pathIndex});// PathList.push_back(waypointPath); // Push full path to outer list path = path->NextSiblingElement("TrackPathPoint"); } diff --git a/src/port/resource/importers/TrackSectionsFactory.cpp b/src/port/resource/importers/TrackSectionsFactory.cpp index 9cee94725f..294e823121 100644 --- a/src/port/resource/importers/TrackSectionsFactory.cpp +++ b/src/port/resource/importers/TrackSectionsFactory.cpp @@ -26,7 +26,11 @@ ResourceFactoryBinaryTrackSectionsV0::ReadResource(std::shared_ptr f data.crc = reader->ReadUInt64(); data.surfaceType = reader->ReadUByte(); data.sectionId = reader->ReadUByte(); - data.flags = reader->ReadUInt16(); + data.clip = reader->ReadUInt16(); + data.layer = 0; + data.location[0] = 0; + data.location[1] = 0; + data.location[2] = 0; section->TrackSectionsList.push_back(data); } @@ -55,7 +59,11 @@ ResourceFactoryXMLTrackSectionsV0::ReadResource(std::shared_ptr file data.crc = CRC64(child->Attribute("gfx_path")); data.surfaceType = child->IntAttribute("surface"); data.sectionId = child->IntAttribute("section"); - data.flags = child->IntAttribute("flags"); + data.clip = child->IntAttribute("flags"); + data.layer = child->IntAttribute("drawlayer"); + data.location[0] = child->FloatAttribute("x"); + data.location[1] = child->FloatAttribute("y"); + data.location[2] = child->FloatAttribute("z"); section->TrackSectionsList.push_back(data); } diff --git a/src/port/resource/type/TrackPathPointData.cpp b/src/port/resource/type/TrackPathPointData.cpp index f38bf58711..1b9a18c4f7 100644 --- a/src/port/resource/type/TrackPathPointData.cpp +++ b/src/port/resource/type/TrackPathPointData.cpp @@ -24,11 +24,19 @@ TrackPathPoint* Paths::GetPointer() { } size_t Paths::GetPointerSize() { - size_t totalWaypoints = 0; - for (const auto& path : PathList) { - totalWaypoints += path.size(); + size_t totalSize = 0; + // Iterate over each PathObject in the PathObject vector + for (const auto& obj : PathObject) { + // Add the size of the vector itself (this is the overhead of the vector container) + totalSize += sizeof(obj.PathList); + + // Add the size of the elements in the PathList vector + totalSize += obj.PathList.size() * sizeof(TrackPathPoint); + + // Add the size of the PathIndex (int32_t) + totalSize += sizeof(obj.PathIndex); } - return totalWaypoints * sizeof(TrackPathPoint); + return totalSize; } } // namespace MK64 \ No newline at end of file diff --git a/src/port/resource/type/TrackPathPointData.h b/src/port/resource/type/TrackPathPointData.h index b5ed563515..1337825ff9 100644 --- a/src/port/resource/type/TrackPathPointData.h +++ b/src/port/resource/type/TrackPathPointData.h @@ -26,10 +26,16 @@ class Paths : public Ship::Resource { Paths(); + // This struct is really ugly... Sorry + struct PathObject { + std::vector PathList; + int32_t PathIndex; + }; + TrackPathPoint* GetPointer() override; size_t GetPointerSize() override; - std::vector> PathList; + std::vector PathObject; }; } // namespace MK64 diff --git a/src/port/ui/PortMenu.cpp b/src/port/ui/PortMenu.cpp index e5f31dcba6..9fc613d299 100644 --- a/src/port/ui/PortMenu.cpp +++ b/src/port/ui/PortMenu.cpp @@ -214,7 +214,7 @@ void PortMenu::AddSettings() { static int32_t maxFps; const char* tooltip = ""; if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { - maxFps = 360; + maxFps = MAX_FPS; tooltip = "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics. This is " "purely visual and does not impact game logic, execution of glitches etc.\n\nA higher target " "FPS than your monitor's refresh rate will waste resources, and might give a worse result."; @@ -287,7 +287,7 @@ void PortMenu::AddSettings() { AddWidget(path, "Match Refresh Rate", WIDGET_BUTTON) .Callback([](WidgetInfo& info) { int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); - if (hz >= 30 && hz <= 360) { + if (hz >= 30 && hz <= MAX_FPS) { CVarSetInteger("gInterpolationFPS", hz); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); } @@ -307,7 +307,7 @@ void PortMenu::AddSettings() { "CPU to work on one frame while GPU works on the previous frame.\nThis setting " "should be used when your computer is too slow to do CPU + GPU work in time.") .Min(0) - .Max(360) + .Max(MAX_FPS) .DefaultValue(80)); AddWidget(path, "Enable Vsync", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_VSYNC_ENABLED) @@ -522,7 +522,7 @@ void PortMenu::AddDevTools() { .Options(IntSliderOptions() .Tooltip("Sets the target FPS for interpolation. When Modify Interpolation Target FPS are enable") .Min(15) - .Max(360) + .Max(MAX_FPS) .DefaultValue(60)); AddWidget(path, "Render Collision", WIDGET_CVAR_CHECKBOX) .CVar("gRenderCollisionMesh") diff --git a/src/port/ui/PortMenu.h b/src/port/ui/PortMenu.h index e6f0a1d045..f42133d991 100644 --- a/src/port/ui/PortMenu.h +++ b/src/port/ui/PortMenu.h @@ -9,6 +9,8 @@ namespace GameUI { +constexpr size_t MAX_FPS = 480; + static const std::unordered_map menuExtentOptions = { { UIWidgets::MenuExtent::Condensed, "Condensed" }, { UIWidgets::MenuExtent::Stretched, "Stretched" }, diff --git a/src/racing/render_courses.c b/src/racing/render_courses.c index d35fbdb627..c5cdf7e5f7 100644 --- a/src/racing/render_courses.c +++ b/src/racing/render_courses.c @@ -57,17 +57,17 @@ void parse_track_displaylists(TrackSections* asset) { TrackSections* section = (TrackSections*) asset; while (section->crc != 0) { - if (section->flags & 0x8000) { + if (section->clip & 0x8000) { D_8015F59C = 1; } else { D_8015F59C = 0; } - if (section->flags & 0x2000) { + if (section->clip & 0x2000) { D_8015F5A0 = 1; } else { D_8015F5A0 = 0; } - if (section->flags & 0x4000) { + if (section->clip & 0x4000) { D_8015F5A4 = 1; } else { D_8015F5A4 = 0; @@ -199,7 +199,7 @@ void func_80291198(void) { gSPDisplayList(gDisplayListHead++, (Gfx*) d_course_mario_raceway_packed_dl_1140); // } -void func_8029122C(ScreenContext* screen, s32 playerId) { +void draw_transparent_geography(ScreenContext* screen, s32 playerId) { UNUSED s32 pad; Player* player = screen->player; Mat4 matrix; @@ -232,7 +232,7 @@ void func_8029122C(ScreenContext* screen, s32 playerId) { } render_set_position(matrix, 0); - CM_DrawWater(screen, pathCounter, cameraRot, playerDirection); + CM_DrawTransparency(screen, pathCounter, cameraRot, playerDirection); FrameInterpolation_RecordCloseChild(); } @@ -277,7 +277,3 @@ void func_80295D6C(void) { D_8015F6F4 = 3000; D_8015F6F6 = -3000; } - -void func_802966A0(void) { - CM_ScrollingTextures(); -} diff --git a/src/racing/render_courses.h b/src/racing/render_courses.h index 1794f30d15..6f05b5cc57 100644 --- a/src/racing/render_courses.h +++ b/src/racing/render_courses.h @@ -5,7 +5,7 @@ #include "../camera.h" #include "src/engine/tracks/Track.h" -void func_8029122C(ScreenContext*, s32); +void draw_transparent_geography(ScreenContext*, s32); s32 func_80290C20(Camera*); void parse_track_displaylists(TrackSections* asset); void render_track_sections(const char*[], ScreenContext*); @@ -16,7 +16,6 @@ void func_80295C6C(void); void func_80295D50(s16, s16); void func_80295D6C(void); void func_80295D88(void); -void func_802966A0(void); extern s32 D_8015F59C; diff --git a/src/racing/skybox_and_splitscreen.c b/src/racing/skybox_and_splitscreen.c index ea7d227518..2ae1548f7a 100644 --- a/src/racing/skybox_and_splitscreen.c +++ b/src/racing/skybox_and_splitscreen.c @@ -824,7 +824,8 @@ void render_screens(s32 mode, s32 cameraId, s32 playerId) { render_players(camera, screenId); } - func_8029122C(screen, playerId); // Track water related + // Track geography + draw_transparent_geography(screen, playerId); switch (playerId) { // Render player particles or some effect case 0: