### AnimationPlayer Usage Example Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/animation/struct.AnimationPlayer.html Demonstrates creating an AnimationPlayer with a clip, starting playback, and updating the player over time. ```rust use oxiphysics::animation::{Vec3Track, EaseKind, AnimationPlayer, AnimationClip, BodyAnimation}; let mut t = Vec3Track::new(false); t.push_keyframe(0.0, [0.0, 0.0, 0.0], EaseKind::Linear); t.push_keyframe(2.0, [10.0, 0.0, 0.0], EaseKind::Linear); let clip = AnimationClip::new("slide", vec![BodyAnimation::new("box").with_position(t)]); let mut player = AnimationPlayer::new(clip); player.play(); player.update(1.0); assert!(!player.is_finished()); // still playing at t=1 player.update(1.0); assert!(player.is_finished()); // reached t=2 ``` -------------------------------- ### SimRecorder::begin_step Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/replay/struct.SimRecorder.html Marks the start of a new simulation step. ```APIDOC ## pub fn begin_step(&mut self, dt: f64) ### Description Mark the start of a new step with time step `dt`. Must be followed by zero or more `record_*` calls and then `end_step`. ``` -------------------------------- ### Initialize and Apply Buoyancy Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/buoyancy/struct.BuoyancyWorld.html Example showing how to create a world, add a fluid, define a body, and calculate buoyancy forces. ```rust use oxiphysics::buoyancy::{BuoyancyWorld, BuoyantBody, BuoyantShape}; let mut world = BuoyancyWorld::new(9.81); world.add_fluid([-10.0, -5.0, -10.0], [10.0, 0.0, 10.0], 1000.0, 0.0); let body = BuoyantBody { id: 1, position: [0.0, -0.5, 0.0], velocity: [0.0; 3], angular_velocity: [0.0; 3], mass: 5.0, shape: BuoyantShape::Sphere { radius: 0.5 }, }; let result = world.apply(&[body]); println!("{result:?}"); ``` -------------------------------- ### SpatialGrid Usage Example Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/spatial_grid/index.html Demonstrates initializing a SpatialGrid, inserting entries, and performing a radius query to filter nearby items. ```rust use oxiphysics::spatial_grid::SpatialGrid; let mut grid = SpatialGrid::new(5.0); // 5 m cells grid.insert(0, [1.0, 0.0, 2.0]); grid.insert(1, [3.0, 0.0, -1.0]); grid.insert(2, [100.0, 0.0, 100.0]); // far away let hits = grid.query_radius([0.0, 0.0, 0.0], 5.0); assert!(hits.contains(&0)); assert!(hits.contains(&1)); assert!(!hits.contains(&2)); ``` -------------------------------- ### Rope Simulation Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/rope/index.html Example of initializing a rope with 6 links and performing a simulation step. ```APIDOC ## Rope Simulation Example ### Description Initializes a rope of 6 links hanging from a fixed world position and iterates the simulation using Verlet integration. ### Usage ```rust use oxiphysics::rope::{AnchorKind, Rope}; // Rope of 6 links hanging from [0, 5, 0], segment rest-length 1 m. let mut rope = Rope::new([0.0, 5.0, 0.0], 6, 1.0, 1.0).expect("valid rope"); rope.anchor_head = Some(AnchorKind::World([0.0, 5.0, 0.0])); let no_bodies = &(|_: u64| -> Option<[f64; 3]> { None }); let dt = 1.0 / 60.0; for _ in 0..200 { rope.step(dt, no_bodies); } ``` ``` -------------------------------- ### Folded Stacks Format Example Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/profiler/struct.FrameReport.html Example output format for the to_folded_stacks method. ```text root;physics;collision 4200 ``` -------------------------------- ### FractalNoise Usage Example Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/noise/struct.FractalNoise.html Demonstrates initializing a FractalNoise instance, configuring its parameters, and sampling a value. ```rust use oxiphysics::noise::FractalNoise; let mut n = FractalNoise::new(7, 6); n.persistence = 0.5; n.lacunarity = 2.0; let v = n.sample(0.5, 1.5, 2.5); assert!(v >= -1.0 && v <= 1.0); ``` -------------------------------- ### Construct Box from raw pointer Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Examples demonstrating how to recreate a Box from a raw pointer or manually allocate memory for a Box. ```rust #![feature(allocator_api)] use std::alloc::System; let x = Box::new_in(5, System); let (ptr, alloc) = Box::into_raw_with_allocator(x); let x = unsafe { Box::from_raw_in(ptr, alloc) }; ``` ```rust #![feature(allocator_api, slice_ptr_get)] use std::alloc::{Allocator, Layout, System}; unsafe { let ptr = System.allocate(Layout::new::())?.as_mut_ptr() as *mut i32; // In general .write is required to avoid attempting to destruct // the (uninitialized) previous contents of `ptr`, though for this // simple example `*ptr = 5` would have worked as well. ptr.write(5); let x = Box::from_raw_in(ptr, System); } ``` -------------------------------- ### Sample ValueNoise3D Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/noise/struct.ValueNoise3D.html Example usage of initializing a new noise instance and sampling a value at specific coordinates. ```rust use oxiphysics::noise::ValueNoise3D; let n = ValueNoise3D::new(0); let v = n.sample(1.5, -2.3, 4.1); assert!(v >= -1.0 && v <= 1.0); ``` -------------------------------- ### Allocating with custom allocators Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Examples of using new_in and try_new_in to allocate memory using a specific allocator instance. ```rust #![feature(allocator_api)] use std::alloc::System; let five = Box::new_in(5, System); ``` ```rust #![feature(allocator_api)] use std::alloc::System; ``` -------------------------------- ### TriggerWorld Usage Example Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/trigger/struct.TriggerWorld.html Demonstrates initializing a TriggerWorld, adding an AABB trigger, and processing body updates to detect occupancy events. ```rust use oxiphysics::trigger::{TriggerWorld, BodyEntry}; let mut world = TriggerWorld::new(); let _id = world.add_aabb([-5.0, -5.0, -5.0], [5.0, 5.0, 5.0], vec![]); let bodies = vec![BodyEntry { index: 0, position: [0.0, 0.0, 0.0], radius: 0.5, is_sleeping: false }]; let ev = world.update(1, &bodies); assert_eq!(ev.len(), 1); // Enter let ev2 = world.update(2, &bodies); assert!(ev2.is_empty()); // Stay suppressed by default ``` -------------------------------- ### NavMesh::find_path Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/navmesh/struct.NavMesh.html Calculates a path from a start point to a goal point using A* and the Simple Stupid Funnel algorithm. ```APIDOC ## NavMesh::find_path ### Description Find a path from `start` to `goal`. Uses A* over the triangle graph, then the Simple Stupid Funnel algorithm to smooth the corridor into waypoints. `agent_radius` and `obstacles` are used to mark portals as impassable. ### Signature `pub fn find_path(&self, start: [f64; 3], goal: [f64; 3], agent_radius: f64, obstacles: &[Circle2D]) -> Result` ``` -------------------------------- ### Animation System Usage Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/animation/index.html Example of creating a Vec3Track, grouping it into a BodyAnimation and AnimationClip, and using an AnimationPlayer to sample the state. ```APIDOC use oxiphysics::animation::{Vec3Track, EaseKind, AnimationPlayer, AnimationClip, BodyAnimation}; let mut pos = Vec3Track::new(false); pos.push_keyframe(0.0, [0.0, 0.0, 0.0], EaseKind::Linear); pos.push_keyframe(1.0, [0.0, 5.0, 0.0], EaseKind::Linear); pos.push_keyframe(2.0, [0.0, 0.0, 0.0], EaseKind::Linear); let body_anim = BodyAnimation::new("ball").with_position(pos); let clip = AnimationClip::new("rise_and_fall", vec![body_anim]); let mut player = AnimationPlayer::new(clip); player.play(); let states = player.update(0.5); ``` -------------------------------- ### Convert Box to raw pointer with allocator Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Demonstrates consuming a Box into a raw pointer and allocator, with examples for both automatic and manual memory cleanup. ```rust #![feature(allocator_api)] use std::alloc::System; let x = Box::new_in(String::from("Hello"), System); let (ptr, alloc) = Box::into_raw_with_allocator(x); let x = unsafe { Box::from_raw_in(ptr, alloc) }; ``` ```rust #![feature(allocator_api)] use std::alloc::{Allocator, Layout, System}; use std::ptr::{self, NonNull}; let x = Box::new_in(String::from("Hello"), System); let (ptr, alloc) = Box::into_raw_with_allocator(x); unsafe { ptr::drop_in_place(ptr); let non_null = NonNull::new_unchecked(ptr); alloc.deallocate(non_null.cast(), Layout::new::()); } ``` -------------------------------- ### Construct Box from NonNull pointer Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Examples demonstrating how to recreate a Box from a NonNull pointer or manually allocate memory for a Box using NonNull. ```rust #![feature(allocator_api)] use std::alloc::System; let x = Box::new_in(5, System); let (non_null, alloc) = Box::into_non_null_with_allocator(x); let x = unsafe { Box::from_non_null_in(non_null, alloc) }; ``` ```rust #![feature(allocator_api)] use std::alloc::{Allocator, Layout, System}; unsafe { let non_null = System.allocate(Layout::new::())?.cast::(); // In general .write is required to avoid attempting to destruct // the (uninitialized) previous contents of `non_null`. non_null.write(5); let x = Box::from_non_null_in(non_null, System); } ``` -------------------------------- ### MaterialTable API Usage Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/material_table/index.html Examples of how to interact with the MaterialTable to retrieve material IDs, query contact properties, and set pair-specific overrides. ```APIDOC ## MaterialTable API ### Description The `MaterialTable` struct allows for the management of material definitions and the calculation of contact properties between material pairs. ### Methods - **id_for_name(name: &str) -> Option** Retrieves the `MaterialId` associated with a given material name. - **contact_static_friction(a: MaterialId, b: MaterialId) -> f32** Calculates the static friction coefficient for a contact pair using the configured `CombineRule`. - **contact_restitution(a: MaterialId, b: MaterialId) -> f32** Calculates the restitution coefficient for a contact pair. - **set_pair_restitution(a: MaterialId, b: MaterialId, value: f32)** Sets a specific override for the restitution coefficient between two materials. ### Example ```rust use oxiphysics::material_table::{MaterialTable, CombineRule}; let mut table = MaterialTable::new(); let rubber = table.id_for_name("rubber").unwrap(); let concrete = table.id_for_name("concrete").unwrap(); // Query friction let friction = table.contact_static_friction(rubber, concrete); // Set override let ice = table.id_for_name("ice").unwrap(); table.set_pair_restitution(ice, ice, 0.05); ``` ``` -------------------------------- ### Convert Box to NonNull pointer with allocator Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Demonstrates consuming a Box into a NonNull pointer and allocator, with examples for both automatic and manual memory cleanup. ```rust #![feature(allocator_api)] use std::alloc::System; let x = Box::new_in(String::from("Hello"), System); let (non_null, alloc) = Box::into_non_null_with_allocator(x); let x = unsafe { Box::from_non_null_in(non_null, alloc) }; ``` ```rust #![feature(allocator_api)] use std::alloc::{Allocator, Layout, System}; let x = Box::new_in(String::from("Hello"), System); let (non_null, alloc) = Box::into_non_null_with_allocator(x); unsafe { non_null.drop_in_place(); alloc.deallocate(non_null.cast::(), Layout::new::()); } ``` -------------------------------- ### Typical Snapshot Workflow Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/snapshot/index.html Demonstrates initializing a SnapshotManager and recording a WorldSnapshot after a simulation step. ```rust use oxiphysics::snapshot::{BodySnapshot, WorldSnapshot, SnapshotManager}; let mut manager = SnapshotManager::new(10); // keep last 10 snapshots // After each simulation step… let snap = WorldSnapshot::new(1, 1.0 / 60.0) .add_body(BodySnapshot::at_rest(0, [0.0, 0.0, 0.0])); manager.push(snap); assert_eq!(manager.len(), 1); assert!(manager.latest().is_some()); ``` -------------------------------- ### Initialize and Configure ForceFieldSystem Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/force_field/struct.ForceFieldSystem.html Demonstrates creating a system, adding global and bounded force fields, and calculating the resulting force at a specific point in time. ```rust use oxiphysics::force_field::{ForceFieldKind, ForceFieldSystem, AabbRegion}; let mut sys = ForceFieldSystem::new(); // Gravity (downward uniform field) sys.add(ForceFieldKind::Uniform { force: [0.0, -9.81, 0.0] }); // An explosion at origin, starting at t=0 sys.add(ForceFieldKind::Explosion { center: [0.0, 0.0, 0.0], peak_force: 1000.0, wave_speed: 50.0, thickness: 2.0, start_time: 0.0, }); // Vortex bounded to a region let id = sys.add_bounded( ForceFieldKind::Vortex { center: [0.0, 0.0, 0.0], axis: [0.0, 1.0, 0.0], tangential_strength: 5.0, axial_strength: 0.0, }, AabbRegion::new([-5.0; 3], [5.0; 3]), ); let force = sys.force_at([1.0, 0.0, 0.0], 0.5); assert!(force.iter().any(|&f| f.abs() > 1e-10)); sys.disable(id); ``` -------------------------------- ### BodyTransformLookup Implementation Pattern Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/rope/type.BodyTransformLookup.html Example syntax for implementing the lookup as a closure. ```rust &|handle: u64| -> Option<[f64; 3]> { … } ``` -------------------------------- ### Initialize and step an XPBD solver Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/xpbd/index.html Demonstrates creating an XpbdSolver, adding particles with specific masses, defining a distance constraint, and advancing the simulation by one time step. ```rust use oxiphysics::xpbd::{XpbdConstraint, XpbdSolver}; let mut solver = XpbdSolver::new(); let a = solver.add_particle([0.0, 0.0, 0.0], 0.0); // pinned let b = solver.add_particle([1.0, 0.0, 0.0], 1.0); // dynamic solver.add_constraint(XpbdConstraint::Distance { a, b, rest_length: 1.0, compliance: 0.0, }); solver.step(1.0 / 60.0); ``` -------------------------------- ### Initialize NavMesh and Find Path Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/navmesh/index.html Demonstrates creating a NavMesh from vertices and triangles, then calculating a path between two points. ```rust use oxiphysics::navmesh::{NavMesh, Circle2D}; let verts = vec![ [0.0, 0.0, 0.0f64], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0], [1.0, 0.0, 1.0], ]; let tris = vec![[0u32, 1, 2], [1, 3, 2]]; let mesh = NavMesh::from_triangles(verts, tris); let path = mesh.find_path([0.1, 0.0, 0.1], [0.9, 0.0, 0.9], 0.0, &[]); assert!(path.is_ok()); ``` -------------------------------- ### Initialize and Configure ForceFieldSystem Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/force_field/index.html Demonstrates creating a ForceFieldSystem and adding multiple force field types such as radial attraction and wind. ```rust use oxiphysics::force_field::{ForceFieldKind, ForceFieldSystem}; let mut sys = ForceFieldSystem::new(); // Gravity-like field pulling toward origin sys.add(ForceFieldKind::RadialAttract { center: [0.0, 0.0, 0.0], strength: 9.81, falloff_exp: 2.0, }); // Wind pushing in +X sys.add(ForceFieldKind::Wind { direction: [1.0, 0.0, 0.0], base_speed: 5.0, }); let f = sys.force_at([1.0, 1.0, 1.0], 0.0); assert!(f[0].is_finite()); // wind contribution ``` -------------------------------- ### Initialize and Configure MaterialTable Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/material_table/index.html Demonstrates creating a MaterialTable, retrieving material IDs, querying contact friction, and setting a custom pair-wise restitution override. ```rust use oxiphysics::material_table::{MaterialTable, CombineRule}; let mut table = MaterialTable::new(); let rubber = table.id_for_name("rubber").unwrap(); let concrete = table.id_for_name("concrete").unwrap(); // Rubber-on-concrete: high friction let friction = table.contact_static_friction(rubber, concrete); assert!(friction > 0.5); // Ice-on-ice: override bounce to a specific value let ice = table.id_for_name("ice").unwrap(); table.set_pair_restitution(ice, ice, 0.05); assert!((table.contact_restitution(ice, ice) - 0.05).abs() < 1e-9); ``` -------------------------------- ### Initialize and populate SnapshotManager Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/snapshot/struct.SnapshotManager.html Demonstrates creating a manager with a fixed capacity and pushing snapshots, showing how older snapshots are automatically dropped. ```rust use oxiphysics::snapshot::{BodySnapshot, WorldSnapshot, SnapshotManager}; let mut manager = SnapshotManager::new(5); for step in 0..8_u64 { let snap = WorldSnapshot::new(step, step as f64 / 60.0) .add_body(BodySnapshot::at_rest(0, [0.0, step as f64, 0.0])); manager.push(snap); } // Only the last 5 are kept assert_eq!(manager.len(), 5); assert_eq!(manager.latest().unwrap().step, 7); ``` -------------------------------- ### Initialize and Step RollbackWorld Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/rollback/index.html Demonstrates setting up a RollbackWorld with custom simulation functions and performing a simulation step. ```rust use oxiphysics::rollback::RollbackWorld; struct Sim { state: i64 } fn advance(w: &mut Sim, _dt: f64, cmds: &[i32]) { w.state += cmds.iter().map(|c| *c as i64).sum::(); } fn snapshot(w: &Sim) -> Vec { w.state.to_le_bytes().to_vec() } fn restore(w: &mut Sim, snap: &[u8]) { if snap.len() == 8 { let arr: [u8; 8] = snap.try_into().unwrap_or([0; 8]); w.state = i64::from_le_bytes(arr); } } let mut rw = RollbackWorld::new(Sim { state: 0 }, 64, advance, snapshot, restore); rw.step(1.0 / 60.0, &[5_i32]); assert_eq!(rw.world.state, 5); ``` -------------------------------- ### Initialize and Run Physics Scheduler Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/scheduler/index.html Demonstrates the lifecycle of a Scheduler, including island registration, frame scheduling, and velocity updates for auto-sleeping. ```rust use oxiphysics::scheduler::{Scheduler, Priority}; let mut sched = Scheduler::new(2, 4); // base = 2, max = 4 let island_a = sched.add_island(Priority::Critical, 10); let island_b = sched.add_island(Priority::Normal, 50); let island_c = sched.add_island(Priority::Low, 200); // Simulate a few frames for _ in 0..60 { let frame = sched.schedule(1.0 / 60.0); for alloc in &frame.allocations { // run `alloc.substeps` sub-steps of dt = `alloc.dt_per_substep` let _ = alloc.substeps; let _ = alloc.dt_per_substep; } // update velocity hints so the scheduler can auto-sleep idle islands sched.update_velocity(island_b, 0.001); sched.update_velocity(island_c, 0.0); sched.auto_sleep_step(); } ``` -------------------------------- ### Initialize and update LodSystem Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/lod/index.html Demonstrates configuring the LOD system with distance thresholds and substep counts, adding bodies, and processing tier transitions. ```rust use oxiphysics::lod::{LodSystem, LodConfig, LodTier}; let config = LodConfig { full_radius: 50.0, reduced_radius: 150.0, minimal_radius: 300.0, substeps_full: 4, substeps_reduced: 2, substeps_minimal: 1, }; let mut lod = LodSystem::new(config, [0.0; 3]); let near_body = lod.add_body([10.0, 0.0, 0.0], 0.0); let far_body = lod.add_body([500.0, 0.0, 0.0], 0.0); let transitions = lod.update(); assert_eq!(lod.tier(near_body), Some(LodTier::Full)); assert_eq!(lod.tier(far_body), Some(LodTier::Frozen)); assert!(!transitions.is_empty()); ``` -------------------------------- ### Leaking Box memory Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Examples of consuming a Box to return a static mutable reference, applicable to both simple types and unsized slices. ```rust let x = Box::new(41); let static_ref: &'static mut usize = Box::leak(x); *static_ref += 1; assert_eq!(*static_ref, 42); ``` ```rust let x = vec![1, 2, 3].into_boxed_slice(); let static_ref = Box::leak(x); static_ref[0] = 4; assert_eq!(*static_ref, [4, 2, 3]); ``` -------------------------------- ### Record and Replay Simulation Inputs in Rust Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/replay/index.html Demonstrates the full lifecycle of recording simulation steps with SimRecorder and replaying them using SimReplayer. ```rust use oxiphysics::replay::{SimRecorder, SimReplayer, ReplayCommand}; let mut rec = SimRecorder::new(42); // Simulate 3 steps, recording the inputs for step in 0..3 { rec.begin_step(1.0 / 60.0); rec.record_force(0, [0.0, 100.0, 0.0]); rec.record_impulse(1, [1.0, 0.0, 0.0]); rec.end_step(); } let record = rec.finish(); assert_eq!(record.step_count(), 3); // Replay let mut replayer = SimReplayer::new(record); while let Some(step) = replayer.advance() { for cmd in &step.commands { let _ = cmd; // re-apply each command to the simulation } } assert!(replayer.is_done()); ``` -------------------------------- ### SnapshotManager Usage Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/snapshot/index.html Demonstrates the typical workflow for initializing a SnapshotManager and pushing a new WorldSnapshot after a simulation step. ```APIDOC ## SnapshotManager Workflow ### Description This example shows how to initialize a `SnapshotManager` with a fixed capacity and record a `WorldSnapshot` containing body states. ### Code Example ```rust use oxiphysics::snapshot::{BodySnapshot, WorldSnapshot, SnapshotManager}; let mut manager = SnapshotManager::new(10); // keep last 10 snapshots // After each simulation step… let snap = WorldSnapshot::new(1, 1.0 / 60.0) .add_body(BodySnapshot::at_rest(0, [0.0, 0.0, 0.0])); manager.push(snap); assert_eq!(manager.len(), 1); assert!(manager.latest().is_some()); ``` ``` -------------------------------- ### Initialize Transform and Vector Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/index.html Demonstrates basic usage of the core math and transform modules to perform a point transformation. ```rust use oxiphysics::core::math::Vec3; use oxiphysics::core::Transform; let t = Transform::default(); let v = Vec3::new(1.0, 2.0, 3.0); let _transformed = t.transform_point(&v); ``` -------------------------------- ### Constructing a PhysicsConfig Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/struct.PipelineConfigBuilder.html Demonstrates the fluent API usage to initialize and configure a new physics pipeline configuration. ```rust let config = PipelineConfigBuilder::new() .gravity(Vec3::new(0.0, -9.81, 0.0)) .solver_iterations(10) .ccd_enabled(true) .build(); ``` -------------------------------- ### EventBus Usage Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/event_bus/index.html Demonstrates how to initialize an EventBus, subscribe to events, publish events, and process the event queue. ```APIDOC ## EventBus ### Description A lightweight publish/subscribe event bus for physics events. ### Methods - **new()**: Creates a new EventBus instance. - **subscribe(listener: Fn(PhysicsEvent)) -> ListenerId**: Registers a listener function to be called when events are flushed. - **unsubscribe(id: ListenerId)**: Removes a previously registered listener. - **publish(event: PhysicsEvent)**: Queues a physics event to be dispatched. - **flush()**: Dispatches all queued events to registered listeners. - **drain() -> Vec**: Drains the event queue and returns the events as a vector without dispatching to listeners. ``` -------------------------------- ### Construct a PhysicsPipeline Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/struct.PipelineBuilder.html Demonstrates the fluent builder pattern to configure and finalize a PhysicsPipeline instance. ```rust let pipeline = PhysicsPipeline::builder() .gravity(Vec3::new(0.0, -9.81, 0.0)) .ccd_enabled(true) .profiling(true) .finish(); ``` -------------------------------- ### Using ProfilerSession for hierarchical timing Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/profiler/index.html Demonstrates initializing a session, creating nested scopes with RAII guards, and generating reports in CSV, JSON, and folded stack formats. ```rust use oxiphysics::profiler::ProfilerSession; let mut session = ProfilerSession::new(); session.begin_frame(); { let _a = session.scope("physics"); { let _b = session.scope("collision"); // inner work } // _b drops here — records "collision" } // _a drops here — records "physics" let report = session.end_frame(); println!("frame ns: {}", report.frame_ns); println!("csv:\n{}", report.to_csv()); println!("json:\n{}", report.to_json()); println!("folded:\n{}", report.to_folded_stacks()); ``` -------------------------------- ### Using DebugDrawSession for Simulation Steps Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/debug_draw/struct.DebugDrawSession.html Demonstrates initializing a session, beginning a step, adding a sphere command, and finalizing the frame. ```rust use oxiphysics::debug_draw::{DebugDrawSession, DrawDuration}; let mut session = DebugDrawSession::new(); session.begin_step(42); session.sphere([0.0, 1.0, 0.0], 0.5, [1.0, 0.0, 0.0, 1.0]); let frame = session.end_step(); assert_eq!(frame.step, 42); assert_eq!(frame.commands.len(), 1); ``` -------------------------------- ### Initialize and move a CharacterController Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/character/index.html Demonstrates setting up a character controller with a capsule shape and performing a movement operation using a custom sweep callback. ```rust use oxiphysics::character::{CharacterController, CharacterConfig, CharacterShape, SweepHit}; let shape = CharacterShape { radius: 0.4, half_height: 0.9 }; let config = CharacterConfig::default(); let mut controller = CharacterController::new([0.0, 1.0, 0.0], shape, config); // Move down by 1 unit; caller-provided sweep returns no hit. let result = controller.move_and_slide([0.0, -1.0, 0.0], |_origin, _dir| None); let _ = result.translation; ``` -------------------------------- ### Calculate Aerodynamic Forces with AeroSystem Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/aero/index.html Demonstrates setting up an AeroEntry with a bluff-body and a wing surface, then calculating the resulting forces using AeroSystem. ```rust use oxiphysics::aero::{ AeroBody, AeroEntry, AeroSystem, DragCurve, LiftCurve, WingSurface, }; // Identity rotation (body axes aligned with world axes) let identity = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]; // A flat plate moving at 20 m/s into the wind let entry = AeroEntry { position: [0.0, 0.0, 0.0], rotation: identity, velocity: [20.0, 0.0, 0.0], drag_body: Some(AeroBody { drag_coeff: 1.28, cross_section: 0.05, air_density: 1.225, }), wings: vec![WingSurface { center_local: [0.0, 0.0, 0.0], normal_local: [0.0, 1.0, 0.0], chord: 0.3, span: 1.2, lift_curve: LiftCurve::Linear { cl0: 0.0, slope: 5.73 }, drag_curve: DragCurve::Constant(0.02), air_density: 1.225, }], }; let system = AeroSystem { entries: vec![entry], wind: [0.0; 3] }; let forces = system.apply(); assert_eq!(forces.len(), 1); assert!(forces[0].force[0] < 0.0, "drag opposes +X motion"); ``` -------------------------------- ### Perform a Raycast Query in Rust Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/query/index.html Demonstrates initializing a QueryWorld, adding spheres, and performing a raycast to find the first intersection. ```rust use oxiphysics::query::{QueryWorld, Ray, QueryFilter}; let mut world = QueryWorld::new(); world.add_sphere(0, [0.0, 0.0, 0.0], 1.0, false); world.add_sphere(1, [3.0, 0.0, 0.0], 1.0, false); let ray = Ray::new([-5.0, 0.0, 0.0], [1.0, 0.0, 0.0]); let hit = world.raycast(&ray, &QueryFilter::default()); assert!(hit.is_some()); assert_eq!(hit.unwrap().body_index, 0); ``` -------------------------------- ### Using the EventBus for Physics Events Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/event_bus/index.html Demonstrates how to subscribe to events, publish them, and manage the event queue using flush or drain. ```rust use oxiphysics::event_bus::{EventBus, PhysicsEvent}; let mut bus = EventBus::new(); // Register a listener that counts collisions let id = bus.subscribe(|ev| { if matches!(ev, PhysicsEvent::CollisionBegin { .. }) { // handle collision } }); // Emit some events (normally done by the pipeline) bus.publish(PhysicsEvent::CollisionBegin { body_a: 0, body_b: 1, contact_normal: [0.0, 1.0, 0.0], penetration_depth: 0.01, }); bus.publish(PhysicsEvent::StepCompleted { step: 1, sim_time: 1.0 / 60.0, dt: 1.0 / 60.0 }); // Flush: deliver all queued events to listeners bus.flush(); // Or drain: take ownership without calling listeners let events = bus.drain(); assert!(events.is_empty()); // already flushed above bus.unsubscribe(id); ``` -------------------------------- ### Scheduler::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/scheduler/struct.Scheduler.html Creates a new instance of the Scheduler with specified substep configurations. ```APIDOC ## pub fn new(base_substeps: u32, max_substeps: u32) -> Self ### Description Creates a new scheduler instance. The base_substeps parameter is clamped to >= 1, and max_substeps is clamped to >= base_substeps. ### Parameters - **base_substeps** (u32) - Required - Substeps for Normal islands. - **max_substeps** (u32) - Required - Substeps for High/Critical islands. ``` -------------------------------- ### Initialize CouplingRuntime Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/struct.CouplingRuntime.html Create a new, empty instance of the runtime. ```rust pub fn new() -> Self ``` -------------------------------- ### IkChain::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/ik/struct.IkChain.html Creates a new IkChain instance from a root position and a list of segment definitions. ```APIDOC ## pub fn new(root_world: [f64; 3], segments: &[(f64, f64, f64)]) -> Self ### Description Builds a new kinematic chain starting at the specified root world position. The segments parameter accepts a list of tuples containing (segment_length, cone_limit_rad, twist_limit_rad). ### Parameters - **root_world** ([f64; 3]) - The world-space position of the root joint base. - **segments** (&[(f64, f64, f64)]) - A slice of tuples defining segment length, cone limit in radians, and twist limit in radians. ``` -------------------------------- ### Initialize and update ContactCache Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/contact_cache/index.html Demonstrates the basic lifecycle of a ContactCache, including initialization, updating a contact pair, and retrieving cached data. ```rust use oxiphysics::contact_cache::{ContactCache, ContactPoint}; let mut cache = ContactCache::new(3); cache.begin_step(); let pt = ContactPoint { pos_a: [0.0, 1.0, 0.0], pos_b: [0.0, 0.9, 0.0], normal: [0.0, 1.0, 0.0], depth: 0.1, }; cache.update_pair(0, 1, vec![pt]); cache.evict_stale(); let entry = cache.lookup(0, 1).unwrap(); assert_eq!(entry.points.len(), 1); ``` -------------------------------- ### BenchmarkBaseline::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/perf_regression/struct.BenchmarkBaseline.html Creates a new empty BenchmarkBaseline instance. ```APIDOC ## pub fn new(commit_hash: &str, date: &str) -> Self ### Description Creates a new empty baseline with the specified commit hash and date. ### Parameters - **commit_hash** (&str) - Required - Git commit hash or identifier. - **date** (&str) - Required - Human-readable date string. ``` -------------------------------- ### CouplingRuntime::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/struct.CouplingRuntime.html Creates a new, empty CouplingRuntime instance. ```APIDOC ## pub fn new() -> Self ### Description Create an empty runtime with no domains or couplers. ``` -------------------------------- ### Solve an IK chain using FABRIK Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/ik/index.html Demonstrates initializing an IkChain with three segments and solving for a target position using the FABRIK solver. ```rust use oxiphysics::ik::{IkChain, IkSolver}; // Three 1-metre segments hanging downward from origin let mut chain = IkChain::new([0.0, 0.0, 0.0], &[ (1.0, std::f64::consts::PI, 0.0), (1.0, std::f64::consts::PI, 0.0), (1.0, std::f64::consts::PI, 0.0), ]); let solver = IkSolver::Fabrik { max_iterations: 30, tolerance: 1e-6 }; let report = solver.solve(&mut chain, [0.0, 3.0, 0.0]); assert!(report.converged); ``` -------------------------------- ### Construct a scene using SceneBuilder Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/scene/struct.SceneBuilder.html Demonstrates the fluent builder pattern to define a scene with gravity, a sphere, and a static box. ```rust use oxiphysics::scene::SceneBuilder; let scene = SceneBuilder::new("demo") .with_gravity([0.0, -9.81, 0.0]) .add_sphere("ball", [0.0, 5.0, 0.0], 0.5, false) .add_static_box("floor", [0.0, 0.0, 0.0], [10.0, 0.1, 10.0]) .build(); assert_eq!(scene.body_count(), 2); ``` -------------------------------- ### Constructing a PhysicsPipeline with the Builder Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/struct.PhysicsPipeline.html Use the builder pattern to initialize a pipeline with specific gravity and CCD settings. ```rust let pipeline = PhysicsPipeline::builder() .gravity(Vec3::new(0.0, -9.81, 0.0)) .ccd_enabled(true) .finish(); ``` -------------------------------- ### CharacterController Methods Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/character/struct.CharacterController.html Methods for initializing the controller, handling movement with collision, jumping, and applying gravity. ```rust pub fn new( position: [f64; 3], shape: CharacterShape, config: CharacterConfig, ) -> Self ``` ```rust pub fn move_and_slide( &mut self, desired_delta: [f64; 3], sweep: F, ) -> CharacterMove where F: Fn([f64; 3], [f64; 3]) -> Option, ``` ```rust pub fn jump(&mut self, speed: f64) ``` ```rust pub fn apply_gravity(&mut self, gravity_accel: f64, dt: f64) ``` -------------------------------- ### Factory Methods Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/scene/struct.SceneMaterial.html Convenience methods to create pre-configured SceneMaterial instances. ```APIDOC ## Factory Methods ### static_surface() Returns a material for static surfaces (high friction, no bounce). ### rubber() Returns a rubber-like material (high restitution, high friction). ### metal() Returns a metal-like material (low restitution, moderate friction). ### ice() Returns an ice-like material (very low friction). ``` -------------------------------- ### Clone Box from Reference Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Demonstrates cloning a Box from a reference using a specific allocator. ```rust let hello: Box = Box::try_clone_from_ref_in("hello", System)?; ``` -------------------------------- ### RollbackWorld::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/rollback/struct.RollbackWorld.html Creates a new instance of RollbackWorld, initializing the simulation world and required callback functions. ```APIDOC ## pub fn new(world: World, capacity: usize, advance_fn: fn(&mut World, f64, &[Cmd]), snapshot_fn: fn(&World) -> Vec, restore_fn: fn(&mut World, &[u8])) -> Self ### Description Initializes a new RollbackWorld. An initial frame at tick 0 is captured immediately to ensure state restoration is possible. ### Parameters - **world** (World) - The initial simulation world. - **capacity** (usize) - The capacity of the rollback buffer. - **advance_fn** (fn) - Function to advance the simulation state. - **snapshot_fn** (fn) - Function to serialize the world state. - **restore_fn** (fn) - Function to restore the world state from a snapshot. ``` -------------------------------- ### CloneToUninit Implementation Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/character/struct.CharacterConfig.html Experimental nightly-only API for performing copy-assignment to uninitialized memory. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### Create a new FluidVolume Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/buoyancy/struct.FluidVolume.html Constructor for creating a fluid volume with default drag coefficients. ```rust pub fn new(min: [f64; 3], max: [f64; 3], density: f64) -> Self ``` -------------------------------- ### BuoyancyWorld Methods Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/buoyancy/struct.BuoyancyWorld.html Methods for initializing the buoyancy world, managing fluid volumes, and calculating forces on bodies. ```APIDOC ## pub fn new(gravity: f64) -> Self ### Description Creates a new BuoyancyWorld instance with the specified gravitational acceleration. ## pub fn add_fluid(&mut self, min: [f64; 3], max: [f64; 3], density: f64, surface_y: f64) -> u32 ### Description Registers a new fluid volume defined by an AABB (min/max coordinates), density, and surface level. Returns a unique ID for the fluid. ## pub fn add_fluid_with_drag(&mut self, min: [f64; 3], max: [f64; 3], density: f64, surface_y: f64, linear_drag: f64, angular_drag: f64) -> u32 ### Description Registers a fluid volume with explicit linear and angular drag coefficients. ## pub fn remove_fluid(&mut self, id: u32) ### Description Removes a fluid volume from the world by its ID. ## pub fn apply(&self, bodies: &[BuoyantBody]) -> Vec<(u32, BuoyancyForce)> ### Description Calculates the combined buoyancy and drag forces for a slice of bodies against all overlapping fluid volumes. ## pub fn apply_single(&self, body: &BuoyantBody) -> Option ### Description Calculates the buoyancy force for a single body, returning None if the body does not overlap any fluid. ## pub fn is_floating(&self, body: &BuoyantBody, threshold: f64) -> bool ### Description Estimates if a body is floating at the surface based on a submerged fraction threshold. ``` -------------------------------- ### Register domains and couplers Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/struct.CouplingRuntime.html Methods to add simulation domains and couplers to the runtime, returning their respective indices. ```rust pub fn add_domain(&mut self, domain: Box) -> usize ``` ```rust pub fn add_coupler(&mut self, coupler: Box) -> usize ``` -------------------------------- ### AnimationClip::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/animation/struct.AnimationClip.html Creates a new instance of an AnimationClip. ```APIDOC ## pub fn new(name: impl Into, body_animations: Vec) -> Self ### Description Creates a new AnimationClip with the specified name and a collection of body animations. ### Parameters - **name** (impl Into) - The human-readable name of the clip. - **body_animations** (Vec) - The list of body animation tracks to include. ``` -------------------------------- ### Try to create a new Box Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/pipeline/type.StageCallback.html Experimental API that returns an error if heap allocation fails. ```rust #![feature(allocator_api)] let five = Box::try_new(5)?; ``` -------------------------------- ### MaterialTable::new Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/material_table/struct.MaterialTable.html Creates a new MaterialTable instance pre-populated with built-in surface presets. ```APIDOC ## pub fn new() -> Self ### Description Creates a table pre-populated with six built-in surface presets: concrete, rubber, metal, ice, wood, and glass. ``` -------------------------------- ### CouplingRuntime Methods Source: https://docs.rs/oxiphysics/0.1.2/oxiphysics/coupling/struct.CouplingRuntime.html Methods for managing domains, couplers, and simulation steps within the CouplingRuntime. ```APIDOC ## pub fn new() -> Self ### Description Create an empty runtime with no domains or couplers. ## pub fn add_domain(&mut self, domain: Box) -> usize ### Description Register a domain and return its index. ## pub fn add_coupler(&mut self, coupler: Box) -> usize ### Description Register a coupler and return its index. ## pub fn schedule_pair(&mut self, coupler_idx: usize, domain_a_idx: usize, domain_b_idx: usize) ### Description Schedule a coupling step between two domains via an existing coupler. The triple is appended to the schedule in the order it was registered. ## pub fn step(&mut self, dt: f64) -> Vec ### Description Advance all scheduled couplers by one time step of duration `dt`. Returns a `Vec` with one entry per scheduled pair, in schedule order. ## pub fn domain_count(&self) -> usize ### Description Return the number of registered domains. ## pub fn coupler_count(&self) -> usize ### Description Return the number of registered couplers. ## pub fn schedule_len(&self) -> usize ### Description Return the number of scheduled pairs. ```