summaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2025-12-13 17:28:44 -0700
committerGitHub <noreply@github.com>2025-12-13 17:28:44 -0700
commit7bc8d6f4be2bc22f7f4815d3c5eac691c4b92c0f (patch)
treeea7bed88faf5f3bb0788c698fd0252d3f624548a /src/engine
parent4e51b7d5b6a9b89deb5ef135deec0ee5f0087e7c (diff)
Refactor Field-of-view into the Camera Struct (#590)
* Fix finishline for toads turnpike in extra * Fixed trash bin in extra * Refactor fov * Update scene.json * Allow setting fog * impl fog save & load
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/actors/FallingRock.cpp2
-rw-r--r--src/engine/actors/MarioSign.cpp2
-rw-r--r--src/engine/actors/Text.cpp2
-rw-r--r--src/engine/actors/Tree.cpp2
-rw-r--r--src/engine/actors/WarioSign.cpp2
-rw-r--r--src/engine/cameras/FreeCamera.cpp2
-rw-r--r--src/engine/cameras/GameCamera.cpp2
-rw-r--r--src/engine/cameras/TourCamera.cpp2
-rw-r--r--src/engine/editor/EditorMath.cpp2
-rw-r--r--src/engine/editor/SceneManager.cpp58
-rw-r--r--src/engine/editor/SceneManager.h2
-rw-r--r--src/engine/objects/TrashBin.cpp13
-rw-r--r--src/engine/tracks/BansheeBoardwalk.cpp2
-rw-r--r--src/engine/tracks/ChocoMountain.cpp4
-rw-r--r--src/engine/tracks/ToadsTurnpike.cpp2
-rw-r--r--src/engine/tracks/Track.cpp14
16 files changed, 91 insertions, 22 deletions
diff --git a/src/engine/actors/FallingRock.cpp b/src/engine/actors/FallingRock.cpp
index fb0c47280..d32b65c9d 100644
--- a/src/engine/actors/FallingRock.cpp
+++ b/src/engine/actors/FallingRock.cpp
@@ -157,7 +157,7 @@ void AFallingRock::Draw(Camera* camera) {
return;
}
- height = is_within_render_distance(camera->pos, Pos, camera->rot[1], 400.0f, gCameraFOV[camera - camera1],
+ height = is_within_render_distance(camera->pos, Pos, camera->rot[1], 400.0f, camera->fieldOfView,
4000000.0f);
if (CVarGetInteger("gNoCulling", 0) == 1) {
diff --git a/src/engine/actors/MarioSign.cpp b/src/engine/actors/MarioSign.cpp
index c8d9188ff..7722b7de5 100644
--- a/src/engine/actors/MarioSign.cpp
+++ b/src/engine/actors/MarioSign.cpp
@@ -68,7 +68,7 @@ void AMarioSign::Draw(Camera *camera) {
return;
}
- unk = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, gCameraFOV[camera - camera1], 16000000.0f);
+ unk = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, camera->fieldOfView, 16000000.0f);
if (CVarGetInteger("gNoCulling", 0) == 1) {
unk = MAX(unk, 0.0f);
}
diff --git a/src/engine/actors/Text.cpp b/src/engine/actors/Text.cpp
index 0a5b204e6..9e6423239 100644
--- a/src/engine/actors/Text.cpp
+++ b/src/engine/actors/Text.cpp
@@ -182,7 +182,7 @@ void AText::Draw(Camera* camera) {
}
f32 distance = is_within_render_distance(camera->pos, (float*)&Pos[0], camera->rot[1], Close,
- gCameraFOV[camera - camera1], Far);
+ camera->fieldOfView, Far);
if (distance == -1.0f) {
Dist = DistanceProps::TOO_FAR;
diff --git a/src/engine/actors/Tree.cpp b/src/engine/actors/Tree.cpp
index 480fdf980..cd732c1e4 100644
--- a/src/engine/actors/Tree.cpp
+++ b/src/engine/actors/Tree.cpp
@@ -38,7 +38,7 @@ void ATree::Draw(Camera* camera) {
return;
}
- dist = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, gCameraFOV[camera - camera1],
+ dist = is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, camera->fieldOfView,
DrawDistance);
if (CVarGetInteger("gNoCulling", 0) == 1) {
diff --git a/src/engine/actors/WarioSign.cpp b/src/engine/actors/WarioSign.cpp
index aca8084eb..cd7813f04 100644
--- a/src/engine/actors/WarioSign.cpp
+++ b/src/engine/actors/WarioSign.cpp
@@ -48,7 +48,7 @@ void AWarioSign::Tick() {
void AWarioSign::Draw(Camera *camera) {
Mat4 sp38;
f32 unk =
- is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, gCameraFOV[camera - camera1], 16000000.0f);
+ is_within_render_distance(camera->pos, Pos, camera->rot[1], 0, camera->fieldOfView, 16000000.0f);
if (CVarGetInteger("gNoCulling", 0) == 1) {
unk = MAX(unk, 0.0f);
diff --git a/src/engine/cameras/FreeCamera.cpp b/src/engine/cameras/FreeCamera.cpp
index 887f97611..71a0f9079 100644
--- a/src/engine/cameras/FreeCamera.cpp
+++ b/src/engine/cameras/FreeCamera.cpp
@@ -56,7 +56,7 @@ void FreeCamera::SetViewProjection() {
// Perspective (camera movement)
FrameInterpolation_RecordOpenChild("freecam_persp", FrameInterpolation_GetCameraEpoch());
- guPerspective(&PerspectiveMatrix, &perspNorm, 40, gScreenAspect,
+ guPerspective(&PerspectiveMatrix, &perspNorm, _camera->fieldOfView, gScreenAspect,
CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
gSPMatrix(gDisplayListHead++, &PerspectiveMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
diff --git a/src/engine/cameras/GameCamera.cpp b/src/engine/cameras/GameCamera.cpp
index fd02dbd98..73dd9953a 100644
--- a/src/engine/cameras/GameCamera.cpp
+++ b/src/engine/cameras/GameCamera.cpp
@@ -88,7 +88,7 @@ void GameCamera::SetViewProjection() {
(FrameInterpolation_GetCameraEpoch() | ((_camera->cameraId << 8))));
// Calculate camera perspective (camera movement/location)
- guPerspective(&PerspectiveMatrix, &perspNorm, gCameraFOV[_camera->cameraId], gScreenAspect,
+ guPerspective(&PerspectiveMatrix, &perspNorm, _camera->fieldOfView, gScreenAspect,
CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
gSPMatrix(gDisplayListHead++, &PerspectiveMatrix,
diff --git a/src/engine/cameras/TourCamera.cpp b/src/engine/cameras/TourCamera.cpp
index 3e25e77bd..ff50481bf 100644
--- a/src/engine/cameras/TourCamera.cpp
+++ b/src/engine/cameras/TourCamera.cpp
@@ -196,7 +196,7 @@ void TourCamera::SetViewProjection() {
// Perspective (camera movement)
FrameInterpolation_RecordOpenChild("tourcam_persp", FrameInterpolation_GetCameraEpoch());
- guPerspective(&PerspectiveMatrix, &perspNorm, 40, gScreenAspect,
+ guPerspective(&PerspectiveMatrix, &perspNorm, _camera->fieldOfView, gScreenAspect,
CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
gSPPerspNormalize(gDisplayListHead++, perspNorm);
gSPMatrix(gDisplayListHead++, &PerspectiveMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
diff --git a/src/engine/editor/EditorMath.cpp b/src/engine/editor/EditorMath.cpp
index 620aa2b48..02932a5a7 100644
--- a/src/engine/editor/EditorMath.cpp
+++ b/src/engine/editor/EditorMath.cpp
@@ -62,7 +62,7 @@ FVector ScreenRayTrace() {
Mat4 perspMtx;
u16 perspNorm;
- guPerspectiveF(perspMtx, &perspNorm, 40, OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
+ guPerspectiveF(perspMtx, &perspNorm, camera->fieldOfView, OTRGetAspectRatio(), CM_GetProps()->NearPersp, CM_GetProps()->FarPersp, 1.0f);
Mat4 inversePerspMtx;
if (InverseMatrix((float*)&perspMtx, (float*)&inversePerspMtx) != 2) {
diff --git a/src/engine/editor/SceneManager.cpp b/src/engine/editor/SceneManager.cpp
index 135079a57..b8e3d93e0 100644
--- a/src/engine/editor/SceneManager.cpp
+++ b/src/engine/editor/SceneManager.cpp
@@ -29,6 +29,8 @@ extern "C" {
#include "actors.h"
#include "actor_types.h"
#include "code_80005FD0.h"
+#include "code_800029B0.h"
+#include "render_courses.h"
}
namespace Editor {
@@ -56,6 +58,10 @@ namespace Editor {
data["Tour"] = tour;
}
+ nlohmann::json fog;
+ SaveFog(fog);
+ data["Fog"] = fog;
+
if (nullptr == track->Archive) {
SPDLOG_INFO("[SceneManager] [SaveLevel] Track archive nullptr");
return;
@@ -297,6 +303,19 @@ namespace Editor {
}
}
+ void SaveFog(nlohmann::json& fog) {
+ if (bFog) {
+ fog["EnableFog"] = bFog;
+ fog["Colour"]["R"] = gFogColour.r;
+ fog["Colour"]["G"] = gFogColour.g;
+ fog["Colour"]["B"] = gFogColour.b;
+ fog["Colour"]["A"] = gFogColour.a;
+
+ fog["Min"] = gFogMin;
+ fog["Max"] = gFogMax;
+ }
+ }
+
void LoadProps(Track* track, nlohmann::json& data) {
if (!data.contains("Props") || !data["Props"].is_object()) {
SPDLOG_INFO("Track is missing props data. Is the scene.json file corrupt?");
@@ -415,4 +434,43 @@ namespace Editor {
}
}
}
+
+ void LoadFog(nlohmann::json& data) {
+ if (!data.contains("Fog") || !data["Fog"].is_object()) {
+ SPDLOG_INFO(" This track does not contain fog");
+ return;
+ }
+
+ nlohmann::json& fog = data["Fog"];
+
+ bFog = fog.value("Enabled", false);
+
+ if (!bFog) return;
+
+ // Load color
+ if (fog.contains("Colour") && fog["Colour"].is_object()) {
+ nlohmann::json& c = fog["Colour"];
+ gFogColour.r = c.value("R", 255);
+ gFogColour.g = c.value("G", 255);
+ gFogColour.b = c.value("B", 255);
+ gFogColour.a = c.value("A", 255);
+ }
+
+ // Load min/max with safety clamps
+ int minVal = fog.value("Min", 0);
+ int maxVal = fog.value("Max", 500);
+
+ // Ensure min < max
+ if (minVal >= maxVal) {
+ minVal = maxVal - 1;
+ }
+
+ // Clamp to valid ranges
+ minVal = std::clamp(minVal, 0, 999);
+ maxVal = std::clamp(maxVal, 1, 1000);
+
+ gFogMin = static_cast<int16_t>(minVal);
+ gFogMax = static_cast<int16_t>(maxVal);
+
+ }
}
diff --git a/src/engine/editor/SceneManager.h b/src/engine/editor/SceneManager.h
index 48b52a1e2..551d79e32 100644
--- a/src/engine/editor/SceneManager.h
+++ b/src/engine/editor/SceneManager.h
@@ -17,6 +17,7 @@ namespace Editor {
void SaveActors(nlohmann::json& actorList);
void SaveStaticMeshActors(nlohmann::json& actorList);
void SaveTour(Track* track, nlohmann::json& tour);
+ void SaveFog(nlohmann::json& fog);
void LoadProps(Track* track, nlohmann::json& data);
void LoadPaths(Track* track, const std::string& trackPath);
@@ -24,6 +25,7 @@ namespace Editor {
void LoadActors(Track* track, nlohmann::json& data);
void LoadStaticMeshActors(Track* track, nlohmann::json& data);
void LoadTour(Track* track, nlohmann::json& data);
+ void LoadFog(nlohmann::json& data);
void SpawnActors(std::vector<std::pair<std::string, SpawnParams>> spawnList);
diff --git a/src/engine/objects/TrashBin.cpp b/src/engine/objects/TrashBin.cpp
index 954b9491a..b483a7549 100644
--- a/src/engine/objects/TrashBin.cpp
+++ b/src/engine/objects/TrashBin.cpp
@@ -19,14 +19,13 @@ extern "C" {
#include "audio/external.h"
}
-#define DEGREES_FLOAT_TO_SHORT(Degrees) ((s16)((Degrees) * (0x8000 / 180.0f)))
-
OTrashBin::OTrashBin(const SpawnParams& params) : OObject(params) {
Name = "Trash Bin";
ResourceName = "mk:trash_bin";
_pos = params.Location.value_or(FVector(0, 0, 0));
+ _pos.x *= xOrientation;
_rot = params.Rotation.value_or(IRotator(0, 0, 0));
- _scale = params.Scale.value_or(FVector(0, 0, 0)).y; // Only y
+ _scale = params.Scale.value_or(FVector(0, 0, 0)).y;
_bhv = static_cast<Behaviour>(params.Behaviour.value_or(0));
find_unused_obj_index(&_objectIndex);
@@ -86,9 +85,9 @@ void OTrashBin::init_bb_trash_bin(s32 objectIndex) {
gObjectList[objectIndex].unk_04C = 0;
gObjectList[objectIndex].unk_084[7] = 0;
set_obj_orientation(objectIndex, 0U, 0U, 0U);
- gObjectList[objectIndex].orientation[0] = DEGREES_FLOAT_TO_SHORT(_rot.pitch);
- gObjectList[objectIndex].orientation[1] = DEGREES_FLOAT_TO_SHORT(_rot.yaw);
- gObjectList[objectIndex].orientation[2] = DEGREES_FLOAT_TO_SHORT(_rot.roll);
+ gObjectList[objectIndex].orientation[0] = _rot.pitch;
+ gObjectList[objectIndex].orientation[1] = _rot.yaw;
+ gObjectList[objectIndex].orientation[2] = _rot.roll;
gObjectList[objectIndex].pos[0] = _pos.x;
if (_drawBin) {
// Position the lid on-top of the box.
@@ -105,8 +104,6 @@ void OTrashBin::init_bb_trash_bin(s32 objectIndex) {
object_next_state(objectIndex);
}
-#undef DEGREES_FLOAT_TO_SHORT
-
void OTrashBin::func_8007E00C(s32 objectIndex) {
switch (gObjectList[objectIndex].state) {
case 1:
diff --git a/src/engine/tracks/BansheeBoardwalk.cpp b/src/engine/tracks/BansheeBoardwalk.cpp
index 54dc2ac8b..337dc14cd 100644
--- a/src/engine/tracks/BansheeBoardwalk.cpp
+++ b/src/engine/tracks/BansheeBoardwalk.cpp
@@ -166,7 +166,7 @@ void BansheeBoardwalk::BeginPlay() {
}
if (gIsMirrorMode) {
- SpawnActor<OTrashBin>(FVector(1765.0f, 45.0f, 195.0f), IRotator(0, 180, 0), 1.0f, bhv);
+ SpawnActor<OTrashBin>(FVector(-1765.0f, 45.0f, 195.0f), IRotator(0, 180, 0), 1.0f, bhv);
} else {
SpawnActor<OTrashBin>(FVector(-1765.0f, 45.0f, 70.0f), IRotator(0, 0, 0), 1.0f, bhv);
}
diff --git a/src/engine/tracks/ChocoMountain.cpp b/src/engine/tracks/ChocoMountain.cpp
index dc369c9a5..aa8e4666e 100644
--- a/src/engine/tracks/ChocoMountain.cpp
+++ b/src/engine/tracks/ChocoMountain.cpp
@@ -132,8 +132,8 @@ void ChocoMountain::Load() {
gFogColour.g = 255;
gFogColour.b = 255;
gFogColour.a = 255;
- gFogMin = 0x3E3;
- gFogMax = 0x3E8;
+ gFogMin = 995;
+ gFogMax = 1000;
D_802B87D4 = 0x71C;
D_802B87D0 = 0xE38;
diff --git a/src/engine/tracks/ToadsTurnpike.cpp b/src/engine/tracks/ToadsTurnpike.cpp
index ea675e301..4a4c9bbcb 100644
--- a/src/engine/tracks/ToadsTurnpike.cpp
+++ b/src/engine/tracks/ToadsTurnpike.cpp
@@ -103,7 +103,7 @@ ToadsTurnpike::ToadsTurnpike() {
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
FVector finish;
- finish.x = (gIsMirrorMode != 0) ? 100 + 138.0f : 100 - 138.0f;
+ finish.x = -38.0f * xOrientation;
finish.y = (f32) (0 - 15);
finish.z = 16;
diff --git a/src/engine/tracks/Track.cpp b/src/engine/tracks/Track.cpp
index ae6477c59..3f898754e 100644
--- a/src/engine/tracks/Track.cpp
+++ b/src/engine/tracks/Track.cpp
@@ -623,6 +623,19 @@ void Track::Waypoints(Player* player, int8_t playerId) {
void Track::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);
@@ -630,7 +643,6 @@ void Track::Draw(ScreenContext* arg0) {
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);
- // d_course_big_donut_packed_dl_DE8
}
const TrackInfo* info = gTrackRegistry.GetInfo(ResourceName);