mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 06:00:25 +02:00
The pure pieces of the first-person cockpit and hand steering, ported from
heurazy's mario-kart-wii-VR-port: the SteeringWheel grab/turn model, the
native wheel vertex rotation, the level seat stabiliser, the seated-eye and
wheel/handlebar geometry, and the XR_FB_hand_tracking_mesh loader. Adds
openxr_driving.h, the OpenXR-free snapshot the pacing thread will publish for
the guest thread, with the hand-off rule (a held wheel replaces the left
stick's X and releases that hand's grip for the game) and the wheel's
displayed angle.
New [vr] keys: first_person_seat (cockpit), cockpit_units_per_meter (100),
steering_wheel (true), native_steering_wheel (true), hand_steering (false)
and the seven wheel_* tuning keys. Nothing reads them yet.
The fresh-config template now writes the first-person defaults the
constants hold (50 / 1.5 / 0); d86dcb0 updated the constants but not the
template.
Tests: mkw_steering_wheel_tests (the fork's), mkw_vr_cockpit_tests,
mkw_vr_hand_steering_tests.
46 lines
2.2 KiB
C++
46 lines
2.2 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Ported from heurazy's mario-kart-wii-VR-port (GPL-3.0-or-later).
|
|
#pragma once
|
|
#include "vr/mkw_vr_first_person.h"
|
|
#include <vector>
|
|
|
|
namespace mkw::vr {
|
|
// A number of MKW karts bake the steering wheel into their single body bone.
|
|
// Find its thin disc around the authored hand targets, including the hub and
|
|
// spokes, and rotate only that disc. Work on a render copy, never guest assets.
|
|
inline unsigned RotateNativeWheelVertices(std::vector<detail::Vec3>& points,
|
|
detail::Vec3 center,float radius,float angle,const Mtx34* bodyCorrection=nullptr) {
|
|
if (!(radius>4 && radius<100) || !detail::IsFiniteFloat(&angle)) return 0;
|
|
if(bodyCorrection && !detail::IsFiniteMtx34(*bodyCorrection)) return 0;
|
|
float meanY=0,meanZ=0; unsigned count=0;
|
|
const auto candidate=[&](const detail::Vec3& p) {
|
|
return std::abs(p.x-center.x)<radius*1.5f && std::abs(p.y-center.y)<radius*1.5f &&
|
|
std::abs(p.z-center.z)<radius*0.9f;
|
|
};
|
|
for(const auto& p:points) if(candidate(p)) { meanY+=p.y; meanZ+=p.z; ++count; }
|
|
if(count<8) return 0;
|
|
meanY/=count; meanZ/=count;
|
|
float yy=0,yz=0;
|
|
for(const auto& p:points) if(candidate(p)) { yy+=(p.y-meanY)*(p.y-meanY); yz+=(p.y-meanY)*(p.z-meanZ); }
|
|
if(yy<radius*radius) return 0;
|
|
const float slope=std::clamp(yz/yy,-1.0f,1.0f);
|
|
center.z=meanZ+slope*(center.y-meanY);
|
|
const float inv=1/std::sqrt(1+slope*slope);
|
|
const detail::Vec3 up{0,inv,slope*inv},normal{0,-slope*inv,inv};
|
|
const float c=std::cos(angle),s=std::sin(angle);
|
|
unsigned changed=0;
|
|
for(auto& p:points) {
|
|
const detail::Vec3 delta{p.x-center.x,p.y-center.y,p.z-center.z};
|
|
const float x=delta.x,y=detail::Dot(delta,up),z=detail::Dot(delta,normal);
|
|
if(x*x+y*y>radius*radius*2.25f || std::abs(z)>radius*0.30f) continue;
|
|
const float rx=c*x-s*y,ry=s*x+c*y;
|
|
p={center.x+rx,center.y+up.y*ry+normal.y*z,center.z+up.z*ry+normal.z*z};
|
|
// The body may spin during tricks/damage while the seated reference
|
|
// stays level. Compensate only the wheel, leaving chassis animation intact.
|
|
if(bodyCorrection) p=detail::TransformPoint(*bodyCorrection,p.x,p.y,p.z);
|
|
++changed;
|
|
}
|
|
return changed;
|
|
}
|
|
} // namespace mkw::vr
|