mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 08:00:25 +02:00
The VR first-person camera will animate the local vehicle's steering wheel by handing Aurora a rotated copy of one of the vehicle's position arrays. A draw picks up the copy only when it binds that exact array with the local vehicle's position matrix (per-position ownership for indexed-matrix draws), so opponents sharing the asset keep the original vertices. The copy takes the same padded upload path as the original and never touches the shared array cache. Ported from heurazy's mario-kart-wii-VR-port (GPL-3.0-or-later).
64 lines
2.9 KiB
C++
64 lines
2.9 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Ported from heurazy's mario-kart-wii-VR-port (GPL-3.0-or-later).
|
|
//
|
|
// The VR first-person camera animates the local vehicle's steering wheel by
|
|
// handing Aurora a rotated copy of one of the vehicle's position arrays. The
|
|
// copy applies only to a draw that binds that exact array *and* carries the
|
|
// local vehicle's model-view matrix, so an opponent sharing the asset keeps
|
|
// the original vertices. Everything here runs on the GX (command processor)
|
|
// thread; the set/clear entry points are posted there by the runtime.
|
|
#pragma once
|
|
#include "gx.hpp"
|
|
#include <vector>
|
|
#include <cstring>
|
|
#include <cmath>
|
|
#include <atomic>
|
|
#include <aurora/native_wheel_match.hpp>
|
|
namespace aurora::gx {
|
|
struct NativeWheelArray {
|
|
const void* source{};
|
|
std::vector<uint8_t> bytes;
|
|
std::array<float,12> modelView{};
|
|
gfx::Range uploaded{};
|
|
// Element stride of `uploaded`, which differs from the array's when the upload is padded.
|
|
uint32_t uploadedStride=0;
|
|
};
|
|
inline std::vector<NativeWheelArray> nativeWheelArrays;
|
|
inline uint32_t nativeWheelMatches=0;
|
|
inline std::atomic<uint32_t> nativeWheelLastMatches{0};
|
|
inline bool native_wheel_source(const void* source) {
|
|
for(const auto& replacement:nativeWheelArrays) if(source==replacement.source) return true;
|
|
return false;
|
|
}
|
|
inline NativeWheelArray* native_wheel_array(const AttrArray& array,const uint8_t* vertices,
|
|
uint32_t vertexBytes,uint32_t vertexStride,uint32_t positionOffset) {
|
|
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;
|
|
// 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;
|
|
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);
|
|
bool matches=true;
|
|
for(int i=0;i<12;++i) {
|
|
uint32_t bits;std::memcpy(&bits,&matrix[i],4);
|
|
if((bits&0x7f800000u)==0x7f800000u ||
|
|
std::abs(matrix[i]-replacement.modelView[i])>(i%4==3?0.1f:0.002f)) { matches=false;break; }
|
|
}
|
|
if(matches) matching|=uint16_t(1u<<slot);
|
|
}
|
|
if(!matching) continue;
|
|
if(indexedMatrix && !NativeWheelDrawMatches(
|
|
{static_cast<const uint8_t*>(array.data),array.size},
|
|
{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;
|
|
}
|
|
return nullptr;
|
|
}
|
|
}
|