more fixes
This commit is contained in:
@@ -15,12 +15,7 @@ struct Interactable {
|
|||||||
// Interaction radius squared (fixed-point 12-bit, pre-squared for fast distance checks)
|
// Interaction radius squared (fixed-point 12-bit, pre-squared for fast distance checks)
|
||||||
psyqo::FixedPoint<12> radiusSquared;
|
psyqo::FixedPoint<12> radiusSquared;
|
||||||
|
|
||||||
// Interaction point offset from object center
|
// Button index that triggers interaction (0-15, matches psyqo::AdvancedPad::Button)
|
||||||
psyqo::FixedPoint<12> offsetX;
|
|
||||||
psyqo::FixedPoint<12> offsetY;
|
|
||||||
psyqo::FixedPoint<12> offsetZ;
|
|
||||||
|
|
||||||
// Button index that triggers interaction (0-15)
|
|
||||||
uint8_t interactButton;
|
uint8_t interactButton;
|
||||||
|
|
||||||
// Configuration flags
|
// Configuration flags
|
||||||
@@ -33,22 +28,39 @@ struct Interactable {
|
|||||||
uint16_t currentCooldown; // Frames remaining until can interact again
|
uint16_t currentCooldown; // Frames remaining until can interact again
|
||||||
uint16_t gameObjectIndex; // Index of associated GameObject
|
uint16_t gameObjectIndex; // Index of associated GameObject
|
||||||
|
|
||||||
|
// Prompt canvas name (null-terminated, max 15 chars + null)
|
||||||
|
char promptCanvasName[16];
|
||||||
|
|
||||||
// Flag accessors
|
// Flag accessors
|
||||||
bool isRepeatable() const { return flags & 0x01; }
|
bool isRepeatable() const { return flags & 0x01; }
|
||||||
bool showPrompt() const { return flags & 0x02; }
|
bool showPrompt() const { return flags & 0x02; }
|
||||||
bool requireLineOfSight() const { return flags & 0x04; }
|
bool requireLineOfSight() const { return flags & 0x04; }
|
||||||
|
|
||||||
// Check if ready to interact
|
// Check if ready to interact
|
||||||
bool canInteract() const { return currentCooldown == 0; }
|
bool canInteract() const {
|
||||||
|
// Non-repeatable interactions: once cooldown was set, it stays permanently
|
||||||
|
if (!isRepeatable() && cooldownFrames > 0 && currentCooldown == 0) {
|
||||||
|
// Check if we already triggered once (cooldownFrames acts as sentinel)
|
||||||
|
// We use a special value to mark "already used"
|
||||||
|
}
|
||||||
|
return currentCooldown == 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Called when interaction happens
|
// Called when interaction happens
|
||||||
void triggerCooldown() { currentCooldown = cooldownFrames; }
|
void triggerCooldown() {
|
||||||
|
if (isRepeatable()) {
|
||||||
|
currentCooldown = cooldownFrames;
|
||||||
|
} else {
|
||||||
|
// Non-repeatable: set to max to permanently disable
|
||||||
|
currentCooldown = 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called each frame to decrement cooldown
|
// Called each frame to decrement cooldown
|
||||||
void update() {
|
void update() {
|
||||||
if (currentCooldown > 0) currentCooldown--;
|
if (currentCooldown > 0 && currentCooldown != 0xFFFF) currentCooldown--;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Interactable) == 24, "Interactable is not 24 bytes");
|
static_assert(sizeof(Interactable) == 28, "Interactable must be 28 bytes");
|
||||||
|
|
||||||
} // namespace psxsplash
|
} // namespace psxsplash
|
||||||
|
|||||||
@@ -1263,9 +1263,9 @@ int LuaAPI::Audio_StopAll(lua_State* L) {
|
|||||||
|
|
||||||
int LuaAPI::Debug_Log(lua_State* L) {
|
int LuaAPI::Debug_Log(lua_State* L) {
|
||||||
psyqo::Lua lua(L);
|
psyqo::Lua lua(L);
|
||||||
|
if (lua.isString(1)) {
|
||||||
// Debug.Log is a no-op on PS1 to avoid printf overhead.
|
printf("%s\n", lua.toString(1));
|
||||||
// Messages are only visible in emulator TTY builds.
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "loadingscreen.hh"
|
#include "loadingscreen.hh"
|
||||||
|
|
||||||
#include <psyqo/primitives/misc.hh>
|
#include <psyqo/primitives/misc.hh>
|
||||||
|
#include <psyqo/trigonometry.hh>
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
@@ -23,6 +24,13 @@ using namespace psxsplash;
|
|||||||
// Static member definition
|
// Static member definition
|
||||||
psyqo::Font<>* psxsplash::SceneManager::s_font = nullptr;
|
psyqo::Font<>* psxsplash::SceneManager::s_font = nullptr;
|
||||||
|
|
||||||
|
// Default player collision radius: ~0.5 world units at GTE 100 -> 20 in 20.12
|
||||||
|
static constexpr int32_t PLAYER_RADIUS = 20;
|
||||||
|
|
||||||
|
// Interaction system state
|
||||||
|
static psyqo::Trig<> s_interactTrig;
|
||||||
|
static int s_activePromptCanvas = -1; // Currently shown prompt canvas index (-1 = none)
|
||||||
|
|
||||||
void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingScreen* loading) {
|
void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingScreen* loading) {
|
||||||
auto& gpu = Renderer::GetInstance().getGPU();
|
auto& gpu = Renderer::GetInstance().getGPU();
|
||||||
|
|
||||||
@@ -47,7 +55,6 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc
|
|||||||
m_gameObjects = std::move(sceneSetup.objects);
|
m_gameObjects = std::move(sceneSetup.objects);
|
||||||
m_objectNames = std::move(sceneSetup.objectNames);
|
m_objectNames = std::move(sceneSetup.objectNames);
|
||||||
m_bvh = sceneSetup.bvh; // Copy BVH for frustum culling
|
m_bvh = sceneSetup.bvh; // Copy BVH for frustum culling
|
||||||
m_worldCollision = sceneSetup.worldCollision; // World collision soup (v7+)
|
|
||||||
m_navRegions = sceneSetup.navRegions; // Nav region system (v7+)
|
m_navRegions = sceneSetup.navRegions; // Nav region system (v7+)
|
||||||
m_playerNavRegion = m_navRegions.isLoaded() ? m_navRegions.getStartRegion() : NAV_NO_REGION;
|
m_playerNavRegion = m_navRegions.isLoaded() ? m_navRegions.getStartRegion() : NAV_NO_REGION;
|
||||||
|
|
||||||
@@ -406,91 +413,41 @@ void psxsplash::SceneManager::GameTick(psyqo::GPU &gpu) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t navmeshStart = gpu.now();
|
uint32_t navmeshStart = gpu.now();
|
||||||
if (!freecam) {
|
if (!freecam && m_navRegions.isLoaded()) {
|
||||||
if (m_worldCollision.isLoaded()) {
|
// Apply gravity
|
||||||
psyqo::Vec3 slid = m_worldCollision.moveAndSlide(
|
for (int f = 0; f < m_deltaFrames; f++) {
|
||||||
oldPlayerPosition, m_playerPosition, m_playerRadius, 0xFF);
|
m_velocityY += m_gravityPerFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply vertical velocity to position
|
||||||
|
int32_t posYDelta = (m_velocityY * m_deltaFrames) / 30;
|
||||||
|
m_playerPosition.y.value += posYDelta;
|
||||||
|
|
||||||
m_playerPosition.x = slid.x;
|
// Resolve position via nav regions
|
||||||
m_playerPosition.z = slid.z;
|
uint16_t prevRegion = m_playerNavRegion;
|
||||||
|
int32_t px = m_playerPosition.x.value;
|
||||||
|
int32_t pz = m_playerPosition.z.value;
|
||||||
|
int32_t floorY = m_navRegions.resolvePosition(
|
||||||
|
px, pz, m_playerNavRegion);
|
||||||
|
|
||||||
// Apply gravity: velocity changes each frame
|
if (m_playerNavRegion != NAV_NO_REGION) {
|
||||||
for (int f = 0; f < m_deltaFrames; f++) {
|
m_playerPosition.x.value = px;
|
||||||
m_velocityY += m_gravityPerFrame;
|
m_playerPosition.z.value = pz;
|
||||||
}
|
|
||||||
|
|
||||||
// Apply vertical velocity to position
|
int32_t cameraAtFloor = floorY - m_playerHeight.raw();
|
||||||
// velocityY is in fp12 per-second; convert per-frame: pos += vel / 30
|
|
||||||
int32_t posYDelta = (m_velocityY * m_deltaFrames) / 30;
|
|
||||||
m_playerPosition.y.value += posYDelta;
|
|
||||||
|
|
||||||
// Resolve floor Y from nav regions if available
|
if (m_playerPosition.y.value >= cameraAtFloor) {
|
||||||
if (m_navRegions.isLoaded()) {
|
m_playerPosition.y.value = cameraAtFloor;
|
||||||
uint16_t prevRegion = m_playerNavRegion;
|
m_velocityY = 0;
|
||||||
int32_t px = m_playerPosition.x.value;
|
m_isGrounded = true;
|
||||||
int32_t pz = m_playerPosition.z.value;
|
|
||||||
int32_t floorY = m_navRegions.resolvePosition(
|
|
||||||
px, pz, m_playerNavRegion);
|
|
||||||
|
|
||||||
|
|
||||||
if (m_playerNavRegion != NAV_NO_REGION) {
|
|
||||||
m_playerPosition.x.value = px;
|
|
||||||
m_playerPosition.z.value = pz;
|
|
||||||
|
|
||||||
// Ground (feet) position in PSX coords:
|
|
||||||
// Camera is at position.y, feet are at position.y + playerHeight
|
|
||||||
// (Y-down: larger Y = lower)
|
|
||||||
int32_t cameraAtFloor = floorY - m_playerHeight.raw();
|
|
||||||
|
|
||||||
if (m_playerPosition.y.value >= cameraAtFloor) {
|
|
||||||
// Player is at or below floor — snap to ground
|
|
||||||
m_playerPosition.y.value = cameraAtFloor;
|
|
||||||
m_velocityY = 0;
|
|
||||||
m_isGrounded = true;
|
|
||||||
} else {
|
|
||||||
// Player is above floor (jumping/airborne)
|
|
||||||
m_isGrounded = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Off all nav regions — revert to old position
|
|
||||||
m_playerPosition = oldPlayerPosition;
|
|
||||||
m_playerNavRegion = prevRegion;
|
|
||||||
m_velocityY = 0;
|
|
||||||
m_isGrounded = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Ground trace fallback (no nav regions)
|
m_isGrounded = false;
|
||||||
int32_t groundY;
|
|
||||||
int32_t groundNormalY;
|
|
||||||
uint8_t surfFlags;
|
|
||||||
if (m_worldCollision.groundTrace(m_playerPosition,
|
|
||||||
4096 * 4, // max 4 units down
|
|
||||||
groundY, groundNormalY, surfFlags, 0xFF)) {
|
|
||||||
int32_t cameraAtFloor = groundY - m_playerHeight.raw();
|
|
||||||
if (m_playerPosition.y.value >= cameraAtFloor) {
|
|
||||||
m_playerPosition.y.value = cameraAtFloor;
|
|
||||||
m_velocityY = 0;
|
|
||||||
m_isGrounded = true;
|
|
||||||
} else {
|
|
||||||
m_isGrounded = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
m_playerPosition = oldPlayerPosition;
|
|
||||||
m_velocityY = 0;
|
|
||||||
m_isGrounded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ceiling check: if jumping upward, check for ceiling collision
|
|
||||||
if (m_velocityY < 0 && m_worldCollision.isLoaded()) {
|
|
||||||
int32_t ceilingY;
|
|
||||||
if (m_worldCollision.ceilingTrace(m_playerPosition,
|
|
||||||
m_playerHeight.raw(), ceilingY, 0xFF)) {
|
|
||||||
// Hit a ceiling — stop upward velocity
|
|
||||||
m_velocityY = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
m_playerPosition = oldPlayerPosition;
|
||||||
|
m_playerNavRegion = prevRegion;
|
||||||
|
m_velocityY = 0;
|
||||||
|
m_isGrounded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,48 +484,88 @@ void psxsplash::SceneManager::fireTriggerExit(int16_t luaFileIndex, uint16_t tri
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
void psxsplash::SceneManager::updateInteractionSystem() {
|
void psxsplash::SceneManager::updateInteractionSystem() {
|
||||||
// Get interact button state - Cross button by default
|
// Tick cooldowns for all interactables
|
||||||
auto interactButton = psyqo::AdvancedPad::Button::Cross;
|
for (auto* interactable : m_interactables) {
|
||||||
bool buttonPressed = m_controls.wasButtonPressed(interactButton);
|
if (interactable) interactable->update();
|
||||||
|
}
|
||||||
|
|
||||||
if (!buttonPressed) return; // Early out if no interaction attempt
|
// Player position for distance checks
|
||||||
|
|
||||||
// Player position for distance check
|
|
||||||
psyqo::FixedPoint<12> playerX = static_cast<psyqo::FixedPoint<12>>(m_playerPosition.x);
|
psyqo::FixedPoint<12> playerX = static_cast<psyqo::FixedPoint<12>>(m_playerPosition.x);
|
||||||
psyqo::FixedPoint<12> playerY = static_cast<psyqo::FixedPoint<12>>(m_playerPosition.y);
|
psyqo::FixedPoint<12> playerY = static_cast<psyqo::FixedPoint<12>>(m_playerPosition.y);
|
||||||
psyqo::FixedPoint<12> playerZ = static_cast<psyqo::FixedPoint<12>>(m_playerPosition.z);
|
psyqo::FixedPoint<12> playerZ = static_cast<psyqo::FixedPoint<12>>(m_playerPosition.z);
|
||||||
|
|
||||||
// Find closest interactable in range
|
// Player forward direction from Y rotation (for line-of-sight checks)
|
||||||
Interactable* closest = nullptr;
|
psyqo::FixedPoint<12> forwardX = s_interactTrig.sin(playerRotationY);
|
||||||
|
psyqo::FixedPoint<12> forwardZ = s_interactTrig.cos(playerRotationY);
|
||||||
|
|
||||||
|
// First pass: find which interactable is closest and in range (for prompt display)
|
||||||
|
Interactable* inRange = nullptr;
|
||||||
psyqo::FixedPoint<12> closestDistSq;
|
psyqo::FixedPoint<12> closestDistSq;
|
||||||
closestDistSq.value = 0x7FFFFFFF; // Max positive value
|
closestDistSq.value = 0x7FFFFFFF;
|
||||||
|
|
||||||
for (auto* interactable : m_interactables) {
|
for (auto* interactable : m_interactables) {
|
||||||
if (!interactable || !interactable->canInteract()) continue;
|
if (!interactable) continue;
|
||||||
|
|
||||||
// Check if object is active
|
|
||||||
auto* go = getGameObject(interactable->gameObjectIndex);
|
auto* go = getGameObject(interactable->gameObjectIndex);
|
||||||
if (!go || !go->isActive()) continue;
|
if (!go || !go->isActive()) continue;
|
||||||
|
|
||||||
// Calculate distance squared
|
// Distance check
|
||||||
psyqo::FixedPoint<12> dx = playerX - interactable->offsetX - go->position.x;
|
psyqo::FixedPoint<12> dx = playerX - go->position.x;
|
||||||
psyqo::FixedPoint<12> dy = playerY - interactable->offsetY - go->position.y;
|
psyqo::FixedPoint<12> dy = playerY - go->position.y;
|
||||||
psyqo::FixedPoint<12> dz = playerZ - interactable->offsetZ - go->position.z;
|
psyqo::FixedPoint<12> dz = playerZ - go->position.z;
|
||||||
|
|
||||||
psyqo::FixedPoint<12> distSq = dx * dx + dy * dy + dz * dz;
|
psyqo::FixedPoint<12> distSq = dx * dx + dy * dy + dz * dz;
|
||||||
|
|
||||||
// Check if in range and closer than current closest
|
if (distSq > interactable->radiusSquared) continue;
|
||||||
if (distSq <= interactable->radiusSquared && distSq < closestDistSq) {
|
|
||||||
closest = interactable;
|
// Line-of-sight check: dot product of forward vector and direction to object
|
||||||
|
if (interactable->requireLineOfSight()) {
|
||||||
|
// dot = forwardX * dx + forwardZ * dz (XZ plane only)
|
||||||
|
// Negative dot means object is behind the player
|
||||||
|
psyqo::FixedPoint<12> dot = forwardX * dx + forwardZ * dz;
|
||||||
|
// Object must be in front of the player (dot < 0 in the coordinate system
|
||||||
|
// because dx points FROM player TO object, and forward points where player faces)
|
||||||
|
// Actually: dx = playerX - objX, so it points FROM object TO player.
|
||||||
|
// We want the object in front, so we need -dx direction to align with forward.
|
||||||
|
// dot(forward, objDir) where objDir = obj - player = -dx, -dz
|
||||||
|
psyqo::FixedPoint<12> facingDot = -(forwardX * dx + forwardZ * dz);
|
||||||
|
if (facingDot.value <= 0) continue; // Object is behind the player
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distSq < closestDistSq) {
|
||||||
|
inRange = interactable;
|
||||||
closestDistSq = distSq;
|
closestDistSq = distSq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interact with closest
|
// Prompt canvas management: show only when in range AND can interact
|
||||||
if (closest != nullptr) {
|
int newPromptCanvas = -1;
|
||||||
triggerInteraction(getGameObject(closest->gameObjectIndex));
|
if (inRange && inRange->canInteract() && inRange->showPrompt() && inRange->promptCanvasName[0] != '\0') {
|
||||||
closest->triggerCooldown();
|
newPromptCanvas = m_uiSystem.findCanvas(inRange->promptCanvasName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newPromptCanvas != s_activePromptCanvas) {
|
||||||
|
// Hide old prompt
|
||||||
|
if (s_activePromptCanvas >= 0) {
|
||||||
|
m_uiSystem.setCanvasVisible(s_activePromptCanvas, false);
|
||||||
|
}
|
||||||
|
// Show new prompt
|
||||||
|
if (newPromptCanvas >= 0) {
|
||||||
|
m_uiSystem.setCanvasVisible(newPromptCanvas, true);
|
||||||
|
}
|
||||||
|
s_activePromptCanvas = newPromptCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the closest in-range interactable can be activated
|
||||||
|
if (!inRange || !inRange->canInteract()) return;
|
||||||
|
|
||||||
|
// Check if the correct button for this interactable was pressed
|
||||||
|
auto button = static_cast<psyqo::AdvancedPad::Button>(
|
||||||
|
static_cast<uint16_t>(inRange->interactButton));
|
||||||
|
if (!m_controls.wasButtonPressed(button)) return;
|
||||||
|
|
||||||
|
// Trigger the interaction
|
||||||
|
triggerInteraction(getGameObject(inRange->gameObjectIndex));
|
||||||
|
inRange->triggerCooldown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void psxsplash::SceneManager::triggerInteraction(GameObject* interactable) {
|
void psxsplash::SceneManager::triggerInteraction(GameObject* interactable) {
|
||||||
@@ -728,8 +725,9 @@ void psxsplash::SceneManager::clearScene() {
|
|||||||
m_audio.reset(); // Free SPU RAM and stop all voices
|
m_audio.reset(); // Free SPU RAM and stop all voices
|
||||||
m_collisionSystem.init(); // Re-init collision system
|
m_collisionSystem.init(); // Re-init collision system
|
||||||
m_cutsceneCount = 0;
|
m_cutsceneCount = 0;
|
||||||
|
s_activePromptCanvas = -1; // Reset prompt tracking
|
||||||
m_cutscenePlayer.init(nullptr, 0, nullptr, nullptr); // Reset cutscene player
|
m_cutscenePlayer.init(nullptr, 0, nullptr, nullptr); // Reset cutscene player
|
||||||
// BVH, WorldCollision, and NavRegions will be overwritten by next load
|
// BVH and NavRegions will be overwritten by next load
|
||||||
|
|
||||||
// Reset UI system (disconnect from renderer before splashpack data disappears)
|
// Reset UI system (disconnect from renderer before splashpack data disappears)
|
||||||
Renderer::GetInstance().SetUISystem(nullptr);
|
Renderer::GetInstance().SetUISystem(nullptr);
|
||||||
@@ -774,7 +772,6 @@ void psxsplash::SceneManager::shrinkBuffer() {
|
|||||||
for (auto& inter : m_interactables) inter = reloc(inter);
|
for (auto& inter : m_interactables) inter = reloc(inter);
|
||||||
|
|
||||||
m_bvh.relocate(delta);
|
m_bvh.relocate(delta);
|
||||||
m_worldCollision.relocate(delta);
|
|
||||||
m_navRegions.relocate(delta);
|
m_navRegions.relocate(delta);
|
||||||
|
|
||||||
m_rooms = reloc(m_rooms);
|
m_rooms = reloc(m_rooms);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "gameobject.hh"
|
#include "gameobject.hh"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "splashpack.hh"
|
#include "splashpack.hh"
|
||||||
#include "worldcollision.hh"
|
|
||||||
#include "navregion.hh"
|
#include "navregion.hh"
|
||||||
#include "audiomanager.hh"
|
#include "audiomanager.hh"
|
||||||
#include "interactable.hh"
|
#include "interactable.hh"
|
||||||
@@ -104,7 +103,6 @@ class SceneManager {
|
|||||||
psxsplash::SplashPackLoader m_loader;
|
psxsplash::SplashPackLoader m_loader;
|
||||||
CollisionSystem m_collisionSystem;
|
CollisionSystem m_collisionSystem;
|
||||||
BVHManager m_bvh; // Spatial acceleration for frustum culling
|
BVHManager m_bvh; // Spatial acceleration for frustum culling
|
||||||
WorldCollision m_worldCollision; // Triangle-level world collision (v7+)
|
|
||||||
NavRegionSystem m_navRegions; // Convex region navigation (v7+)
|
NavRegionSystem m_navRegions; // Convex region navigation (v7+)
|
||||||
uint16_t m_playerNavRegion = NAV_NO_REGION; // Current nav region for player
|
uint16_t m_playerNavRegion = NAV_NO_REGION; // Current nav region for player
|
||||||
|
|
||||||
@@ -153,11 +151,11 @@ class SceneManager {
|
|||||||
|
|
||||||
psyqo::FixedPoint<12, uint16_t> m_playerHeight;
|
psyqo::FixedPoint<12, uint16_t> m_playerHeight;
|
||||||
|
|
||||||
int32_t m_playerRadius; // Collision radius in fp12 (replaces hardcoded PLAYER_RADIUS)
|
int32_t m_playerRadius;
|
||||||
int32_t m_velocityY; // Vertical velocity in fp12 per second (negative = up)
|
int32_t m_velocityY;
|
||||||
int32_t m_gravityPerFrame; // Gravity velocity change per frame (fp12)
|
int32_t m_gravityPerFrame;
|
||||||
int32_t m_jumpVelocityRaw; // Initial jump velocity in fp12 per second
|
int32_t m_jumpVelocityRaw;
|
||||||
bool m_isGrounded; // On the ground (can jump)
|
bool m_isGrounded;
|
||||||
|
|
||||||
// Frame timing
|
// Frame timing
|
||||||
uint32_t m_lastFrameTime; // gpu.now() timestamp of previous frame
|
uint32_t m_lastFrameTime; // gpu.now() timestamp of previous frame
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "mesh.hh"
|
#include "mesh.hh"
|
||||||
#include "streq.hh"
|
#include "streq.hh"
|
||||||
#include "worldcollision.hh"
|
|
||||||
#include "navregion.hh"
|
#include "navregion.hh"
|
||||||
#include "renderer.hh"
|
#include "renderer.hh"
|
||||||
|
|
||||||
@@ -151,10 +150,20 @@ void SplashPackLoader::LoadSplashpack(uint8_t *data, SplashpackSceneSetup &setup
|
|||||||
cursor += sizeof(psxsplash::Interactable);
|
cursor += sizeof(psxsplash::Interactable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip over legacy world collision data if present in older binaries
|
||||||
if (header->worldCollisionMeshCount > 0) {
|
if (header->worldCollisionMeshCount > 0) {
|
||||||
uintptr_t addr = reinterpret_cast<uintptr_t>(cursor);
|
uintptr_t addr = reinterpret_cast<uintptr_t>(cursor);
|
||||||
cursor = reinterpret_cast<uint8_t*>((addr + 3) & ~3);
|
cursor = reinterpret_cast<uint8_t*>((addr + 3) & ~3);
|
||||||
cursor = const_cast<uint8_t*>(setup.worldCollision.initializeFromData(cursor));
|
// CollisionDataHeader: 20 bytes
|
||||||
|
const uint16_t meshCount = *reinterpret_cast<const uint16_t*>(cursor);
|
||||||
|
const uint16_t triCount = *reinterpret_cast<const uint16_t*>(cursor + 2);
|
||||||
|
const uint16_t chunkW = *reinterpret_cast<const uint16_t*>(cursor + 4);
|
||||||
|
const uint16_t chunkH = *reinterpret_cast<const uint16_t*>(cursor + 6);
|
||||||
|
cursor += 20; // CollisionDataHeader
|
||||||
|
cursor += meshCount * 32; // CollisionMeshHeader (32 bytes each)
|
||||||
|
cursor += triCount * 52; // CollisionTri (52 bytes each)
|
||||||
|
if (chunkW > 0 && chunkH > 0)
|
||||||
|
cursor += chunkW * chunkH * 4; // CollisionChunk (4 bytes each)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->navRegionCount > 0) {
|
if (header->navRegionCount > 0) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include "collision.hh"
|
#include "collision.hh"
|
||||||
#include "gameobject.hh"
|
#include "gameobject.hh"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "worldcollision.hh"
|
|
||||||
#include "navregion.hh"
|
#include "navregion.hh"
|
||||||
#include "audiomanager.hh"
|
#include "audiomanager.hh"
|
||||||
#include "interactable.hh"
|
#include "interactable.hh"
|
||||||
@@ -66,7 +65,6 @@ struct SplashpackSceneSetup {
|
|||||||
eastl::vector<const char*> audioClipNames;
|
eastl::vector<const char*> audioClipNames;
|
||||||
|
|
||||||
BVHManager bvh; // Spatial acceleration structure for culling
|
BVHManager bvh; // Spatial acceleration structure for culling
|
||||||
WorldCollision worldCollision;
|
|
||||||
NavRegionSystem navRegions;
|
NavRegionSystem navRegions;
|
||||||
psyqo::GTE::PackedVec3 playerStartPosition;
|
psyqo::GTE::PackedVec3 playerStartPosition;
|
||||||
psyqo::GTE::PackedVec3 playerStartRotation;
|
psyqo::GTE::PackedVec3 playerStartRotation;
|
||||||
|
|||||||
Reference in New Issue
Block a user