1#![deny(missing_docs)]
206#![allow(
215 clippy::cast_possible_truncation,
216 clippy::cast_precision_loss,
217 clippy::cast_sign_loss,
218 clippy::cast_lossless,
219 clippy::cast_possible_wrap,
220 clippy::similar_names,
221 clippy::many_single_char_names,
222 clippy::module_name_repetitions,
223 clippy::unreadable_literal,
224 clippy::large_stack_arrays,
225 clippy::doc_markdown
226)]
227#![cfg_attr(not(feature = "std"), no_std)]
228
229#[cfg(all(feature = "wasm", feature = "ffi"))]
230compile_error!("Features `wasm` and `ffi` are mutually exclusive. Enable only one.");
231
232#[cfg(all(feature = "wasm", not(feature = "std")))]
233compile_error!("Feature `wasm` requires `std`.");
234
235#[cfg(not(feature = "std"))]
236extern crate alloc;
237
238#[cfg(test)]
242extern crate self as alice_physics;
243
244pub mod acoustic_wave;
245pub mod aeroelasticity;
246#[cfg(feature = "analytics")]
247pub mod analytics_bridge;
248pub mod animation_blend;
249pub mod anisotropic;
250pub mod anisotropic_friction;
251#[cfg(feature = "std")]
252pub mod anomaly;
253pub mod articulation;
254pub mod atmosphere;
255pub mod audio_physics;
256pub mod beam_stress;
257pub mod bimaterial;
258pub mod box_collider;
259#[cfg(feature = "std")]
260pub mod bridging;
261pub mod buckling;
262pub mod buoyancy_zone;
263pub mod bvh;
264pub mod ccd;
265#[cfg(feature = "std")]
266pub mod cfd_solver;
267pub mod character;
268pub mod character_state;
269pub mod cloth;
270pub mod cloth_fluid;
271pub mod collider;
272pub mod collision_mesh_gen;
273pub mod compound;
274pub mod compressible;
275pub mod cone;
276pub mod contact_cache;
277pub mod contact_viz;
278#[cfg(feature = "std")]
279pub mod convex_decompose;
280pub mod convex_mesh_builder;
281pub mod coupled_field;
282pub mod coupled_iteration;
283pub mod coupling_medium;
284pub mod creep_longterm;
285pub mod crowd_force;
286pub mod cubic_elastic_fem;
287pub mod cylinder;
288pub mod damping_rayleigh;
289#[cfg(feature = "replay")]
290pub mod db_bridge;
291pub mod debug_render;
292pub mod deformable;
293pub mod det_math {
306 pub use alice_det_math::{acos64, asin64, round, round64, sin_cos, sqrt, sqrt64};
307
308 macro_rules! delegate {
309 ($(fn $name:ident($($arg:ident: $ty:ty),*) -> $ret:ty;)*) => {
310 $(
311 #[doc = concat!("Delegates to [`alice_det_math::", stringify!($name), "`].")]
312 #[inline]
313 #[must_use]
314 pub fn $name($($arg: $ty),*) -> $ret {
315 alice_det_math::$name($($arg),*)
316 }
317 )*
318 };
319 }
320
321 delegate! {
322 fn sin(x: f32) -> f32;
323 fn cos(x: f32) -> f32;
324 fn exp(x: f32) -> f32;
325 fn ln(x: f32) -> f32;
326 fn powf(x: f32, y: f32) -> f32;
327 fn powi(x: f32, n: i32) -> f32;
328 fn cbrt(x: f32) -> f32;
329 fn hypot(x: f32, y: f32) -> f32;
330 fn atan(x: f32) -> f32;
331 fn atan2(y: f32, x: f32) -> f32;
332 fn asin(x: f32) -> f32;
333 fn acos(x: f32) -> f32;
334 fn tan(x: f32) -> f32;
335 fn tanh(x: f32) -> f32;
336 fn atan64(x: f64) -> f64;
337 fn atan2_64(y: f64, x: f64) -> f64;
338 fn exp64(x: f64) -> f64;
339 fn ln64(x: f64) -> f64;
340 fn powf64(x: f64, y: f64) -> f64;
341 }
342}
343#[cfg(any(feature = "ffi", feature = "wasm", feature = "python"))]
344mod binding_api;
345pub mod dynamic_bvh;
346#[cfg(feature = "std")]
347pub mod dynamic_fem;
348pub mod electromagnetic;
349pub mod ellipsoid;
350#[cfg(feature = "std")]
351pub mod erosion;
352pub mod error;
353pub mod euler_fv;
354pub mod eulerian_grid;
355pub mod event;
356pub mod fatigue;
357#[cfg(feature = "ffi")]
358pub mod ffi;
359pub mod filament_db;
360
361pub(crate) mod body_collider;
362pub mod fillet_stress;
363pub mod filter;
364#[cfg(feature = "std")]
365pub mod flow_viz;
366pub mod fluid;
367#[cfg(feature = "std")]
368pub mod fluid_netcode;
369pub mod force;
370#[cfg(feature = "std")]
371pub mod fracture;
372#[cfg(feature = "std")]
373pub mod fsi_advanced;
374#[cfg(feature = "std")]
375pub mod gpu_sdf;
376pub mod heatmap;
377pub mod heightfield;
378pub mod hyperelastic;
379#[cfg(feature = "std")]
380pub mod ik_physics_bridge;
381pub mod interface_capture;
382pub mod interpolation;
383pub mod joint;
384pub mod joint_extra;
385pub mod kepler;
386pub mod kinematic_loop;
387#[cfg(feature = "std")]
388pub mod laminate;
389pub mod laminate_failure;
390pub mod law_id;
392pub mod layer_adhesion;
393pub mod lift_drag;
394#[cfg(feature = "std")]
402pub mod linear_elastic_fem;
403pub mod linear_solver;
404pub mod mass_properties;
405pub mod material;
406pub mod math;
407pub mod math_util;
408pub mod maxwell_fdtd;
409pub mod metric;
410pub mod modal;
411pub mod molecular_dynamics;
412pub mod motor;
413pub mod multi_world;
414pub mod multiphase;
415pub mod nbody;
416pub mod netcode;
417#[cfg(feature = "std")]
418pub mod netcode_prediction;
419#[cfg(feature = "neural")]
420pub mod neural;
421pub mod non_newtonian;
422pub mod pair_potential;
423pub mod particle;
424#[cfg(feature = "std")]
425pub mod phase_change;
426#[cfg(feature = "std")]
427pub mod piezoelectric;
428#[cfg(feature = "std")]
429pub mod pipeline;
430pub mod plane_collider;
431pub mod plastic;
432#[cfg(feature = "std")]
433pub mod pressure;
434pub mod prestressed;
435pub mod print_orientation;
436#[cfg(feature = "std")]
437pub mod print_pipeline_solver;
438#[cfg(feature = "std")]
439pub mod privacy;
440pub mod profiling;
441#[cfg(feature = "python")]
442mod python;
443pub mod quadratic_elastic_fem;
444pub mod query;
445pub mod ragdoll;
446pub mod raycast;
447#[cfg(feature = "replay")]
448pub mod replay;
449pub mod rng;
450#[cfg(feature = "std")]
451pub mod rolling_contact;
452pub mod rope;
453pub mod rope_attach;
454pub mod rotor;
455#[cfg(feature = "std")]
456pub mod scene_io;
457#[cfg(feature = "std")]
458pub mod sdf_adaptive;
459pub mod sdf_ccd;
460pub mod sdf_character;
461pub mod sdf_collider;
462#[cfg(feature = "std")]
463pub mod sdf_destruction;
464#[cfg(feature = "std")]
465pub mod sdf_fem_mesh;
466pub mod sdf_force;
467pub mod sdf_manifold;
468#[cfg(feature = "std")]
469pub mod sdf_sph;
470pub mod sdf_wind_field;
471pub mod semantics;
473pub mod sensors;
474pub mod shape;
475pub mod shape_raycast;
476#[cfg(feature = "std")]
477pub mod sim_field;
478#[cfg(feature = "std")]
479pub mod sim_modifier;
480pub mod static_collider;
481pub mod structural_solver;
482#[cfg(feature = "std")]
483pub mod support_volume;
484pub mod surface_tension_csf;
485#[cfg(feature = "std")]
486pub mod thin_wall;
487pub mod vibration_wall;
488pub mod warp_risk;
489pub mod wave_ship;
490pub mod wind_zone;
491pub mod world_character;
492pub mod world_participant;
493pub mod world_shape_query;
494
495pub mod physics2d;
496
497#[cfg(feature = "gpu-solver-bridge")]
498pub mod gpu_bridge;
499#[cfg(feature = "std")]
500pub mod sketch;
501pub mod sleeping;
502pub mod smoke_fire;
503pub mod soft_body_cut;
504pub mod solver;
505pub(crate) mod gyroscopic;
507#[cfg(feature = "std")]
512pub(crate) mod solver_tgs;
513#[cfg(feature = "std")]
514pub(crate) mod solver_tgs_hooks_6dof_oriented;
515#[cfg(feature = "std")]
516pub(crate) mod solver_tgs_hooks_6dof_oriented_scoped;
517#[cfg(feature = "std")]
522pub(crate) mod solver_tgs_backend;
523pub mod spatial;
524pub mod spherical_terrain;
525#[cfg(feature = "std")]
526pub mod thermal;
527pub mod thermal_stress;
528pub mod torus;
529#[cfg(feature = "std")]
530pub mod transient_thermal;
531pub mod trimesh;
532pub mod turbulence;
533pub mod vehicle;
534pub mod vehicle_dynamics;
535#[cfg(feature = "wasm")]
536mod wasm;
537pub mod wedge;
538
539pub use animation_blend::{AnimationBlender, AnimationClip, BlendMode, SkeletonPose};
541#[cfg(feature = "std")]
542pub use anomaly::{
543 AnomalyCallback, AnomalyEvent, CompositeDetector, EwmaDetector, MadDetector, StreamingMedian,
544 ZScoreDetector,
545};
546pub use articulation::{ArticulatedBody, FeatherstoneSolver};
547pub use audio_physics::{AudioConfig, AudioEvent, AudioGenerator, AudioMaterial};
548pub use box_collider::OrientedBox;
549pub use bvh::{BvhNode, BvhPrimitive, LinearBvh};
550pub use ccd::{
551 aabb_plane_toi, capsule_plane_toi, speculative_contact, sphere_capsule_toi, CcdConfig,
552};
553pub use character::{CharacterConfig, CharacterController, MoveResult, PushImpulse};
554pub use cloth::{Cloth, ClothConfig};
555pub use cloth_fluid::{
556 apply_cloth_boundary_to_fluid, apply_fluid_forces_to_cloth, ClothFluidCoupling,
557};
558pub use collider::{Capsule, CollisionResult, ConvexHull, ScaledShape, Sphere, Support, AABB};
559pub use collision_mesh_gen::{
560 compute_mesh_aabb, generate_collision_mesh, simplify_collision_mesh, CollisionMesh,
561 CollisionMeshConfig,
562};
563#[cfg(feature = "std")]
564pub use compound::{CompoundShape, ShapeRef};
565pub use cone::Cone;
566pub use contact_cache::{BodyPairKey, ContactCache, ContactManifold};
567pub use contact_viz::{
568 generate_contact_arrows, generate_friction_cones, ContactArrow, FrictionCone,
569};
570#[cfg(feature = "std")]
571pub use convex_decompose::{DecomposeConfig, DecompositionResult};
572pub use convex_mesh_builder::{build_convex_hull, compute_centroid};
573pub use cylinder::Cylinder;
574pub use debug_render::{debug_draw_world, DebugColor, DebugDrawData, DebugDrawFlags};
575pub use deformable::{DeformableBody, DeformableConfig};
576pub use dynamic_bvh::DynamicAabbTree;
577pub use ellipsoid::Ellipsoid;
578#[cfg(feature = "std")]
579pub use erosion::{ErosionConfig, ErosionModifier, ErosionType};
580pub use error::PhysicsError;
581pub use event::{ContactEvent, ContactEventType, EventCollector, JointBreakEvent, TriggerEvent};
582pub use filter::layers;
584pub use filter::CollisionFilter;
585#[cfg(feature = "std")]
586pub use flow_viz::{
587 generate_flow_arrows, generate_streamlines, FlowArrow, FlowVizConfig, Streamlines,
588};
589pub use fluid::{Fluid, FluidConfig};
590#[cfg(feature = "std")]
591pub use fluid_netcode::{FluidDelta, FluidSnapshot};
592pub use force::{apply_force_fields, ForceField, ForceFieldInstance};
593#[cfg(feature = "std")]
594pub use fracture::{Crack, FractureConfig, FractureModifier};
595#[cfg(feature = "std")]
596pub use gpu_sdf::{
597 batch_size, GpuDispatchConfig, GpuSdfBatch, GpuSdfInstancedBatch, GpuSdfMultiDispatch,
598 GpuSdfQuery, GpuSdfResult,
599};
600pub use heatmap::{
601 generate_stress_heatmap, generate_temperature_heatmap, heatmap_to_rgba, Heatmap, HeatmapConfig,
602 SliceAxis,
603};
604pub use heightfield::HeightField;
605pub use interpolation::{BodySnapshot, InterpolationState, WorldSnapshot};
606#[allow(deprecated)] pub use joint::{
608 solve_joints, solve_joints_breakable, solve_joints_breaking_on_force,
609 solve_joints_with_reaction_forces,
610};
611pub use joint::{
612 BallJoint, ConeTwistJoint, D6Joint, D6Motion, FixedJoint, HingeJoint, Joint, JointType,
613 SliderJoint, SpringJoint,
614};
615pub use joint_extra::{
616 solve_extra_joints, ExtraJoint, GearJoint, MouseJoint, PulleyJoint, RackAndPinionJoint,
617 WeldJoint,
618};
619pub use mass_properties::{
620 box_mass_properties, capsule_mass_properties, convex_hull_mass_properties,
621 cylinder_mass_properties, sphere_mass_properties, translate_inertia, MassProperties,
622};
623pub use material::{CombineRule, CombinedMaterial, MaterialId, MaterialTable, PhysicsMaterial};
624pub use math::{simd_width, Fix128, Mat3Fix, QuatFix, Vec3Fix, SIMD_WIDTH};
625pub use motor::{JointMotor, MotorMode, PdController};
626pub use multi_world::{MultiWorld, Portal};
627pub use netcode::{
628 DeterministicSimulation, FrameInput, InputApplicator, NetcodeConfig, SimulationChecksum,
629 SimulationSnapshot,
630};
631pub use particle::{LandingEvent, LandingTarget, Particle, ParticleEmitter, ParticleSystem};
632#[cfg(feature = "std")]
633pub use phase_change::{Phase, PhaseChangeConfig, PhaseChangeModifier};
634pub use physics2d::{
635 BodyType2D, Contact2D, Joint2D, PhysicsConfig2D, PhysicsWorld2D, RigidBody2D, Shape2D, Vec2Fix,
636};
637#[cfg(feature = "std")]
638pub use pipeline::{
639 MetricEvent, MetricPipeline, MetricRegistry, MetricSnapshot, MetricType, RingBuffer,
640};
641pub use plane_collider::PlaneCollider;
642#[cfg(feature = "std")]
643pub use pressure::{PressureConfig, PressureModifier};
644#[cfg(feature = "std")]
645pub use privacy::{
646 LaplaceNoise, PrivacyBudget, PrivateAggregator, RandomizedResponse, Rappor, XorShift64,
647};
648pub use profiling::{PhysicsProfiler, ProfileEntry, StepStats};
649pub use query::{
650 batch_raycast, batch_sphere_cast, capsule_cast, overlap_aabb, overlap_aabb_bvh, overlap_sphere,
651 overlap_sphere_bvh, sphere_cast, BatchRayQuery, OverlapResult, ShapeCastHit,
652};
653pub use raycast::{
654 raycast_all_aabbs, raycast_all_spheres, raycast_any_aabbs, raycast_any_spheres, Ray, RayHit,
655};
656pub use rng::DeterministicRng;
657pub use rope::{Rope, RopeConfig};
658pub use rope_attach::{solve_rope_attachments, RopeAttachment};
659#[cfg(feature = "std")]
660pub use scene_io::{
661 load_scene, load_scene_json, save_scene, save_scene_json, PhysicsScene, SerializedBody,
662 SerializedJoint,
663};
664#[cfg(feature = "std")]
665pub use sdf_adaptive::{AdaptiveConfig, AdaptiveSdfEvaluator};
666pub use sdf_ccd::SdfCcdConfig;
667pub use sdf_collider::{ClosureSdf, SdfCollider, SdfContact, SdfField};
668#[cfg(feature = "std")]
669pub use sdf_destruction::{DestructibleSdf, DestructionShape};
670pub use sdf_force::{SdfForceField, SdfForceType};
671pub use sdf_manifold::ManifoldConfig;
672#[cfg(feature = "std")]
673pub use sdf_manifold::SdfManifold;
674pub use semantics::{PHYSICS_SEMANTICS_ID, PHYSICS_SEMANTICS_PINS};
675pub use shape::{Shape, ShapeError};
676#[cfg(feature = "std")]
677pub use sim_field::{ScalarField3D, VectorField3D};
678#[cfg(feature = "std")]
679pub use sim_modifier::{ModifiedSdf, PhysicsModifier, SingleModifiedSdf};
680#[cfg(feature = "std")]
681pub use sketch::{CountMinSketch, DDSketch, FnvHasher, HeavyHitters, HyperLogLog, Mergeable};
682pub use sleeping::{Island, IslandManager, SleepConfig, SleepData, SleepState};
683pub use soft_body_cut::{cut_cloth, cut_deformable, CutPlane, CutResult};
684#[cfg(feature = "std")]
685pub use solver::ContactModifier;
686#[cfg(feature = "std")]
687pub use solver::TgsCacheStats;
688pub use solver::{
689 BodyType, ContactConstraint, DistanceConstraint, LawCheck, PhysicsConfig, PhysicsWorld,
690 RigidBody, SolverBackend, StageWork, WorldCcdConfig, WorldSnapshotError,
691};
692pub use spatial::SpatialGrid;
693#[cfg(feature = "std")]
694pub use thermal::{HeatSource, ThermalConfig, ThermalModifier};
695pub use torus::Torus;
696pub use trimesh::{TriMesh, Triangle};
697pub use vehicle::{Vehicle, VehicleConfig};
698pub use wedge::Wedge;
699
700pub mod prelude {
702 pub use crate::animation_blend::{AnimationBlender, AnimationClip, BlendMode, SkeletonPose};
703 #[cfg(feature = "std")]
704 pub use crate::anomaly::{
705 AnomalyCallback, AnomalyEvent, CompositeDetector, EwmaDetector, MadDetector,
706 StreamingMedian, ZScoreDetector,
707 };
708 pub use crate::articulation::{ArticulatedBody, FeatherstoneSolver};
709 pub use crate::audio_physics::{AudioConfig, AudioEvent, AudioGenerator, AudioMaterial};
710 pub use crate::box_collider::OrientedBox;
711 pub use crate::bvh::{BvhNode, BvhPrimitive, LinearBvh};
712 pub use crate::ccd::{speculative_contact, CcdConfig};
713 pub use crate::character::{CharacterConfig, CharacterController, MoveResult, PushImpulse};
714 pub use crate::cloth::{Cloth, ClothConfig};
715 pub use crate::cloth_fluid::{
716 apply_cloth_boundary_to_fluid, apply_fluid_forces_to_cloth, ClothFluidCoupling,
717 };
718 pub use crate::collider::{
719 Capsule, CollisionResult, ConvexHull, ScaledShape, Sphere, Support, AABB,
720 };
721 pub use crate::collision_mesh_gen::{
722 compute_mesh_aabb, generate_collision_mesh, simplify_collision_mesh, CollisionMesh,
723 CollisionMeshConfig,
724 };
725 #[cfg(feature = "std")]
726 pub use crate::compound::{CompoundShape, ShapeRef};
727 pub use crate::cone::Cone;
728 pub use crate::contact_cache::{BodyPairKey, ContactCache, ContactManifold};
729 pub use crate::contact_viz::{
730 generate_contact_arrows, generate_friction_cones, ContactArrow, FrictionCone,
731 };
732 #[cfg(feature = "std")]
733 pub use crate::convex_decompose::{DecomposeConfig, DecompositionResult};
734 pub use crate::convex_mesh_builder::{build_convex_hull, compute_centroid};
735 pub use crate::cylinder::Cylinder;
736 pub use crate::debug_render::{debug_draw_world, DebugColor, DebugDrawData, DebugDrawFlags};
737 pub use crate::deformable::{DeformableBody, DeformableConfig};
738 pub use crate::dynamic_bvh::DynamicAabbTree;
739 pub use crate::ellipsoid::Ellipsoid;
740 #[cfg(feature = "std")]
741 pub use crate::erosion::{ErosionConfig, ErosionModifier, ErosionType};
742 pub use crate::error::PhysicsError;
743 pub use crate::event::{
744 ContactEvent, ContactEventType, EventCollector, JointBreakEvent, TriggerEvent,
745 };
746 pub use crate::filter::layers;
747 pub use crate::filter::CollisionFilter;
748 #[cfg(feature = "std")]
749 pub use crate::flow_viz::{
750 generate_flow_arrows, generate_streamlines, FlowArrow, FlowVizConfig, Streamlines,
751 };
752 pub use crate::fluid::{Fluid, FluidConfig};
753 #[cfg(feature = "std")]
754 pub use crate::fluid_netcode::{FluidDelta, FluidSnapshot};
755 pub use crate::force::{apply_force_fields, ForceField, ForceFieldInstance};
756 #[cfg(feature = "std")]
757 pub use crate::fracture::{Crack, FractureConfig, FractureModifier};
758 #[cfg(feature = "std")]
759 pub use crate::gpu_sdf::{
760 batch_size, GpuDispatchConfig, GpuSdfBatch, GpuSdfInstancedBatch, GpuSdfMultiDispatch,
761 GpuSdfQuery, GpuSdfResult,
762 };
763 pub use crate::heatmap::{
764 generate_stress_heatmap, generate_temperature_heatmap, heatmap_to_rgba, Heatmap,
765 HeatmapConfig, SliceAxis,
766 };
767 pub use crate::heightfield::HeightField;
768 pub use crate::interpolation::{BodySnapshot, InterpolationState, WorldSnapshot};
769 #[allow(deprecated)] pub use crate::joint::{
771 solve_joints, solve_joints_breakable, solve_joints_breaking_on_force,
772 solve_joints_with_reaction_forces,
773 };
774 pub use crate::joint::{
775 BallJoint, ConeTwistJoint, D6Joint, D6Motion, FixedJoint, HingeJoint, Joint, JointType,
776 SliderJoint, SpringJoint,
777 };
778 pub use crate::joint_extra::{
779 solve_extra_joints, ExtraJoint, GearJoint, MouseJoint, PulleyJoint, RackAndPinionJoint,
780 WeldJoint,
781 };
782 pub use crate::mass_properties::{
783 box_mass_properties, capsule_mass_properties, convex_hull_mass_properties,
784 cylinder_mass_properties, sphere_mass_properties, translate_inertia, MassProperties,
785 };
786 pub use crate::material::{
787 CombineRule, CombinedMaterial, MaterialId, MaterialTable, PhysicsMaterial,
788 };
789 pub use crate::math::{simd_width, Fix128, Mat3Fix, QuatFix, Vec3Fix, SIMD_WIDTH};
790 pub use crate::motor::{JointMotor, MotorMode, PdController};
791 pub use crate::multi_world::{MultiWorld, Portal};
792 pub use crate::netcode::{
793 DeterministicSimulation, FrameInput, InputApplicator, NetcodeConfig, SimulationChecksum,
794 SimulationSnapshot,
795 };
796 pub use crate::particle::{
797 LandingEvent, LandingTarget, Particle, ParticleEmitter, ParticleSystem,
798 };
799 #[cfg(feature = "std")]
800 pub use crate::phase_change::{Phase, PhaseChangeConfig, PhaseChangeModifier};
801 #[cfg(feature = "std")]
802 pub use crate::pipeline::{
803 MetricEvent, MetricPipeline, MetricRegistry, MetricSnapshot, MetricType, RingBuffer,
804 };
805 pub use crate::plane_collider::PlaneCollider;
806 #[cfg(feature = "std")]
807 pub use crate::pressure::{PressureConfig, PressureModifier};
808 #[cfg(feature = "std")]
809 pub use crate::privacy::{
810 LaplaceNoise, PrivacyBudget, PrivateAggregator, RandomizedResponse, Rappor, XorShift64,
811 };
812 pub use crate::profiling::{PhysicsProfiler, ProfileEntry, StepStats};
813 pub use crate::query::{
814 batch_raycast, batch_sphere_cast, capsule_cast, overlap_aabb, overlap_aabb_bvh,
815 overlap_sphere, overlap_sphere_bvh, sphere_cast, BatchRayQuery, OverlapResult,
816 ShapeCastHit,
817 };
818 pub use crate::raycast::{
819 raycast_all_aabbs, raycast_all_spheres, raycast_any_aabbs, raycast_any_spheres, Ray, RayHit,
820 };
821 pub use crate::rng::DeterministicRng;
822 pub use crate::rope::{Rope, RopeConfig};
823 pub use crate::rope_attach::{solve_rope_attachments, RopeAttachment};
824 #[cfg(feature = "std")]
825 pub use crate::scene_io::{
826 load_scene, load_scene_json, save_scene, save_scene_json, PhysicsScene, SerializedBody,
827 SerializedJoint,
828 };
829 #[cfg(feature = "std")]
830 pub use crate::sdf_adaptive::{AdaptiveConfig, AdaptiveSdfEvaluator};
831 pub use crate::sdf_ccd::SdfCcdConfig;
832 pub use crate::sdf_collider::{ClosureSdf, SdfCollider, SdfContact, SdfField};
833 #[cfg(feature = "std")]
834 pub use crate::sdf_destruction::{DestructibleSdf, DestructionShape};
835 pub use crate::sdf_force::{SdfForceField, SdfForceType};
836 pub use crate::sdf_manifold::ManifoldConfig;
837 #[cfg(feature = "std")]
838 pub use crate::sdf_manifold::SdfManifold;
839 #[cfg(feature = "std")]
840 pub use crate::sim_field::{ScalarField3D, VectorField3D};
841 #[cfg(feature = "std")]
842 pub use crate::sim_modifier::{ModifiedSdf, PhysicsModifier, SingleModifiedSdf};
843 #[cfg(feature = "std")]
844 pub use crate::sketch::{
845 CountMinSketch, DDSketch, FnvHasher, HeavyHitters, HyperLogLog, Mergeable,
846 };
847 pub use crate::sleeping::{Island, IslandManager, SleepConfig, SleepData, SleepState};
848 pub use crate::soft_body_cut::{cut_cloth, cut_deformable, CutPlane, CutResult};
849 #[cfg(feature = "std")]
850 pub use crate::solver::ContactModifier;
851 #[cfg(feature = "std")]
852 pub use crate::solver::TgsCacheStats;
853 pub use crate::solver::{
854 BodyType, ContactConstraint, DistanceConstraint, LawCheck, PhysicsConfig, PhysicsWorld,
855 RigidBody, SolverBackend, StageWork, WorldCcdConfig, WorldSnapshotError,
856 };
857 pub use crate::spatial::SpatialGrid;
858 #[cfg(feature = "std")]
859 pub use crate::thermal::{HeatSource, ThermalConfig, ThermalModifier};
860 pub use crate::torus::Torus;
861 pub use crate::trimesh::{TriMesh, Triangle};
862 pub use crate::vehicle::{Vehicle, VehicleConfig};
863 pub use crate::wedge::Wedge;
864}
865
866#[cfg(all(test, feature = "std"))]
867mod compile_smoke_tests {
868 use super::*;
872
873 #[test]
874 fn test_prelude_types_accessible() {
875 let _ = Fix128::ZERO;
876 let _ = Vec3Fix::ZERO;
877 let _ = QuatFix::IDENTITY;
878 let _ = Mat3Fix::IDENTITY;
879 let _ = PhysicsConfig::default();
880 let _ = CollisionFilter::default();
881 let _ = SleepConfig::default();
882 }
883
884 #[test]
885 fn test_error_type_accessible() {
886 let e = PhysicsError::InvalidBodyIndex { index: 0, count: 0 };
887 let _ = format!("{e}");
888 }
889
890 #[test]
891 fn test_spatial_grid_accessible() {
892 let mut grid = SpatialGrid::new(Fix128::ONE, 16);
893 grid.insert(0, Vec3Fix::ZERO);
894 grid.build();
895 let mut neighbors = Vec::new();
896 grid.query_neighbors_into(Vec3Fix::ZERO, Fix128::ONE, &mut neighbors);
897 assert!(neighbors.contains(&0));
898 }
899
900 #[test]
901 fn test_wasm_ffi_mutual_exclusion() {
902 }
908}
909
910#[cfg(all(test, feature = "std"))]
911mod tests {
912 use super::*;
913
914 #[test]
915 fn test_basic_simulation() {
916 let config = PhysicsConfig::default();
918 let mut world = PhysicsWorld::new(config);
919
920 let mut body = RigidBody::new_dynamic(Vec3Fix::from_int(0, 100, 0), Fix128::ONE);
922 body.restitution = Fix128::from_ratio(5, 10); let body_id = world.add_body(body);
925
926 let ground = RigidBody::new_static(Vec3Fix::ZERO);
928 world.add_body(ground);
929
930 let dt = Fix128::from_ratio(1, 60);
932 for _ in 0..60 {
933 world.step(dt);
934 }
935
936 let pos = world.bodies[body_id].position;
938 assert!(pos.y < Fix128::from_int(100), "Body should have fallen");
939 }
940
941 #[test]
942 fn test_determinism() {
943 fn run_simulation() -> Vec3Fix {
945 let config = PhysicsConfig::default();
946 let mut world = PhysicsWorld::new(config);
947
948 let body = RigidBody::new_dynamic(
949 Vec3Fix::from_int(5, 50, 3),
950 Fix128::from_ratio(3, 2), );
952 world.add_body(body);
953
954 let dt = Fix128::from_ratio(1, 60);
955 for _ in 0..120 {
956 world.step(dt);
957 }
958
959 world.bodies[0].position
960 }
961
962 let result1 = run_simulation();
963 let result2 = run_simulation();
964
965 assert_eq!(result1.x.hi, result2.x.hi);
967 assert_eq!(result1.x.lo, result2.x.lo);
968 assert_eq!(result1.y.hi, result2.y.hi);
969 assert_eq!(result1.y.lo, result2.y.lo);
970 assert_eq!(result1.z.hi, result2.z.hi);
971 assert_eq!(result1.z.lo, result2.z.lo);
972 }
973
974 #[test]
975 fn test_state_serialization() {
976 let config = PhysicsConfig::default();
977 let mut world = PhysicsWorld::new(config);
978
979 let body = RigidBody::new_dynamic(Vec3Fix::from_int(10, 20, 30), Fix128::ONE);
981 world.add_body(body);
982
983 let dt = Fix128::from_ratio(1, 60);
984 for _ in 0..30 {
985 world.step(dt);
986 }
987
988 let state = world.serialize_state();
990
991 for _ in 0..30 {
993 world.step(dt);
994 }
995 let pos_after = world.bodies[0].position;
996
997 world.deserialize_state(&state);
999
1000 for _ in 0..30 {
1002 world.step(dt);
1003 }
1004 let pos_restored = world.bodies[0].position;
1005
1006 assert_eq!(pos_after.x.hi, pos_restored.x.hi);
1008 assert_eq!(pos_after.y.hi, pos_restored.y.hi);
1009 assert_eq!(pos_after.z.hi, pos_restored.z.hi);
1010 }
1011
1012 #[test]
1013 fn test_distance_constraint() {
1014 let config = PhysicsConfig::default();
1015 let mut world = PhysicsWorld::new(config);
1016
1017 let body_a = RigidBody::new_dynamic(Vec3Fix::from_int(0, 10, 0), Fix128::ONE);
1019 let body_b = RigidBody::new_dynamic(Vec3Fix::from_int(5, 10, 0), Fix128::ONE);
1020 let id_a = world.add_body(body_a);
1021 let id_b = world.add_body(body_b);
1022
1023 let constraint = DistanceConstraint {
1025 body_a: id_a,
1026 body_b: id_b,
1027 local_anchor_a: Vec3Fix::ZERO,
1028 local_anchor_b: Vec3Fix::ZERO,
1029 target_distance: Fix128::from_int(5),
1030 compliance: Fix128::ZERO,
1031 cached_lambda: Fix128::ZERO,
1032 };
1033 world.add_distance_constraint(constraint);
1034
1035 let dt = Fix128::from_ratio(1, 120);
1037 for _ in 0..120 {
1038 world.step(dt);
1039 }
1040
1041 let pos_a = world.bodies[id_a].position;
1043 let pos_b = world.bodies[id_b].position;
1044 let dist = (pos_b - pos_a).length();
1045
1046 let target = Fix128::from_int(5);
1047 let error = if dist > target {
1048 dist - target
1049 } else {
1050 target - dist
1051 };
1052
1053 let tolerance = Fix128::from_ratio(1, 10);
1055 assert!(
1056 error < tolerance,
1057 "Distance constraint violated: error = {error:?}, tolerance = {tolerance:?}"
1058 );
1059 }
1060}