mirror of
https://github.com/SK8-ENGINE/skate-3-rust-engine.git
synced 2026-10-26 19:47:44 +00:00
Publish native grind direction and conditioned camera contact
This commit is contained in:
1 parent
685d55601e
commit
d39703e48c
4 files changed
+121
-8
No files matched your search
@@ -2,7 +2,7 @@
|
||||
//! Reset82DE53F0 runs before the actual producers82DB6EC0/82D3A388.
|
||||
use super::{GamePhysics, SkaterRuntime};
|
||||
use crate::camera::{
|
||||
CameraAirOutput, CameraAnimationOutput, CameraEventsOutput, CameraGrindOutput,
|
||||
CameraAirOutput, CameraAnimationOutput, CameraEventsOutput,
|
||||
CameraOffboardOutput, CameraPreferences, CameraPublicationInputs, CameraStateOutput,
|
||||
};
|
||||
use skate_core::{
|
||||
@@ -15,11 +15,16 @@ use skate_core::{
|
||||
/// The user's selected normal High camera is graph type1. This custom world
|
||||
/// has no road/ledge/camera-volume annotations or other moving actors.
|
||||
pub(crate) fn advance(
|
||||
physics: &GamePhysics,
|
||||
physics: &mut GamePhysics,
|
||||
skater: &SkaterRuntime,
|
||||
feedback: &PhysicalFeedback,
|
||||
camera: &mut crate::camera::CameraRuntime,
|
||||
) -> Result<(), String> {
|
||||
//Once per physical publication, preserving conditioner history across
|
||||
//direct grind-type changes and invalidating it on the first non-grind tick.
|
||||
physics.grind.advance_camera(
|
||||
skater.player_input.processed.vectors_400_416[0].map(f32::from_bits),
|
||||
)?;
|
||||
let inputs = publish(
|
||||
physics,
|
||||
skater,
|
||||
@@ -137,12 +142,9 @@ pub(crate) fn publish(
|
||||
use_trajectory_331: 0,
|
||||
dropping_in_334: 0,
|
||||
},
|
||||
grinds: CameraGrindOutput {
|
||||
//Reset82DE3518 loads original world-X literal82139A10.
|
||||
direction_0: [1.0, 0.0, 0.0, 0.0],
|
||||
camera_target_96: [0.0; 4],
|
||||
grinding_316: u8::from(matches!(physical.grinds.words_136_140[1], 1 | 2)),
|
||||
},
|
||||
//Shared grind Fill82D40EA0 publishes the directed rail tangent;
|
||||
//conditioner82DF0640 supplies the continuous contact anchor.
|
||||
grinds: physics.grind.camera_output(),
|
||||
events: CameraEventsOutput {
|
||||
intent_51: bit(intents, 28),
|
||||
preparing_52: bit(intents, 27),
|
||||
|
||||
@@ -17,7 +17,10 @@ use skate_core::{
|
||||
};
|
||||
use skate_data::collections::Collections;
|
||||
type V = [f32; 4];
|
||||
#[path = "grind_camera.rs"]
|
||||
mod camera;
|
||||
pub(crate) struct Runtime {
|
||||
camera: camera::GrindCamera,
|
||||
primitives: Vec<Primitive>,
|
||||
pub candidate: Option<FiftyFiftyCandidate>,
|
||||
pub name: String,
|
||||
@@ -50,6 +53,7 @@ impl Runtime {
|
||||
.words::<8>("physics_grinds", "default", "PinVsSlope")?
|
||||
.map(f32::from_bits);
|
||||
Ok(Self {
|
||||
camera: camera::GrindCamera::default(),
|
||||
primitives: crate::grind_world::primitives(map)?,
|
||||
candidate: None,
|
||||
name: String::new(),
|
||||
@@ -98,6 +102,23 @@ impl Runtime {
|
||||
diagnostic_tick: 0,
|
||||
})
|
||||
}
|
||||
pub fn advance_camera(&mut self, velocity: V) -> Result<(), String> {
|
||||
if self.active {
|
||||
let contact = self.candidate.ok_or("Grind camera needs active contact")?;
|
||||
self.camera.update(contact, self.primitives[contact.primitive], self.kind, velocity);
|
||||
} else {
|
||||
self.camera.exit();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn camera_output(&self) -> crate::camera::CameraGrindOutput {
|
||||
crate::camera::CameraGrindOutput {
|
||||
//Reset82DE3518 defaults still apply outside the active state.
|
||||
direction_0: if self.active { self.camera.direction } else { [1.0, 0.0, 0.0, 0.0] },
|
||||
camera_target_96: if self.active { self.camera.target } else { [0.0; 4] },
|
||||
grinding_316: u8::from(self.active),
|
||||
}
|
||||
}
|
||||
pub fn output(&self) -> GrindState {
|
||||
if !self.active {
|
||||
return GrindState::default();
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//! TU3 grind direction82D87460 and contact-point conditioner82DF0640.
|
||||
use skate_core::physics::grind_contact::{FiftyFiftyCandidate, Primitive};
|
||||
use skate_core::riding::ground_correction_math::dot_product;
|
||||
type V = [f32; 4];
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct GrindCamera {
|
||||
pub direction: V,
|
||||
pub target: V,
|
||||
previous_target: V,
|
||||
offset: V,
|
||||
midpoint: V,
|
||||
kind: u32,
|
||||
active: bool,
|
||||
}
|
||||
impl GrindCamera {
|
||||
pub fn exit(&mut self) {
|
||||
//82DF0610/82DF07EC invalidate history without erasing the rail tangent.
|
||||
self.active = false;
|
||||
}
|
||||
|
||||
pub fn update(&mut self, contact: FiftyFiftyCandidate, edge: Primitive, kind: u32, velocity: V) {
|
||||
//82D37048 supplies the normalized primitive tangent, independently of
|
||||
//the deck's facing direction (including backwards50-50s/boardslides).
|
||||
let delta: V = core::array::from_fn(|i| edge.end[i] - edge.start[i]);
|
||||
let length = dot_product(delta, delta).sqrt();
|
||||
let mut direction = if length > 0.0 { delta.map(|v| v / length) } else { self.direction };
|
||||
let along = dot_product(direction, velocity);
|
||||
if along < 0.0 {
|
||||
direction = direction.map(|v| -v);
|
||||
}
|
||||
//82D874F0: native literals820641A8=.1 and822F8E94=-.9.
|
||||
if along.abs() < 0.1 && dot_product(self.direction, direction) < -0.9 {
|
||||
direction = direction.map(|v| -v);
|
||||
}
|
||||
self.direction = direction;
|
||||
|
||||
let midpoint: V = core::array::from_fn(|i| (edge.start[i] + edge.end[i]) * 0.5);
|
||||
if !self.active {
|
||||
self.offset = [0.0; 4];
|
||||
self.target = contact.centre;
|
||||
self.previous_target = contact.centre;
|
||||
} else if kind != self.kind || midpoint[..3] != self.midpoint[..3] {
|
||||
//Preserve extrapolated motion across a change of contact owner.
|
||||
self.offset = core::array::from_fn(|i| {
|
||||
self.target[i] + (self.target[i] - self.previous_target[i]) - contact.centre[i]
|
||||
});
|
||||
}
|
||||
//Constructor82DF24CC loads literal82072818, .95 per physical tick.
|
||||
//This decays a contact discontinuity, not ordinary camera movement.
|
||||
self.offset = self.offset.map(|v| v * 0.95);
|
||||
self.previous_target = self.target;
|
||||
self.target = core::array::from_fn(|i| contact.centre[i] + self.offset[i]);
|
||||
self.midpoint = midpoint;
|
||||
self.kind = kind;
|
||||
self.active = true;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user