mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 07:00:30 +02:00
Keep the cockpit wheel with the view and let the native wheel recover
Found on a Quest 3 through Virtual Desktop (VirtualDesktopXR, Vulkan): the race camera's view matched the scene camera exactly and the kart's own wheel animated (228 draws a frame took the copy), but during the race's opening pan no draw took it, the 30-frame fallback latched the VR wheel for that vehicle, and it stayed until the scene changed. The fallback now heals: copies keep being published, the VR wheel stands in only while draws are not taking them, and the vehicle's own wheel returns as soon as they are. Both switches are logged, a few per race. With first_person_rotation "yaw_pitch" or "full" the wheel copy and the hands' wheel geometry now ride in the view's own frame (the kart's orientation around the seat) instead of the level seat, so the wheel no longer tilts against the view on slopes. Aurora logs, after about half a second, five seconds and a minute of copies, how many draws bound a copied array (inside and outside its window), how many matched, and the closest position matrix against the expected one, so a mismatch says whether the array or the matrix differs.
This commit is contained in:
1 parent
0d07df14c9
commit
131da8a7a9
5 files changed
+145
-40
No files matched your search
@@ -21,6 +21,10 @@ extern "C" void aurora_clear_native_wheel_vertices() {
|
||||
aurora::gx::fifo::drain();
|
||||
aurora::gx::nativeWheelLastMatches.store(aurora::gx::nativeWheelMatches);
|
||||
aurora::gx::nativeWheelMatches = 0;
|
||||
aurora::gx::nativeWheelPreviousSources.clear();
|
||||
for (const auto& array : aurora::gx::nativeWheelArrays)
|
||||
aurora::gx::nativeWheelPreviousSources.push_back(array.source);
|
||||
aurora::gx::native_wheel_report();
|
||||
aurora::gx::nativeWheelArrays.clear();
|
||||
}
|
||||
extern "C" uint32_t aurora_native_wheel_draw_count() { return aurora::gx::nativeWheelLastMatches.load(); }
|
||||
@@ -38,6 +42,30 @@ extern "C" void aurora_set_native_wheel_vertices(const void* source, const void*
|
||||
// Single definition for the `Log` that gx.hpp declares for this directory.
|
||||
aurora::Module Log("aurora::gx");
|
||||
|
||||
namespace aurora::gx {
|
||||
// Called as a set is cleared: a line at about half a second, five seconds and
|
||||
// a minute of sets, with the matrices on the first report that saw a draw.
|
||||
void native_wheel_report() {
|
||||
auto& diagnostics=nativeWheelDiagnostics;
|
||||
++diagnostics.sets;
|
||||
++nativeWheelClears;
|
||||
if(nativeWheelClears!=30 && nativeWheelClears!=300 && nativeWheelClears!=3600) return;
|
||||
::Log.info("Native steering wheel: {} sets; draws binding a replaced array {} ({} with a larger range, {} outside a "
|
||||
"set); matched {}; closest position matrix off by {} ({} matrices)",
|
||||
diagnostics.sets,diagnostics.boundDraws,diagnostics.oversizeDraws,diagnostics.outsideDraws,
|
||||
diagnostics.matchedDraws,diagnostics.bestError,diagnostics.bestIndexed?"indexed":"current");
|
||||
if(diagnostics.boundDraws!=0 && nativeWheelReports++==0) {
|
||||
const auto& m=diagnostics.bestMatrix;
|
||||
const auto& e=diagnostics.expected;
|
||||
::Log.info("Native steering wheel: closest [{} {} {} {} | {} {} {} {} | {} {} {} {}] expected [{} {} {} {} | {} {} "
|
||||
"{} {} | {} {} {} {}]",
|
||||
m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9],m[10],m[11],
|
||||
e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9],e[10],e[11]);
|
||||
}
|
||||
diagnostics={};
|
||||
}
|
||||
} // namespace aurora::gx
|
||||
|
||||
static void GXWriteString(const char* label) {
|
||||
auto length = strlen(label);
|
||||
|
||||
|
||||
@@ -2422,6 +2422,8 @@ static void handle_draw_unmerged(GXPrimitive prim, GXVtxFmt fmt, u16 vtxCount, g
|
||||
}
|
||||
auto& array = g_gxState.arrays[i];
|
||||
const u32 uploadStride = padded_upload_stride(array.stride);
|
||||
if (i == GX_VA_POS && nativeWheelArrays.empty() && !nativeWheelPreviousSources.empty())
|
||||
UNLIKELY { native_wheel_note_outside(array.data); }
|
||||
if (i == GX_VA_POS && !nativeWheelArrays.empty())
|
||||
UNLIKELY {
|
||||
if (auto* nativeWheel = native_wheel_array(array, vertices, static_cast<u32>(vtxCount) * vtxStride, vtxStride,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// thread; the set/clear entry points are posted there by the runtime.
|
||||
#pragma once
|
||||
#include "gx.hpp"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
@@ -26,6 +27,49 @@ struct NativeWheelArray {
|
||||
inline std::vector<NativeWheelArray> nativeWheelArrays;
|
||||
inline uint32_t nativeWheelMatches=0;
|
||||
inline std::atomic<uint32_t> nativeWheelLastMatches{0};
|
||||
|
||||
// For the host log: why draws of the replaced arrays did or did not take them.
|
||||
struct NativeWheelDiagnostics {
|
||||
uint32_t sets=0; // replacement sets cleared since the last report
|
||||
uint32_t boundDraws=0; // draws that bound a replacement's source array
|
||||
uint32_t oversizeDraws=0; // ... whose bound range was larger than the replacement
|
||||
uint32_t outsideDraws=0; // draws that bound a cleared set's source while no set was active
|
||||
uint32_t matchedDraws=0;
|
||||
float bestError=INFINITY; // smallest largest-element difference of a position matrix
|
||||
bool bestIndexed=false;
|
||||
std::array<float,12> bestMatrix{};
|
||||
std::array<float,12> expected{};
|
||||
};
|
||||
inline NativeWheelDiagnostics nativeWheelDiagnostics;
|
||||
inline std::vector<const void*> nativeWheelPreviousSources;
|
||||
inline uint32_t nativeWheelClears=0;
|
||||
inline uint32_t nativeWheelReports=0;
|
||||
|
||||
inline void native_wheel_note_outside(const void* source) {
|
||||
for(const void* previous:nativeWheelPreviousSources)
|
||||
if(previous==source) { ++nativeWheelDiagnostics.outsideDraws;return; }
|
||||
}
|
||||
|
||||
inline void native_wheel_note_bound(const NativeWheelArray& replacement,bool indexedMatrix) {
|
||||
auto& diagnostics=nativeWheelDiagnostics;
|
||||
++diagnostics.boundDraws;
|
||||
for(uint32_t slot=0;slot<MaxPnMtx;++slot) {
|
||||
if(!indexedMatrix && slot!=g_gxState.currentPnMtx) continue;
|
||||
const auto* matrix=reinterpret_cast<const float*>(&g_gxState.pnMtx[slot].pos);
|
||||
float error=0;
|
||||
for(int i=0;i<12;++i) error=std::max(error,std::abs(matrix[i]-replacement.modelView[i]));
|
||||
if(error<diagnostics.bestError) {
|
||||
diagnostics.bestError=error;
|
||||
diagnostics.bestIndexed=indexedMatrix;
|
||||
std::memcpy(diagnostics.bestMatrix.data(),matrix,sizeof(float)*12);
|
||||
diagnostics.expected=replacement.modelView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called as a set is cleared (GXAurora.cpp): one host log line at about half a
|
||||
// second, five seconds and a minute of sets.
|
||||
void native_wheel_report();
|
||||
inline bool native_wheel_source(const void* source) {
|
||||
for(const auto& replacement:nativeWheelArrays) if(source==replacement.source) return true;
|
||||
return false;
|
||||
@@ -35,7 +79,9 @@ inline NativeWheelArray* native_wheel_array(const AttrArray& array,const uint8_t
|
||||
const bool indexedMatrix=g_gxState.vtxDesc[GX_VA_PNMTXIDX]==GX_DIRECT;
|
||||
if(!indexedMatrix && g_gxState.currentPnMtx>=MaxPnMtx) return nullptr;
|
||||
for(auto& replacement:nativeWheelArrays) {
|
||||
if(array.data!=replacement.source || array.size>replacement.bytes.size()) continue;
|
||||
if(array.data!=replacement.source) continue;
|
||||
if(array.size>replacement.bytes.size()) { ++nativeWheelDiagnostics.oversizeDraws;continue; }
|
||||
native_wheel_note_bound(replacement,indexedMatrix);
|
||||
// A matching asset alone would also animate an opponent. Multi-joint
|
||||
// models need a per-position ownership check, not a blanket exclusion.
|
||||
uint16_t matching=0;
|
||||
@@ -56,7 +102,7 @@ inline NativeWheelArray* native_wheel_array(const AttrArray& array,const uint8_t
|
||||
{replacement.bytes.data(),array.size},array.stride,
|
||||
{vertices,vertexBytes},vertexStride,positionOffset,
|
||||
g_gxState.vtxDesc[GX_VA_POS]==GX_INDEX8?1:2,matching)) continue;
|
||||
++nativeWheelMatches;return &replacement;
|
||||
++nativeWheelMatches;++nativeWheelDiagnostics.matchedDraws;return &replacement;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user