diff --git a/output.bin b/output.bin index 30528a2..317e6d2 100644 Binary files a/output.bin and b/output.bin differ diff --git a/src/camera.hh b/src/camera.hh index 51ef552..39c3e84 100644 --- a/src/camera.hh +++ b/src/camera.hh @@ -6,6 +6,7 @@ namespace psxsplash { +// Camera class for managing 3D position and rotation. class Camera { public: Camera(); diff --git a/src/gtemath.hh b/src/gtemath.hh index 059f34e..73fb10b 100644 --- a/src/gtemath.hh +++ b/src/gtemath.hh @@ -1,3 +1,4 @@ +#pragma once #include namespace psxsplash { diff --git a/src/main.cpp b/src/main.cpp index b94b1d6..b04f955 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,11 +30,12 @@ class PSXSplash final : public psyqo::Application { void createScene() override; public: - psyqo::Font<> m_font; - psyqo::AdvancedPad m_input; psxsplash::SplashPackLoader m_loader; - static constexpr uint8_t m_stickDeadzone = 0x30; + psyqo::Font<> m_font; + + psyqo::AdvancedPad m_input; + static constexpr uint8_t m_stickDeadzone = 0x30; }; class MainScene final : public psyqo::Scene { @@ -49,12 +50,17 @@ class MainScene final : public psyqo::Scene { static constexpr psyqo::FixedPoint<12> moveSpeed = 0.002_fp; static constexpr psyqo::Angle rotSpeed = 0.01_pi; - bool m_sprinting = 0; - static constexpr psyqo::FixedPoint<12> sprintSpeed = 0.003_fp; + bool m_sprinting = false; + static constexpr psyqo::FixedPoint<12> sprintSpeed = 0.01_fp; + + bool m_freecam = false; + psyqo::FixedPoint<12> pheight = 0.0_fp; + + bool m_renderSelect = false; }; -PSXSplash psxSplash; +PSXSplash app; MainScene mainScene; } // namespace @@ -78,11 +84,32 @@ void PSXSplash::createScene() { } void MainScene::start(StartReason reason) { - psxSplash.m_loader.LoadSplashpack(_binary_output_bin_start); + app.m_loader.LoadSplashpack(_binary_output_bin_start); psxsplash::Renderer::GetInstance().SetCamera(m_mainCamera); -} -psyqo::FixedPoint<12> pheight = 0.0_fp; + m_mainCamera.SetPosition(static_cast>(app.m_loader.playerStartPos.x), + static_cast>(app.m_loader.playerStartPos.y), + static_cast>(app.m_loader.playerStartPos.z)); + + pheight = psyqo::FixedPoint<12>(app.m_loader.playerHeight); + + app.m_input.setOnEvent( + eastl::function{[this](const psyqo::AdvancedPad::Event& event) { + if (event.pad != psyqo::AdvancedPad::Pad::Pad1a) return; + if (app.m_loader.navmeshes.empty()) return; + if (event.type == psyqo::AdvancedPad::Event::ButtonPressed) { + if (event.button == psyqo::AdvancedPad::Button::Triangle) { + m_freecam = !m_freecam; + } else if (event.button == psyqo::AdvancedPad::Button::Square) { + m_renderSelect = !m_renderSelect; + } + } + }}); + + if (app.m_loader.navmeshes.empty()) { + m_freecam = true; + } +} void MainScene::frame() { uint32_t beginFrame = gpu().now(); @@ -95,63 +122,69 @@ void MainScene::frame() { } mainScene.m_lastFrameCounter = currentFrameCounter; - - uint8_t rightX = psxSplash.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 0); - uint8_t rightY = psxSplash.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 1); - uint8_t leftX = psxSplash.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 2); - uint8_t leftY = psxSplash.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 3); + uint8_t rightX = app.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 0); + uint8_t rightY = app.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 1); + + uint8_t leftX = app.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 2); + uint8_t leftY = app.m_input.getAdc(psyqo::AdvancedPad::Pad::Pad1a, 3); int16_t rightXOffset = (int16_t)rightX - 0x80; int16_t rightYOffset = (int16_t)rightY - 0x80; int16_t leftXOffset = (int16_t)leftX - 0x80; int16_t leftYOffset = (int16_t)leftY - 0x80; - - if(__builtin_abs(leftXOffset) < psxSplash.m_stickDeadzone && - __builtin_abs(leftYOffset) < psxSplash.m_stickDeadzone) { + + if (__builtin_abs(leftXOffset) < app.m_stickDeadzone && + __builtin_abs(leftYOffset) < app.m_stickDeadzone) { m_sprinting = false; } - if(psxSplash.m_input.isButtonPressed(psyqo::AdvancedPad::Pad::Pad1a, psyqo::AdvancedPad::Button::L3)) { + if (app.m_input.isButtonPressed(psyqo::AdvancedPad::Pad::Pad1a, psyqo::AdvancedPad::Button::L3)) { m_sprinting = true; } psyqo::FixedPoint<12> speed = m_sprinting ? sprintSpeed : moveSpeed; - if (__builtin_abs(rightXOffset) > psxSplash.m_stickDeadzone) { - camRotY += (rightXOffset * rotSpeed * deltaTime) >> 7; + if (__builtin_abs(rightXOffset) > app.m_stickDeadzone) { + camRotY += (rightXOffset * rotSpeed * deltaTime) >> 7; } - if (__builtin_abs(rightYOffset) > psxSplash.m_stickDeadzone) { + if (__builtin_abs(rightYOffset) > app.m_stickDeadzone) { camRotX -= (rightYOffset * rotSpeed * deltaTime) >> 7; camRotX = eastl::clamp(camRotX, -0.5_pi, 0.5_pi); } m_mainCamera.SetRotation(camRotX, camRotY, camRotZ); - if (__builtin_abs(leftYOffset) > psxSplash.m_stickDeadzone) { + if (__builtin_abs(leftYOffset) > app.m_stickDeadzone) { psyqo::FixedPoint<12> forward = -(leftYOffset * speed * deltaTime) >> 7; m_mainCamera.MoveX((m_trig.sin(camRotY) * forward)); m_mainCamera.MoveZ((m_trig.cos(camRotY) * forward)); } - if (__builtin_abs(leftXOffset) > psxSplash.m_stickDeadzone) { - psyqo::FixedPoint<12> strafe = -(leftXOffset * speed * deltaTime) >> 7; + if (__builtin_abs(leftXOffset) > app.m_stickDeadzone) { + psyqo::FixedPoint<12> strafe = -(leftXOffset * speed * deltaTime) >> 7; m_mainCamera.MoveX(-(m_trig.cos(camRotY) * strafe)); m_mainCamera.MoveZ((m_trig.sin(camRotY) * strafe)); } - if(psxSplash.m_input.isButtonPressed(psyqo::AdvancedPad::Pad::Pad1a, psyqo::AdvancedPad::Button::L1)) { - pheight += 0.01_fp; + if (app.m_input.isButtonPressed(psyqo::AdvancedPad::Pad::Pad1a, psyqo::AdvancedPad::Button::L1)) { + m_mainCamera.MoveY(speed * deltaTime); } - if(psxSplash.m_input.isButtonPressed(psyqo::AdvancedPad::Pad::Pad1a, psyqo::AdvancedPad::Button::R1)) { - pheight -= 0.01_fp; + if (app.m_input.isButtonPressed(psyqo::AdvancedPad::Pad::Pad1a, psyqo::AdvancedPad::Button::R1)) { + m_mainCamera.MoveY(-speed * deltaTime); } - psyqo::Vec3 adjustedPosition = - psxsplash::ComputeNavmeshPosition(m_mainCamera.GetPosition(), *psxSplash.m_loader.navmeshes[0], -0.05_fp); - m_mainCamera.SetPosition(adjustedPosition.x, adjustedPosition.y, adjustedPosition.z); + if (!m_freecam) { + psyqo::Vec3 adjustedPosition = + psxsplash::ComputeNavmeshPosition(m_mainCamera.GetPosition(), *app.m_loader.navmeshes[0], -pheight); + m_mainCamera.SetPosition(adjustedPosition.x, adjustedPosition.y, adjustedPosition.z); + } - psxsplash::Renderer::GetInstance().Render(psxSplash.m_loader.gameObjects); - // psxsplash::Renderer::getInstance().renderNavmeshPreview(*psxSplash.m_loader.navmeshes[0], true); - psxSplash.m_font.chainprintf(gpu(), {{.x = 2, .y = 2}}, {{.r = 0xff, .g = 0xff, .b = 0xff}}, "FPS: %i", + if (!m_renderSelect) { + psxsplash::Renderer::GetInstance().Render(app.m_loader.gameObjects); + } else { + psxsplash::Renderer::GetInstance().RenderNavmeshPreview(*app.m_loader.navmeshes[0], true); + } + + app.m_font.chainprintf(gpu(), {{.x = 2, .y = 2}}, {{.r = 0xff, .g = 0xff, .b = 0xff}}, "FPS: %i", gpu().getRefreshRate() / deltaTime); gpu().pumpCallbacks(); @@ -159,4 +192,4 @@ void MainScene::frame() { uint32_t spent = endFrame - beginFrame; } -int main() { return psxSplash.run(); } \ No newline at end of file +int main() { return app.run(); } \ No newline at end of file diff --git a/src/navmesh.cpp b/src/navmesh.cpp index 91e5aaf..bd21ed0 100644 --- a/src/navmesh.cpp +++ b/src/navmesh.cpp @@ -7,6 +7,9 @@ using namespace psyqo::fixed_point_literals; +// FIXME: This entire file uses hard FixedPoint scaling of 100. This is not ideal. +// It would be better to move the fixedpoint precision to 19 instead. + namespace psxsplash { psyqo::FixedPoint<12> DotProduct2D(const psyqo::Vec2& a, const psyqo::Vec2& b) { return a.x * b.x + a.y * b.y; } diff --git a/src/navmesh.hh b/src/navmesh.hh index 121c880..538c1b3 100644 --- a/src/navmesh.hh +++ b/src/navmesh.hh @@ -1,6 +1,6 @@ #pragma once -#include "psyqo/gte-registers.hh" +#include namespace psxsplash { diff --git a/src/renderer.cpp b/src/renderer.cpp index 94ecfee..9d14658 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1,5 +1,6 @@ #include "renderer.hh" +#include #include #include @@ -14,9 +15,7 @@ #include #include -#include "EASTL/array.h" #include "gtemath.hh" -#include "splashpack.hh" using namespace psyqo::fixed_point_literals; using namespace psyqo::trig_literals; @@ -46,7 +45,6 @@ void psxsplash::Renderer::Init(psyqo::GPU &gpuInstance) { void psxsplash::Renderer::SetCamera(psxsplash::Camera &camera) { m_currentCamera = &camera; } - void psxsplash::Renderer::Render(eastl::vector &objects) { psyqo::Kernel::assert(m_currentCamera != nullptr, "PSXSPLASH: Tried to render without an active camera"); @@ -189,6 +187,10 @@ void psxsplash::Renderer::RenderNavmeshPreview(psxsplash::Navmesh navmesh, bool zIndex = eastl::max(eastl::max(sz0, sz1), sz2); if (zIndex < 0 || zIndex >= ORDERING_TABLE_SIZE) continue; + read(&projected[0].packed); + read(&projected[1].packed); + read(&projected[2].packed); + auto &prim = balloc.allocateFragment(); prim.primitive.pointA = projected[0]; @@ -244,6 +246,11 @@ void psxsplash::Renderer::recursiveSubdivideAndRender(Tri &tri, eastl::array(); prim.primitive.pointA = projected[0]; @@ -252,7 +259,7 @@ void psxsplash::Renderer::recursiveSubdivideAndRender(Tri &tri, eastl::array uint32_t { int dx = a.x - b.x; int dy = a.y - b.y; diff --git a/src/renderer.hh b/src/renderer.hh index 8b73344..c5a733a 100644 --- a/src/renderer.hh +++ b/src/renderer.hh @@ -16,7 +16,7 @@ #include "camera.hh" #include "gameobject.hh" -#include "splashpack.hh" +#include "navmesh.hh" namespace psxsplash { @@ -25,6 +25,7 @@ class Renderer final { Renderer(const Renderer&) = delete; Renderer& operator=(const Renderer&) = delete; + // FIXME: I have no idea how to precompute the required sizes of these. It would be best to allocate them based on the scene static constexpr size_t ORDERING_TABLE_SIZE = 2048 * 3; static constexpr size_t BUMP_ALLOCATOR_SIZE = 8096 * 24; diff --git a/src/splashpack.cpp b/src/splashpack.cpp index 56c7df2..d5d6b3e 100644 --- a/src/splashpack.cpp +++ b/src/splashpack.cpp @@ -6,6 +6,8 @@ #include "gameobject.hh" #include "mesh.hh" +#include "psyqo/fixed-point.hh" +#include "psyqo/gte-registers.hh" #include "renderer.hh" namespace psxsplash { @@ -17,7 +19,10 @@ struct SPLASHPACKFileHeader { uint16_t navmeshCount; uint16_t textureAtlasCount; uint16_t clutCount; - uint16_t pad[2]; + psyqo::GTE::PackedVec3 playerStartPos; + psyqo::GTE::PackedVec3 playerStartRot; + psyqo::FixedPoint<12, uint16_t> playerHeight; + uint16_t pad[1]; }; struct SPLASHPACKTextureAtlas { @@ -39,6 +44,10 @@ void SplashPackLoader::LoadSplashpack(uint8_t *data) { psxsplash::SPLASHPACKFileHeader *header = reinterpret_cast(data); psyqo::Kernel::assert(memcmp(header->magic, "SP", 2) == 0, "Splashpack has incorrect magic"); + playerStartPos = header->playerStartPos; + playerStartRot = header->playerStartRot; + playerHeight = header->playerHeight; + gameObjects.reserve(header->gameObjectCount); navmeshes.reserve(header->navmeshCount); diff --git a/src/splashpack.hh b/src/splashpack.hh index 7218ed8..11273c8 100644 --- a/src/splashpack.hh +++ b/src/splashpack.hh @@ -6,6 +6,7 @@ #include "gameobject.hh" #include "navmesh.hh" +#include "psyqo/fixed-point.hh" namespace psxsplash { @@ -13,6 +14,10 @@ class SplashPackLoader { public: eastl::vector gameObjects; eastl::vector navmeshes; + + psyqo::GTE::PackedVec3 playerStartPos, playerStartRot; + psyqo::FixedPoint<12, uint16_t> playerHeight; + void LoadSplashpack(uint8_t *data); };