Skip to content

Commit 48113d4

Browse files
committed
Improve performance of roomscale implementation
1 parent da2bfb2 commit 48113d4

1 file changed

Lines changed: 39 additions & 45 deletions

File tree

src/hooking/entity_controller.cpp

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ struct RoomscaleDebugBody {
116116
float groundProbeDown = 0.75f;
117117
};
118118

119+
static RoomscaleDebugBody s_roomscaleResolveBody = {};
120+
static bool s_roomscaleShouldShowPhysicsDebug = false;
121+
119122
struct RoomscaleDebugPalette {
120123
uint32_t pathColor = 0;
121124
uint32_t pathSecondaryColor = 0;
@@ -181,14 +184,9 @@ static RoomscaleDebugPalette GetRoomscaleDebugPalette(bool isGroundProbe, bool i
181184
};
182185
}
183186

184-
static RoomscaleDebugBody GetRoomscaleDebugBody() {
187+
static RoomscaleDebugBody BuildRoomscaleDebugBody(const PlayerBase& player) {
185188
RoomscaleDebugBody body = {};
186189

187-
PlayerBase player = {};
188-
if (!GameUtils::TryReadPlayerBase(player)) {
189-
return body;
190-
}
191-
192190
const glm::fvec3 localMin = player.aabb.min.getLE();
193191
const glm::fvec3 localMax = player.aabb.max.getLE();
194192
const glm::fvec3 localHalfExtents = (localMax - localMin) * 0.5f;
@@ -208,6 +206,11 @@ static RoomscaleDebugBody GetRoomscaleDebugBody() {
208206
return body;
209207
}
210208

209+
static void CacheRoomscaleResolveContext(const PlayerBase& player) {
210+
s_roomscaleResolveBody = BuildRoomscaleDebugBody(player);
211+
s_roomscaleShouldShowPhysicsDebug = GetSettings().ShouldShowRoomPhysics();
212+
}
213+
211214
static bool IsRoomscaleSweepPhase(RoomscaleResolvePhase phase) {
212215
return phase == RoomscaleResolvePhase_ForwardSweep || phase == RoomscaleResolvePhase_StepUpSweep || phase == RoomscaleResolvePhase_StepForwardSweep;
213216
}
@@ -409,12 +412,11 @@ static bool IsRoomscaleGroundProbe(const RoomscaleRaycastScratch& scratch) {
409412
return scratch.queryType.getLE() != RoomscaleQueryType_Sweep;
410413
}
411414

412-
static void DrawRoomscaleDebugCast(const RoomscaleRaycastScratch& scratch, bool isProbeOnly) {
413-
if (!GetSettings().ShouldShowRoomPhysics() || IsRoomscaleGroundProbe(scratch)) {
415+
static void DrawRoomscaleDebugCast(const RoomscaleRaycastScratch& scratch, const RoomscaleDebugBody& body, bool isProbeOnly, bool shouldShowRoomPhysics) {
416+
if (!shouldShowRoomPhysics || IsRoomscaleGroundProbe(scratch)) {
414417
return;
415418
}
416419

417-
const RoomscaleDebugBody body = GetRoomscaleDebugBody();
418420
const RoomscaleDebugPalette palette = GetRoomscaleDebugPalette(false, isProbeOnly);
419421
const glm::fvec3 castFrom = scratch.castFrom.getLE();
420422
const glm::fvec3 castTo = castFrom + scratch.castDelta.getLE();
@@ -426,8 +428,8 @@ static void DrawRoomscaleDebugCast(const RoomscaleRaycastScratch& scratch, bool
426428
DrawRoomscaleDebugPositionMarker(castTo, 0.04f, palette.pathSecondaryColor, true);
427429
}
428430

429-
static void DrawRoomscaleDebugCastResult(const RoomscaleRaycastScratch& scratch, bool isProbeOnly, bool hadHit, bool acceptedHit) {
430-
if (!GetSettings().ShouldShowRoomPhysics()) {
431+
static void DrawRoomscaleDebugCastResult(const RoomscaleRaycastScratch& scratch, bool isProbeOnly, bool hadHit, bool acceptedHit, bool shouldShowRoomPhysics) {
432+
if (!shouldShowRoomPhysics) {
431433
return;
432434
}
433435

@@ -505,6 +507,8 @@ static void ClearRoomscaleResolveState() {
505507
s_roomscaleState.remainingWorldDelta = glm::fvec3(0.0f);
506508
s_roomscaleState.attemptIndex = 0;
507509
s_roomscaleState.maxAttempts = 0;
510+
s_roomscaleResolveBody = {};
511+
s_roomscaleShouldShowPhysicsDebug = false;
508512
ResetRoomscaleActiveStep();
509513
}
510514

@@ -625,7 +629,7 @@ static void PrimeRoomscaleBaseline(const glm::fvec3& headPos) {
625629
UpdateRoomscaleFade();
626630
}
627631

628-
static bool ShouldDrivePlayerBodyWithVR(const glm::fvec3& currentHeadPos, PlayerBase& player) {
632+
static bool ShouldDrivePlayerBodyWithVR(const glm::fvec3& currentHeadPos, const PlayerBase& player) {
629633
if (!CemuHooks::IsFirstPerson()) {
630634
SetRoomscaleBodyDriveMode(RoomscaleBodyDriveMode::DisabledNotFirstPerson);
631635
PrimeRoomscaleBaseline(currentHeadPos);
@@ -644,25 +648,12 @@ static bool ShouldDrivePlayerBodyWithVR(const glm::fvec3& currentHeadPos, Player
644648
return false;
645649
}
646650

647-
auto* renderer = VRManager::instance().XR->GetRenderer();
648-
if (renderer == nullptr) {
649-
SetRoomscaleBodyDriveMode(RoomscaleBodyDriveMode::DisabledNoRenderer);
650-
PrimeRoomscaleBaseline(currentHeadPos);
651-
return false;
652-
}
653-
654651
if (!VRManager::instance().XR->m_capabilities.supportsPositional) {
655652
SetRoomscaleBodyDriveMode(RoomscaleBodyDriveMode::DisabledNoPositional);
656653
PrimeRoomscaleBaseline(currentHeadPos);
657654
return false;
658655
}
659656

660-
if (!GameUtils::TryReadPlayerBase(player)) {
661-
SetRoomscaleBodyDriveMode(RoomscaleBodyDriveMode::DisabledNoPlayer);
662-
PrimeRoomscaleBaseline(currentHeadPos);
663-
return false;
664-
}
665-
666657
PlayerMoveBitFlags moveBits = player.moveBitFlags.getLE();
667658
OpenXR::GameState gameState = VRManager::instance().XR->m_gameState.load();
668659
bool shouldDisablePlayerBodyDrive = gameState.is_climbing || gameState.is_paragliding || gameState.is_riding_mount || HAS_FLAG(moveBits, PlayerMoveBitFlags::IS_SWIMMING_OR_CLIMBING | PlayerMoveBitFlags::IS_SWIMMING);
@@ -676,16 +667,11 @@ static bool ShouldDrivePlayerBodyWithVR(const glm::fvec3& currentHeadPos, Player
676667
return true;
677668
}
678669

679-
static bool TryGetRoomscaleMoveDelta(uint32_t controller, glm::fvec3& currentHeadPos, glm::fvec3& roomDelta, glm::fvec3& worldDelta) {
670+
static bool TryGetRoomscaleMoveDelta(const PlayerBase& player, glm::fvec3& currentHeadPos, glm::fvec3& roomDelta, glm::fvec3& worldDelta) {
680671
currentHeadPos = glm::fvec3(0.0f);
681672
roomDelta = glm::fvec3(0.0f);
682673
worldDelta = glm::fvec3(0.0f);
683674

684-
uint32_t playerController = 0;
685-
if (!GameUtils::TryGetPlayerCharacterController(playerController) || controller != playerController) {
686-
return false;
687-
}
688-
689675
std::optional<glm::fvec3> currentHeadPosOpt = TryGetCurrentHeadPos();
690676
if (!currentHeadPosOpt.has_value()) {
691677
ResetRoomscaleState();
@@ -695,7 +681,6 @@ static bool TryGetRoomscaleMoveDelta(uint32_t controller, glm::fvec3& currentHea
695681
currentHeadPos = currentHeadPosOpt.value();
696682
s_roomscaleState.trackedHeadPos = currentHeadPos;
697683

698-
PlayerBase player = {};
699684
if (!ShouldDrivePlayerBodyWithVR(currentHeadPos, player)) {
700685
return false;
701686
}
@@ -762,21 +747,23 @@ void CemuHooks::hook_BeginRoomscaleMovement(PPCInterpreter_t* hCPU) {
762747
hCPU->instructionPointer = hCPU->sprNew.LR;
763748

764749
uint32_t controller = hCPU->gpr[3];
765-
uint32_t scratchPtr = hCPU->gpr[4];
766-
RoomscaleRaycastScratch scratch = {};
767-
writeMemory(scratchPtr, &scratch);
768750
hCPU->gpr[3] = RoomscaleHookResult_Skip;
769751
ClearRoomscaleResolveState();
770752

771-
uint32_t playerController = 0;
772-
if (!GameUtils::TryGetPlayerCharacterController(playerController) || controller != playerController) {
753+
PlayerBase player = {};
754+
if (!GameUtils::TryReadPlayerBase(player)) {
755+
return;
756+
}
757+
758+
uint32_t playerController = GameUtils::ResolveActorPhysicsController(player);
759+
if (playerController == 0 || controller != playerController) {
773760
return;
774761
}
775762

776763
glm::fvec3 currentHeadPos = {};
777764
glm::fvec3 roomDelta = {};
778765
glm::fvec3 worldDelta = {};
779-
if (!TryGetRoomscaleMoveDelta(controller, currentHeadPos, roomDelta, worldDelta)) {
766+
if (!TryGetRoomscaleMoveDelta(player, currentHeadPos, roomDelta, worldDelta)) {
780767
glm::fvec3 residual = GetRoomscaleResidual();
781768
glm::fvec3 residualWorldDelta = GetRoomscaleRoomToWorldRotation() * residual;
782769
residualWorldDelta.y = 0.0f;
@@ -796,6 +783,7 @@ void CemuHooks::hook_BeginRoomscaleMovement(PPCInterpreter_t* hCPU) {
796783
s_roomscaleState.maxAttempts = maxAttempts;
797784
s_roomscaleState.isResolving = true;
798785
s_roomscaleState.isProbeOnly = true;
786+
CacheRoomscaleResolveContext(player);
799787
hCPU->gpr[3] = RoomscaleHookResult_Cast;
800788
BetterVRProfiler::BeginSpan(BetterVRProfiler::Section::RoomscaleResolve);
801789
return;
@@ -811,6 +799,7 @@ void CemuHooks::hook_BeginRoomscaleMovement(PPCInterpreter_t* hCPU) {
811799
s_roomscaleState.maxAttempts = maxAttempts;
812800
s_roomscaleState.isResolving = true;
813801
s_roomscaleState.isProbeOnly = false;
802+
CacheRoomscaleResolveContext(player);
814803
hCPU->gpr[3] = RoomscaleHookResult_Cast;
815804
BetterVRProfiler::BeginSpan(BetterVRProfiler::Section::RoomscaleResolve);
816805
}
@@ -850,7 +839,7 @@ void CemuHooks::hook_PrepareRoomscaleRaycast(PPCInterpreter_t* hCPU) {
850839
return;
851840
}
852841

853-
const RoomscaleDebugBody body = GetRoomscaleDebugBody();
842+
const RoomscaleDebugBody& body = s_roomscaleResolveBody;
854843
const glm::fvec3 currentWorldPos = scratch.currentPos.getLE();
855844
const RoomscaleResolvePhase phase = s_roomscaleState.resolvePhase;
856845

@@ -885,7 +874,7 @@ void CemuHooks::hook_PrepareRoomscaleRaycast(PPCInterpreter_t* hCPU) {
885874
PrepareRoomscaleSupportProbe(scratch, body, probeBodyPos);
886875
}
887876

888-
DrawRoomscaleDebugCast(scratch, s_roomscaleState.isProbeOnly);
877+
DrawRoomscaleDebugCast(scratch, body, s_roomscaleState.isProbeOnly, s_roomscaleShouldShowPhysicsDebug);
889878
writeMemory(scratchPtr, &scratch);
890879
hCPU->gpr[3] = RoomscaleHookResult_Cast;
891880
}
@@ -915,8 +904,6 @@ void CemuHooks::hook_ConsumeRoomscaleRaycast(PPCInterpreter_t* hCPU) {
915904
return;
916905
}
917906

918-
RoomscaleRaycastScratch scratch = {};
919-
readMemory(scratchPtr, &scratch);
920907
uint32_t remainingSteps = s_roomscaleState.maxAttempts - s_roomscaleState.attemptIndex;
921908
if (remainingSteps == 0) {
922909
ClearRoomscaleResolveState();
@@ -925,7 +912,12 @@ void CemuHooks::hook_ConsumeRoomscaleRaycast(PPCInterpreter_t* hCPU) {
925912
}
926913

927914
if (IsRoomscaleSweepPhase(s_roomscaleState.resolvePhase)) {
928-
DrawRoomscaleDebugCastResult(scratch, s_roomscaleState.isProbeOnly, hadHit, false);
915+
if (s_roomscaleShouldShowPhysicsDebug) {
916+
RoomscaleRaycastScratch scratch = {};
917+
readMemory(scratchPtr, &scratch);
918+
DrawRoomscaleDebugCastResult(scratch, s_roomscaleState.isProbeOnly, hadHit, false, s_roomscaleShouldShowPhysicsDebug);
919+
}
920+
929921
if (hadHit) {
930922
s_roomscaleState.currentStepBlockedByCollision = true;
931923
if (s_roomscaleState.resolvePhase == RoomscaleResolvePhase_ForwardSweep) {
@@ -952,12 +944,14 @@ void CemuHooks::hook_ConsumeRoomscaleRaycast(PPCInterpreter_t* hCPU) {
952944
return;
953945
}
954946

955-
const RoomscaleDebugBody body = GetRoomscaleDebugBody();
947+
RoomscaleRaycastScratch scratch = {};
948+
readMemory(scratchPtr, &scratch);
949+
const RoomscaleDebugBody& body = s_roomscaleResolveBody;
956950
const bool isStepProbe = s_roomscaleState.resolvePhase == RoomscaleResolvePhase_StepDownSupportProbe;
957951
const float maxGroundRise = isStepProbe ? (kRoomscaleStepUpHeight + kRoomscaleGroundSnapMaxRise) : kRoomscaleGroundSnapMaxRise;
958952
RoomscaleSupportState support = {};
959953
const bool hasSupport = hadHit && TryBuildRoomscaleSupportState(body, scratch.currentPos.getLE(), maxGroundRise, scratch, support);
960-
DrawRoomscaleDebugCastResult(scratch, s_roomscaleState.isProbeOnly, hadHit, hasSupport);
954+
DrawRoomscaleDebugCastResult(scratch, s_roomscaleState.isProbeOnly, hadHit, hasSupport, s_roomscaleShouldShowPhysicsDebug);
961955

962956
if (!hasSupport) {
963957
if (!isStepProbe) {

0 commit comments

Comments
 (0)