Optimize rollback sync-test performance (#86)
## Summary - remove immutable stage geometry and derived animation/collision data from rollback snapshots - avoid a duplicate full skeletal hierarchy traversal during root-motion sampling - cache root-motion cycle deltas per animation clip - optimize the game crate in development builds - make Tracy profiling opt-in via the `tracy` feature Reviewed-on: #86 Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
This commit was merged in pull request #86.
This commit is contained in:
@@ -127,6 +127,8 @@ pub struct FighterBoneMatrices {
|
||||
/// pose has the root translation removed.
|
||||
previous_root_motion_translation: Option<FGVec3>,
|
||||
root_motion_delta: crate::math::vec3::FGVec3,
|
||||
cached_root_motion_kind: Option<AnimKind>,
|
||||
cached_root_motion_cycle_delta: FGVec3,
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Debug, Default)]
|
||||
@@ -366,12 +368,6 @@ impl FighterBoneMatrices {
|
||||
.expect("configured root motion bone should exist"),
|
||||
)
|
||||
};
|
||||
self.model_matrices.resize(local.len(), None);
|
||||
self.model_matrices.fill(None);
|
||||
for index in 0..local.len() {
|
||||
resolve_model_transform(index, parents, local, &mut self.model_matrices)
|
||||
.expect("baked bone hierarchy should be valid");
|
||||
}
|
||||
let model_scale = FixedMat4 {
|
||||
cols: [
|
||||
[model_scale, FGi32::ZERO, FGi32::ZERO, FGi32::ZERO],
|
||||
@@ -380,13 +376,16 @@ impl FighterBoneMatrices {
|
||||
[FGi32::ZERO, FGi32::ZERO, FGi32::ZERO, FGi32::ONE],
|
||||
],
|
||||
};
|
||||
// Root motion only needs the configured bone's model transform. Resolve
|
||||
// that ancestry first, then do the normal full-pose pass once below.
|
||||
// Previously the complete hierarchy was resolved once before removing
|
||||
// root translation and once afterwards.
|
||||
let raw_root_motion_translation = root_index.map(|root_index| {
|
||||
model_scale
|
||||
.mul(
|
||||
self.model_matrices[root_index]
|
||||
.expect("baked bone hierarchy should be valid"),
|
||||
)
|
||||
.get_translation()
|
||||
self.model_matrices.resize(local.len(), None);
|
||||
self.model_matrices.fill(None);
|
||||
let root = resolve_model_transform(root_index, parents, local, &mut self.model_matrices)
|
||||
.expect("baked bone hierarchy should be valid");
|
||||
model_scale.mul(root).get_translation()
|
||||
});
|
||||
|
||||
// Gameplay owns the root's displacement. Keep rotation and scale in
|
||||
@@ -394,11 +393,12 @@ impl FighterBoneMatrices {
|
||||
// used by visuals and gameplay volumes.
|
||||
if let Some(root_index) = root_index {
|
||||
self.local_matrices[root_index].translate(FGVec3::ZERO);
|
||||
self.model_matrices.fill(None);
|
||||
for index in 0..local.len() {
|
||||
resolve_model_transform(index, parents, &self.local_matrices, &mut self.model_matrices)
|
||||
.expect("baked bone hierarchy should be valid");
|
||||
}
|
||||
}
|
||||
self.model_matrices.resize(local.len(), None);
|
||||
self.model_matrices.fill(None);
|
||||
for index in 0..local.len() {
|
||||
resolve_model_transform(index, parents, &self.local_matrices, &mut self.model_matrices)
|
||||
.expect("baked bone hierarchy should be valid");
|
||||
}
|
||||
self.matrices.clear();
|
||||
self.matrices.extend(
|
||||
@@ -517,9 +517,16 @@ fn sample_fighter_bone_matrices(
|
||||
let manifest = manifests
|
||||
.get(&fighter.manifest)
|
||||
.expect("fighter manifest should be loaded before the match starts");
|
||||
let root_motion_cycle_delta = baked
|
||||
.root_motion_cycle_delta(frame.kind, &manifest.root_motion_bone, manifest.model_scale)
|
||||
.unwrap_or(FGVec3::ZERO);
|
||||
let root_motion_cycle_delta = if matrices.cached_root_motion_kind == Some(frame.kind) {
|
||||
matrices.cached_root_motion_cycle_delta
|
||||
} else {
|
||||
let delta = baked
|
||||
.root_motion_cycle_delta(frame.kind, &manifest.root_motion_bone, manifest.model_scale)
|
||||
.unwrap_or(FGVec3::ZERO);
|
||||
matrices.cached_root_motion_kind = Some(frame.kind);
|
||||
matrices.cached_root_motion_cycle_delta = delta;
|
||||
delta
|
||||
};
|
||||
let root_motion_loop_frame_count = baked
|
||||
.frame_count(frame.kind)
|
||||
.map(|count| count.saturating_sub(1).max(1));
|
||||
|
||||
Reference in New Issue
Block a user