diff --git a/common/src/main/rust/Cargo.lock b/common/src/main/rust/Cargo.lock index 8572d78..db87e68 100644 --- a/common/src/main/rust/Cargo.lock +++ b/common/src/main/rust/Cargo.lock @@ -32,12 +32,56 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + [[package]] name = "anstyle" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "approx" version = "0.5.1" @@ -152,11 +196,12 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -165,8 +210,22 @@ version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ + "anstream", "anstyle", "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -175,6 +234,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "colored" version = "1.9.4" @@ -272,6 +337,23 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "ctor" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cf0d42651b16c6dfe68685716d18480d18a9c39c62d76e8cf3eb6ed5d8bcbf" +dependencies = [ + "ctor-proc-macro", + "dtor", + "link-section", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a949c44fcacbbbb7ada007dc7acb34603dd97cd47de5d054f2b6493ecebb483" + [[package]] name = "dashmap" version = "7.0.0-rc2" @@ -292,6 +374,21 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" +[[package]] +name = "dtor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf234dd1594d6dd434a8fb8cada51ddbbc593e40e4a01556a0b31c62da2775b" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2647271c92754afcb174e758003cfd1cbf1e43e5a7853d7b1813e63e19e39a73" + [[package]] name = "either" version = "1.15.0" @@ -329,6 +426,24 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fisher" +version = "0.1.0" +dependencies = [ + "jni", + "marten", +] + +[[package]] +name = "fisher-playback" +version = "0.1.0" +dependencies = [ + "clap", + "clap_derive", + "fisher", + "sable_rapier", +] + [[package]] name = "foldhash" version = "0.1.5" @@ -504,6 +619,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.5.2" @@ -527,6 +648,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" version = "0.13.0" @@ -614,6 +741,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "link-section" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b685d66585d646efe09fec763d796c291049c8b6bf84e04954bffc8748341f0d" + [[package]] name = "lock_api" version = "0.4.14" @@ -765,6 +898,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "oorandom" version = "11.1.5" @@ -1028,8 +1167,10 @@ version = "0.1.0" dependencies = [ "colored 2.2.0", "criterion", + "ctor", "dashmap", "fern", + "fisher", "humantime", "jni", "log", @@ -1169,6 +1310,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.117" @@ -1242,6 +1389,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/common/src/main/rust/Cargo.toml b/common/src/main/rust/Cargo.toml index 0600e54..a334625 100644 --- a/common/src/main/rust/Cargo.toml +++ b/common/src/main/rust/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "3" -members = ["marten", "rapier"] +members = ["fisher", "fisher-playback", "marten", "rapier"] [workspace.package] edition = "2024" @@ -8,6 +8,8 @@ version = "0.1.0" [workspace.dependencies] marten = { path = "marten" } +fisher = { path = "fisher" } +sable_rapier = { path = "rapier" } log = "0.4.22" jni = "0.21.1" @@ -21,4 +23,5 @@ lto = "thin" codegen-units = 1 [profile.bench] +inherits = "release" debug = true diff --git a/common/src/main/rust/fisher-playback/Cargo.toml b/common/src/main/rust/fisher-playback/Cargo.toml new file mode 100644 index 0000000..439fb8f --- /dev/null +++ b/common/src/main/rust/fisher-playback/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "fisher-playback" +edition.workspace = true +version.workspace = true + +[dependencies] +sable_rapier = { workspace = true, features = ["recording"] } +fisher.workspace = true +clap = { version = "4.6", features = ["derive"] } +clap_derive = { version = "4.6.1" } diff --git a/common/src/main/rust/fisher-playback/src/main.rs b/common/src/main/rust/fisher-playback/src/main.rs new file mode 100644 index 0000000..dba2af2 --- /dev/null +++ b/common/src/main/rust/fisher-playback/src/main.rs @@ -0,0 +1,31 @@ +use std::{fs::File, path::PathBuf, time::Instant}; + +use clap::Parser; +use fisher::imp::BorrowReader; +use sable_rapier::api::recording::CallType; + +fn main() { + let args = Arguments::parse(); + + let file = std::fs::read(args.instr_file).unwrap(); + let mut reader = BorrowReader::new(&file); + let start = Instant::now(); + while reader.remaining() != 0 { + let &[byte] = reader.get_bytes_const(); + let ty = CallType::new(byte); + + // dbg!(ty); + let trackable = ty.as_trackable(); + trackable.playback(&mut reader); + } + println!( + "run took {}ms", + Instant::now().saturating_duration_since(start).as_millis() + ); +} + +#[derive(Parser)] +pub struct Arguments { + /// The recorded file to parse + instr_file: PathBuf, +} diff --git a/common/src/main/rust/fisher/Cargo.toml b/common/src/main/rust/fisher/Cargo.toml new file mode 100644 index 0000000..0e4d52a --- /dev/null +++ b/common/src/main/rust/fisher/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "fisher" +edition.workspace = true +version.workspace = true + +[dependencies] +jni.workspace = true +marten.workspace = true + +[features] +enabled = [] +default = ["enabled"] diff --git a/common/src/main/rust/fisher/src/imp.rs b/common/src/main/rust/fisher/src/imp.rs new file mode 100644 index 0000000..17d14bc --- /dev/null +++ b/common/src/main/rust/fisher/src/imp.rs @@ -0,0 +1,150 @@ +use std::{ + array, + fs::File, + io::{self, BufWriter, Write}, + ops::{Deref, DerefMut}, + path::Path, + sync::{Mutex, MutexGuard}, +}; +pub mod argument_encodings; +pub use argument_encodings::BorrowReader; + +#[macro_export] +macro_rules! decl_tracked_api { + ( + $v:vis mod $modname:ident { $($tok:ident),+ $(,)? } + ) => { + /// test + #[expect(non_camel_case_types)] + $v mod $modname { + $( + pub struct $tok; + )+ + #[repr(u8)] + #[derive(::std::fmt::Debug, ::std::marker::Copy, ::std::clone::Clone)] + $v enum CallType { + $( $tok, )+ + __Last, + } + impl CallType { + pub fn new(id: u8) -> Self { + ::std::assert!(id < Self::__Last as u8); + unsafe { core::mem::transmute::(id) } + } + } + impl CallType { + pub fn as_trackable(self) -> &'static dyn $crate::imp::Trackable { + match self { + $( + Self::$tok => const { $crate::imp::require_trackable( &$tok ) } + ),+ + _ => ::std::unreachable!(), + } + } + } + } + macro_rules! __use_tracking_mod { () => { use self::$modname as __tracking; }; } + }; +} +pub const fn require_trackable(v: &'static T) -> &'static dyn Trackable { + v +} +pub const fn require_argument_encoding(_: &T) {} + +#[diagnostic::on_unimplemented( + message = "token `{Self}` is declared but has no tracked call. Instrument a call of this token with `tracked_call!`", + label = "this token has no corresponding tracked call", + note = "all tokens must have a tracked call" +)] +pub trait Trackable { + fn name(&self) -> &'static str; + fn playback(&self, reader: &mut BorrowReader<'_>); +} +#[macro_export] +macro_rules! tracked_call { + ( $f:ident( $($arg:expr),* $(,)?) ) => { + { + const TRACKED_ID: u8 = { + __use_tracking_mod!(); + #[expect(non_local_definitions)] + #[allow(unused_variables)] + impl $crate::imp::Trackable for __tracking::$f { + fn name(&self) -> &'static str { + ::std::stringify!($f) + } + fn playback(&self, reader: &mut $crate::imp::BorrowReader) { + $f( + $( + { + let _ = ::std::stringify!($arg); + $crate::imp::ArgumentEncode::read(reader) + } + ),* + ); + } + } + __tracking::CallType::$f as u8 + }; + + let mut w = $crate::imp::get_writer(); + if let ::std::option::Option::Some(w) = &mut *w { + w.frame(TRACKED_ID).unwrap(); + // TODO is there a way to drop w before calling f to shorten the critical section here? + $f($( + { + let arg = $arg; + $crate::imp::ArgumentEncode::write(&arg, &mut **w).expect("write to succeed"); + arg + } + ),* + ) + } else { + drop(w); + $f( $( $arg ),* ) + } + } + }; +} + +pub struct Writer(BufWriter); +impl Deref for Writer { + type Target = BufWriter; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for Writer { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +impl Writer { + pub fn frame(&mut self, id: u8) -> io::Result<()> { + self.write_all(array::from_ref(&id)) + } + pub fn new(p: impl AsRef) -> Self { + let f = File::options() + .write(true) + .create(true) + .truncate(true) + .open(p) + .expect("trace file to open"); + Self(BufWriter::new(f)) + } +} +pub static FISHER_WRITER: Mutex> = const { Mutex::new(None) }; + +pub fn get_writer<'a>() -> MutexGuard<'a, Option> { + FISHER_WRITER.lock().expect("mutex not to be poisoned") +} + +#[diagnostic::on_unimplemented( + message = "tracked call parameter type `{Self}` doesn't implement `ArgumentEncode`", + label = "this parameter doesn't implement `ArgumentEncode`", + note = "in order to record and playback tracked calls all of their parameters must implement `ArgumentEncode`. Please add an implementation to `rust/fisher`" +)] +pub trait ArgumentEncode: Sized { + fn read(reader: &mut BorrowReader<'_>) -> Self; + fn write(&self, writer: &mut impl Write) -> io::Result<()>; +} diff --git a/common/src/main/rust/fisher/src/imp/argument_encodings.rs b/common/src/main/rust/fisher/src/imp/argument_encodings.rs new file mode 100644 index 0000000..8c8ee97 --- /dev/null +++ b/common/src/main/rust/fisher/src/imp/argument_encodings.rs @@ -0,0 +1,142 @@ +use std::{ + array, + io::{self, Write}, +}; + +use jni::{ + JavaVM, + objects::GlobalRef, + sys::{jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jshort}, +}; +use marten::level::SableMethodID; + +use super::ArgumentEncode; + +/// Simple cursor that allows readers to temporarily borrow from its internal buffer +pub struct BorrowReader<'a> { + bytes: &'a [u8], + cursor: usize, +} +impl<'a> BorrowReader<'a> { + pub fn get_bytes(&mut self, ct: usize) -> &'a [u8] { + assert!(self.cursor + ct <= self.bytes.len()); + let out = &self.bytes[self.cursor..self.cursor + ct]; + self.cursor += ct; + out + } + pub fn get_bytes_const(&mut self) -> &[u8; N] { + self.get_bytes(N).first_chunk().unwrap() + } + pub fn new(bytes: &'a [u8]) -> Self { + Self { bytes, cursor: 0 } + } + pub fn remaining(&self) -> usize { + self.bytes.len() - self.cursor + } +} + +impl ArgumentEncode for () { + fn read(_: &mut BorrowReader) -> Self {} + fn write(&self, _: &mut impl Write) -> io::Result<()> { + Ok(()) + } +} + +macro_rules! numeric_argument_encodings { + ( $( $intty:ty ),+ ) => { + $( + impl ArgumentEncode for $intty { + fn read(reader: &mut BorrowReader<'_>) -> Self { + <$intty>::from_le_bytes(*reader.get_bytes_const()) + } + + fn write(&self, writer: &mut impl Write) -> io::Result<()> { + writer.write_all(&self.to_le_bytes()) + } + } + )+ + }; +} +numeric_argument_encodings!(jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble); + +impl ArgumentEncode for [T; N] { + fn read(reader: &mut BorrowReader) -> Self { + array::from_fn(|_| T::read(reader)) + } + + fn write(&self, writer: &mut impl Write) -> io::Result<()> { + for i in self.iter() { + i.write(writer)? + } + Ok(()) + } +} +impl ArgumentEncode for Box { + fn read(reader: &mut BorrowReader) -> Self { + Box::new(T::read(reader)) + } + + fn write(&self, writer: &mut impl Write) -> io::Result<()> { + (**self).write(writer) + } +} + +impl ArgumentEncode for Vec { + fn read(reader: &mut BorrowReader<'_>) -> Self { + let len = u32::from_le_bytes(*reader.get_bytes_const()); + let bytes = reader.get_bytes(len as usize * size_of::()); + bytes + .as_chunks() + .0 + .iter() + .copied() + .map(jdouble::from_le_bytes) + .collect() + } + + fn write(&self, writer: &mut impl Write) -> io::Result<()> { + writer.write_all( + &(u32::try_from(self.len()).expect("array len to be <= u32::MAX")).to_le_bytes(), + )?; + writer.write_all(unsafe { + core::slice::from_raw_parts(self.as_ptr().cast::(), std::mem::size_of_val(&**self)) + }) + } +} +impl ArgumentEncode for Vec { + fn read(reader: &mut BorrowReader<'_>) -> Self { + let len = u32::from_le_bytes(*reader.get_bytes_const()); + let bytes = reader.get_bytes(len as usize * size_of::()); + bytes + .as_chunks() + .0 + .iter() + .copied() + .map(jint::from_le_bytes) + .collect() + } + + fn write(&self, writer: &mut impl Write) -> io::Result<()> { + writer.write_all( + &(u32::try_from(self.len()).expect("array len to be <= u32::MAX")).to_le_bytes(), + )?; + writer.write_all(unsafe { + core::slice::from_raw_parts(self.as_ptr().cast::(), std::mem::size_of_val(&**self)) + }) + } +} +macro_rules! ignore_option_impls { + ( $( $opt:ty ),+ ) => { + $( + impl ArgumentEncode for Option<$opt> { + fn read(_: &mut BorrowReader<'_>) -> Self { + None + } + fn write(&self, _: &mut impl Write) -> io::Result<()> { + Ok(()) + } + } + )+ + }; +} +ignore_option_impls!(JavaVM, GlobalRef, SableMethodID); diff --git a/common/src/main/rust/fisher/src/lib.rs b/common/src/main/rust/fisher/src/lib.rs new file mode 100644 index 0000000..d02ab0b --- /dev/null +++ b/common/src/main/rust/fisher/src/lib.rs @@ -0,0 +1,32 @@ +use std::io::Write; + +use crate::imp::FISHER_WRITER; + +#[cfg(feature = "enabled")] +pub mod imp; + +#[cfg(not(feature = "enabled"))] +#[macro_export] +macro_rules! decl_tracked_api { + ( $( $any:tt )* ) => {}; +} +#[cfg(not(feature = "enabled"))] +#[macro_export] +macro_rules! tracked_call { + ( $( $any:tt )* ) => { $( $any )* }; + } + +pub fn setup_trace() { + use std::sync::Once; + + use crate::imp::Writer; + static OPEN_FILE_ONCE: Once = Once::new(); + OPEN_FILE_ONCE + .call_once(|| *imp::FISHER_WRITER.lock().unwrap() = Some(Writer::new("sable_trace.bin"))); +} +pub fn finish_trace() { + if let Some(mut v) = FISHER_WRITER.lock().unwrap().take() { + v.flush().unwrap(); + drop(v); + } +} diff --git a/common/src/main/rust/rapier/Cargo.toml b/common/src/main/rust/rapier/Cargo.toml index b74eb39..549e019 100644 --- a/common/src/main/rust/rapier/Cargo.toml +++ b/common/src/main/rust/rapier/Cargo.toml @@ -5,6 +5,7 @@ edition.workspace = true [dependencies] marten.workspace = true +fisher = { workspace = true } fern.workspace = true jni.workspace = true @@ -20,6 +21,7 @@ rapier3d = { git = "https://github.com/ryanhcode/rapier", rev = "a728067629d4f85 rayon = "1.10.0" dashmap = "7.0.0-rc2" +ctor = { version = "0.10.1", optional = true } [lib] crate-type = ["cdylib", "lib"] @@ -32,3 +34,9 @@ harness = false [dev-dependencies] criterion = "0.8.2" + +[features] +#TODO remove +default = ["recording"] + +recording = ["fisher/enabled", "dep:ctor"] diff --git a/common/src/main/rust/rapier/src/api.rs b/common/src/main/rust/rapier/src/api.rs new file mode 100644 index 0000000..9c53cbe --- /dev/null +++ b/common/src/main/rust/rapier/src/api.rs @@ -0,0 +1,950 @@ +use core::slice; + +use fisher::tracked_call; +use jni::{ + JNIEnv, JavaVM, + objects::{JClass, JDoubleArray, JIntArray, JObject}, + sys::{jboolean, jdouble, jint, jlong, jsize}, +}; +use marten::level::SableMethodID; + +use crate::{ + add_chunk, add_linear_velocities, apply_force, apply_force_and_torque, + boxes::{create_box, remove_box}, + change_block, clear_collisions, + config::{config_frequency_and_damping, config_min_island_size, config_solver_iterations}, + contraptions::{ + add_kinematic_contraption_chunk_section, create_kinematic_contraption, + remove_kinematic_contraption, set_kinematic_contraption_transform, + }, + create_sub_level, get_angular_velocity, get_linear_velocity, get_pose, initialize, + joints::{ + add_fixed_constraint, add_free_constraint, add_generic_constraint, add_rotary_constraint, + get_constraint_impulses, is_constraint_valid, remove_constraint, + set_constraint_contacts_enabled, set_constraint_frame, set_constraint_motor, + }, + remove_chunk, remove_sub_level, + rope::{ + add_rope_point_at_start, create_rope, query_rope, remove_rope, remove_rope_point_at_start, + set_rope_attachment, set_rope_first_segment_length, wake_up_rope, + }, + set_center_of_mass, set_local_bounds, set_mass_properties, step, teleport_object, tick, + voxel_collider::{add_voxel_collider_box, clear_voxel_collider_boxes, new_voxel_collider}, + wake_up_object, +}; +macro_rules! extract_jdouble_array { + ($env:expr, $jarr:expr, $len:expr) => {{ + let mut arr = [0.0 as jdouble; $len]; + $env.get_double_array_region($jarr, 0, &mut arr).unwrap(); + arr + }}; +} + +fisher::decl_tracked_api! { + pub mod recording { + add_chunk, add_linear_velocities, apply_force, apply_force_and_torque, create_box, remove_box, change_block, clear_collisions, + config_frequency_and_damping, config_min_island_size, config_solver_iterations, + add_kinematic_contraption_chunk_section, create_kinematic_contraption, + remove_kinematic_contraption, set_kinematic_contraption_transform, + create_sub_level, get_angular_velocity, get_linear_velocity, get_pose, initialize, + add_fixed_constraint, add_free_constraint, add_generic_constraint, add_rotary_constraint, + get_constraint_impulses, is_constraint_valid, remove_constraint, + set_constraint_contacts_enabled, set_constraint_frame, set_constraint_motor, + remove_chunk, remove_sub_level, + add_rope_point_at_start, create_rope, query_rope, remove_rope, remove_rope_point_at_start, + set_rope_attachment, set_rope_first_segment_length, wake_up_rope, + set_center_of_mass, set_local_bounds, set_mass_properties, step, teleport_object, tick, + add_voxel_collider_box, clear_voxel_collider_boxes, new_voxel_collider, + wake_up_object, + } +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createBox<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + mass: jdouble, + half_extent_x: jdouble, + half_extent_y: jdouble, + half_extent_z: jdouble, + pose: JDoubleArray<'local>, +) { + let pose_arr: [jdouble; 7] = extract_jdouble_array!(env, pose, 7); + + tracked_call!(create_box( + scene_id, + id, + mass, + half_extent_x, + half_extent_y, + half_extent_z, + pose_arr, + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeBox<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, +) { + tracked_call!(remove_box(scene_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_configFrequencyAndDamping< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + collision_natural_frequency: jdouble, + collision_damping_ratio: jdouble, +) { + tracked_call!(config_frequency_and_damping( + collision_natural_frequency, + collision_damping_ratio + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_configSolverIterations< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + num_solver_iterations: jint, + num_internal_pgs_iterations: jint, + num_internal_stabilization_iterations: jint, +) { + tracked_call!(config_solver_iterations( + num_solver_iterations, + num_internal_pgs_iterations, + num_internal_stabilization_iterations, + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_configMinIslandSize< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + island_size: jint, +) { + tracked_call!(config_min_island_size(island_size)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createKinematicContraption< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + mount_id: jint, + id: jint, + _pose: JDoubleArray<'local>, +) { + tracked_call!(create_kinematic_contraption(scene_id, mount_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setKinematicContraptionTransform< + 'local, +>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + center_of_mass: JDoubleArray<'local>, + pose: JDoubleArray<'local>, + velocities: JDoubleArray<'local>, +) { + let center_of_mass_arr = extract_jdouble_array!(env, center_of_mass, 3); + let pose_arr = extract_jdouble_array!(env, pose, 7); + let velocities_arr = extract_jdouble_array!(env, velocities, 6); + tracked_call!(set_kinematic_contraption_transform( + scene_id, + id, + center_of_mass_arr, + pose_arr, + velocities_arr + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addKinematicContraptionChunkSection< + 'local, +>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + x: jint, + y: jint, + z: jint, + data: JIntArray<'local>, +) { + let mut buf = Box::<[i32; 4096]>::new_uninit(); + env.get_int_array_region(data, 0, unsafe { + slice::from_raw_parts_mut((*buf).as_mut_ptr().cast(), 4096) + }) + .expect("to copy int array"); + let buf = unsafe { buf.assume_init() }; + tracked_call!(add_kinematic_contraption_chunk_section( + scene_id, id, x, y, z, buf + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeKinematicContraption< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, +) { + tracked_call!(remove_kinematic_contraption(scene_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setConstraintMotor< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + joint_id: jlong, + axis: jint, + target_pos: jdouble, + stiffness: jdouble, + damping: jdouble, + has_max_force: jboolean, + max_force: jdouble, +) { + tracked_call!(set_constraint_motor( + scene_id, + joint_id, + axis, + target_pos, + stiffness, + damping, + has_max_force, + max_force, + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_isConstraintValid< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + joint_id: jlong, +) -> jboolean { + tracked_call!(is_constraint_valid(scene_id, joint_id)) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getConstraintImpulses< + 'local, +>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + joint_id: jlong, + store: JDoubleArray<'local>, +) { + let arr = tracked_call!(get_constraint_impulses(scene_id, joint_id)); + env.set_double_array_region(&store, 0, &arr).unwrap(); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setConstraintContactsEnabled< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + joint_id: jlong, + enabled: jboolean, +) { + tracked_call!(set_constraint_contacts_enabled(scene_id, joint_id, enabled)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeConstraint< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + joint_id: jlong, +) { + tracked_call!(remove_constraint(scene_id, joint_id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addRotaryConstraint< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id_a: jint, + id_b: jint, + local_x_a: jdouble, + local_y_a: jdouble, + local_z_a: jdouble, + local_x_b: jdouble, + local_y_b: jdouble, + local_z_b: jdouble, + axis_x_a: jdouble, + axis_y_a: jdouble, + axis_z_a: jdouble, + axis_x_b: jdouble, + axis_y_b: jdouble, + axis_z_b: jdouble, +) -> jlong { + tracked_call!(add_rotary_constraint( + scene_id, id_a, id_b, local_x_a, local_y_a, local_z_a, local_x_b, local_y_b, local_z_b, + axis_x_a, axis_y_a, axis_z_a, axis_x_b, axis_y_b, axis_z_b, + )) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addFixedConstraint< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id_a: jint, + id_b: jint, + local_x_a: jdouble, + local_y_a: jdouble, + local_z_a: jdouble, + local_x_b: jdouble, + local_y_b: jdouble, + local_z_b: jdouble, + local_q_x: jdouble, + local_q_y: jdouble, + local_q_z: jdouble, + local_q_w: jdouble, +) -> jlong { + tracked_call!(add_fixed_constraint( + scene_id, id_a, id_b, local_x_a, local_y_a, local_z_a, local_x_b, local_y_b, local_z_b, + local_q_x, local_q_y, local_q_z, local_q_w, + )) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addFreeConstraint< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id_a: jint, + id_b: jint, + local_x_a: jdouble, + local_y_a: jdouble, + local_z_a: jdouble, + local_x_b: jdouble, + local_y_b: jdouble, + local_z_b: jdouble, + local_q_x: jdouble, + local_q_y: jdouble, + local_q_z: jdouble, + local_q_w: jdouble, +) -> jlong { + tracked_call!(add_free_constraint( + scene_id, id_a, id_b, local_x_a, local_y_a, local_z_a, local_x_b, local_y_b, local_z_b, + local_q_x, local_q_y, local_q_z, local_q_w, + )) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addGenericConstraint< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id_a: jint, + id_b: jint, + local_x_a: jdouble, + local_y_a: jdouble, + local_z_a: jdouble, + local_q_x_a: jdouble, + local_q_y_a: jdouble, + local_q_z_a: jdouble, + local_q_w_a: jdouble, + local_x_b: jdouble, + local_y_b: jdouble, + local_z_b: jdouble, + local_q_x_b: jdouble, + local_q_y_b: jdouble, + local_q_z_b: jdouble, + local_q_w_b: jdouble, + locked_axes_mask: jint, +) -> jlong { + tracked_call!(add_generic_constraint( + scene_id, + id_a, + id_b, + local_x_a, + local_y_a, + local_z_a, + local_q_x_a, + local_q_y_a, + local_q_z_a, + local_q_w_a, + local_x_b, + local_y_b, + local_z_b, + local_q_x_b, + local_q_y_b, + local_q_z_b, + local_q_w_b, + locked_axes_mask, + )) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setConstraintFrame< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + joint_id: jlong, + side: jint, + local_x: jdouble, + local_y: jdouble, + local_z: jdouble, + local_q_x: jdouble, + local_q_y: jdouble, + local_q_z: jdouble, + local_q_w: jdouble, +) { + tracked_call!(set_constraint_frame( + scene_id, joint_id, side, local_x, local_y, local_z, local_q_x, local_q_y, local_q_z, + local_q_w, + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_initialize<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + x: jdouble, + y: jdouble, + z: jdouble, + universal_drag: jdouble, +) { + let vm = unsafe { JavaVM::from_raw(env.get_java_vm().unwrap().get_java_vm_pointer()).unwrap() }; + tracked_call!(initialize(Some(vm), scene_id, x, y, z, universal_drag)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_tick<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + _time_step: jdouble, +) { + tracked_call!(tick(scene_id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_step<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + time_step: jdouble, +) { + tracked_call!(step(scene_id, time_step)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getPose<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + store: JDoubleArray<'local>, +) { + let arr: [jdouble; 7] = tracked_call!(get_pose(scene_id, id)); + env.set_double_array_region(&store, 0, &arr).unwrap(); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setCenterOfMass< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + x: jdouble, + y: jdouble, + z: jdouble, +) { + tracked_call!(set_center_of_mass(scene_id, id, x, y, z)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setLocalBounds< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + min_x: jint, + min_y: jint, + min_z: jint, + max_x: jint, + max_y: jint, + max_z: jint, +) { + tracked_call!(set_local_bounds( + scene_id, id, min_x, min_y, min_z, max_x, max_y, max_z + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createSubLevel< + 'local, +>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + pose: JDoubleArray<'local>, +) { + let pose_arr = extract_jdouble_array!(env, pose, 7); + tracked_call!(create_sub_level(scene_id, id, pose_arr)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeSubLevel< + 'local, +>( + mut _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, +) { + tracked_call!(remove_sub_level(scene_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addChunk<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + x: jint, + y: jint, + z: jint, + data: JIntArray<'local>, + global: jboolean, + object_id: jint, +) { + let mut buf = Box::<[i32; 4096]>::new_uninit(); + env.get_int_array_region(data, 0, unsafe { + slice::from_raw_parts_mut((*buf).as_mut_ptr().cast(), 4096) + }) + .expect("to copy int array"); + let buf = unsafe { buf.assume_init() }; + tracked_call!(add_chunk(scene_id, x, y, z, buf, global, object_id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeChunk<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + x: jint, + y: jint, + z: jint, + global: jboolean, +) { + tracked_call!(remove_chunk(scene_id, x, y, z, global)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_changeBlock<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + x: jint, + y: jint, + z: jint, + block: jint, +) { + tracked_call!(change_block(scene_id, x, y, z, block)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setMassProperties< + 'local, +>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + mass: jdouble, + center_of_mass: JDoubleArray<'local>, + inertia: JDoubleArray<'local>, +) { + let com = extract_jdouble_array!(env, center_of_mass, 3); + let inertia_arr = extract_jdouble_array!(env, inertia, 9); + + tracked_call!(set_mass_properties(scene_id, id, mass, com, inertia_arr)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_teleportObject< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + x: jdouble, + y: jdouble, + z: jdouble, + i: jdouble, + j: jdouble, + k: jdouble, + r: jdouble, +) { + tracked_call!(teleport_object(scene_id, id, x, y, z, i, j, k, r)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_wakeUpObject< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, +) { + tracked_call!(wake_up_object(scene_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addLinearAngularVelocities< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + linear_x: jdouble, + linear_y: jdouble, + linear_z: jdouble, + angular_x: jdouble, + angular_y: jdouble, + angular_z: jdouble, + wake_up: jboolean, +) { + tracked_call!(add_linear_velocities( + scene_id, id, linear_x, linear_y, linear_z, angular_x, angular_y, angular_z, wake_up, + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_clearCollisions< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, +) -> JDoubleArray<'local> { + let arr = tracked_call!(clear_collisions(scene_id)); + let double_array = _env.new_double_array(arr.len() as jint).unwrap(); + _env.set_double_array_region(&double_array, 0, &arr) + .unwrap(); + + double_array +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_applyForce<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + x: jdouble, + y: jdouble, + z: jdouble, + fx: jdouble, + fy: jdouble, + fz: jdouble, + wake_up: jboolean, +) { + tracked_call!(apply_force(scene_id, id, x, y, z, fx, fy, fz, wake_up)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_applyForceAndTorque< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + fx: jdouble, + fy: jdouble, + fz: jdouble, + tx: jdouble, + ty: jdouble, + tz: jdouble, + wake_up: jboolean, +) { + tracked_call!(apply_force_and_torque( + scene_id, id, fx, fy, fz, tx, ty, tz, wake_up + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getLinearVelocity< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + store: JDoubleArray<'local>, +) { + _env.set_double_array_region(&store, 0, &tracked_call!(get_linear_velocity(scene_id, id))) + .unwrap(); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getAngularVelocity< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jint, + store: JDoubleArray<'local>, +) { + _env.set_double_array_region( + &store, + 0, + &tracked_call!(get_angular_velocity(scene_id, id)), + ) + .unwrap(); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createRope<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + point_radius: jdouble, + first_joint_length: jdouble, + points: JDoubleArray<'local>, + num_points: jint, +) -> jlong { + let mut coordinates = vec![0.0; (num_points * 3) as usize]; + env.get_double_array_region(points, 0, &mut coordinates) + .unwrap(); + tracked_call!(create_rope( + scene_id, + point_radius, + first_joint_length, + coordinates, + num_points, + )) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_queryRope<'local>( + env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jlong, +) -> JDoubleArray<'local> { + let flattened = tracked_call!(query_rope(scene_id, id)); + let double_array = env.new_double_array((flattened.len()) as jsize).unwrap(); + env.set_double_array_region(&double_array, 0, &flattened) + .unwrap(); + double_array +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeRope<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jlong, +) { + tracked_call!(remove_rope(scene_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setRopeFirstSegmentLength< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jlong, + length: jdouble, +) { + tracked_call!(set_rope_first_segment_length(scene_id, id, length)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeRopePointAtStart< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jlong, +) { + tracked_call!(remove_rope_point_at_start(scene_id, id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addRopePointAtStart< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + id: jlong, + x: jdouble, + y: jdouble, + z: jdouble, +) { + tracked_call!(add_rope_point_at_start(scene_id, id, x, y, z)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_wakeUpRope<'local>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + rope_id: jlong, +) { + tracked_call!(wake_up_rope(scene_id, rope_id)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setRopeAttachment< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + scene_id: jint, + rope_id: jlong, + sub_level_id: jint, + x: jdouble, + y: jdouble, + z: jdouble, + end: jboolean, +) { + tracked_call!(set_rope_attachment( + scene_id, + rope_id, + sub_level_id, + x, + y, + z, + end + )); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_newVoxelCollider< + 'local, +>( + mut env: JNIEnv<'static>, + _class: JClass<'local>, + friction: jdouble, + volume: jdouble, + restitution: jdouble, + is_fluid: jboolean, + contact_events: JObject, + dynamic: jboolean, +) -> jint { + let global_ref = if contact_events.is_null() { + None + } else { + Some(env.new_global_ref(contact_events).unwrap()) + }; + + let global_method = if let Some(global_ref_value) = &global_ref { + let class = env.get_object_class(global_ref_value).unwrap(); + + let id = SableMethodID( + env.get_method_id( + class, + String::from("onCollision"), + String::from("(IIIDDDD)[D"), + ) + .unwrap(), + ); + Some(id) + } else { + None + }; + tracked_call!(new_voxel_collider( + friction, + volume, + restitution, + is_fluid, + dynamic, + global_ref, + global_method, + )) +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addVoxelColliderBox< + 'local, +>( + env: JNIEnv<'local>, + _class: JClass<'local>, + index: jint, + box_bounds: JDoubleArray<'local>, +) { + let bounds = extract_jdouble_array!(env, box_bounds, 6); + tracked_call!(add_voxel_collider_box(index, bounds)); +} + +#[unsafe(no_mangle)] +pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_clearVoxelColliderBoxes< + 'local, +>( + _env: JNIEnv<'local>, + _class: JClass<'local>, + index: jint, +) { + tracked_call!(clear_voxel_collider_boxes(index)); +} +#[cfg(feature = "recording")] +#[ctor::ctor] +pub fn ctor() { + fisher::setup_trace(); +} +#[cfg(feature = "recording")] +#[ctor::dtor] +pub fn dtor() { + fisher::finish_trace(); +} diff --git a/common/src/main/rust/rapier/src/boxes.rs b/common/src/main/rust/rapier/src/boxes.rs index cb22eb9..20e2ee9 100644 --- a/common/src/main/rust/rapier/src/boxes.rs +++ b/common/src/main/rust/rapier/src/boxes.rs @@ -1,5 +1,3 @@ -use jni::JNIEnv; -use jni::objects::{JClass, JDoubleArray}; use jni::sys::{jdouble, jint}; use marten::Real; use rapier3d::dynamics::RigidBodyBuilder; @@ -10,21 +8,15 @@ use rapier3d::math::Vector; use crate::get_scene_mut; use crate::scene::LevelColliderID; -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createBox<'local>( - env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn create_box( scene_id: jint, id: jint, mass: jdouble, half_extent_x: jdouble, half_extent_y: jdouble, half_extent_z: jdouble, - pose: JDoubleArray<'local>, + pose_arr: [jdouble; 7], ) { - let mut pose_arr: [jdouble; 7] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; - env.get_double_array_region(pose, 0, &mut pose_arr).unwrap(); - let quat = Quat::from_xyzw( pose_arr[3] as Real, pose_arr[4] as Real, @@ -63,13 +55,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_cre scene.rigid_bodies.insert(id as LevelColliderID, handle); } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeBox<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, -) { +pub fn remove_box(scene_id: jint, id: jint) { let scene = get_scene_mut(scene_id); let handle = scene.rigid_bodies[&(id as LevelColliderID)]; scene.rigid_body_set.remove( diff --git a/common/src/main/rust/rapier/src/config.rs b/common/src/main/rust/rapier/src/config.rs index 62db42c..1a478e3 100644 --- a/common/src/main/rust/rapier/src/config.rs +++ b/common/src/main/rust/rapier/src/config.rs @@ -1,5 +1,3 @@ -use jni::JNIEnv; -use jni::objects::JClass; use jni::sys::{jdouble, jint}; use marten::Real; @@ -11,12 +9,7 @@ pub const JOINT_SPRING_FREQUENCY: Real = 550.0; /// Global damping ratio for joints pub const JOINT_SPRING_DAMPING_RATIO: Real = 4.0; -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_configFrequencyAndDamping< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn config_frequency_and_damping( collision_natural_frequency: jdouble, collision_damping_ratio: jdouble, ) { @@ -34,12 +27,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_con } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_configSolverIterations< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn config_solver_iterations( num_solver_iterations: jint, num_internal_pgs_iterations: jint, num_internal_stabilization_iterations: jint, @@ -59,14 +47,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_con } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_configMinIslandSize< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - island_size: jint, -) { +pub fn config_min_island_size(island_size: jint) { unsafe { if let Some(state) = &mut PHYSICS_STATE { state.integration_parameters.min_island_size = island_size as usize; diff --git a/common/src/main/rust/rapier/src/contraptions.rs b/common/src/main/rust/rapier/src/contraptions.rs index 1611453..3f58ba7 100644 --- a/common/src/main/rust/rapier/src/contraptions.rs +++ b/common/src/main/rust/rapier/src/contraptions.rs @@ -1,7 +1,5 @@ use std::collections::HashMap; -use jni::JNIEnv; -use jni::objects::{JClass, JDoubleArray, JIntArray}; use jni::sys::{jdouble, jint}; use marten::Real; use rapier3d::dynamics::RigidBodyBuilder; @@ -17,22 +15,6 @@ use crate::groups::LEVEL_GROUP; use crate::scene::LevelColliderID; use crate::{ActiveLevelColliderInfo, get_scene_mut_ref}; -macro_rules! extract_jdouble_array { - ($env:expr, $jarr:expr, $len:expr) => {{ - let mut arr = [0.0 as jdouble; $len]; - $env.get_double_array_region($jarr, 0, &mut arr).unwrap(); - arr - }}; -} - -macro_rules! extract_jint_array { - ($env:expr, $jarr:expr, $len:expr) => {{ - let mut arr = [0 as jint; $len]; - $env.get_int_array_region($jarr, 0, &mut arr).unwrap(); - arr - }}; -} - // Helper for getting a mutable kinematic sub-level collider info fn get_kinematic_collider_info( scene: &mut crate::scene::PhysicsScene, @@ -44,16 +26,11 @@ fn get_kinematic_collider_info( .expect("No kinematic contraption with given ID!") } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createKinematicContraption< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn create_kinematic_contraption( scene_id: jint, mount_id: jint, id: jint, - _pose: JDoubleArray<'local>, + // pose_arr: [jdouble; 7] ) { let scene = get_scene_mut_ref(scene_id); @@ -104,21 +81,14 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_cre } /// Set the transform (position/orientation) of a kinematic sub-level's center of mass relative to its parent -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setKinematicContraptionTransform< - 'local, ->( - env: JNIEnv<'local>, - _class: JClass<'local>, +#[inline] +pub fn set_kinematic_contraption_transform( scene_id: jint, id: jint, - center_of_mass: JDoubleArray<'local>, - pose: JDoubleArray<'local>, - velocities: JDoubleArray<'local>, + center_of_mass_arr: [jdouble; 3], + pose_arr: [jdouble; 7], + velocities_arr: [jdouble; 6], ) { - let center_of_mass_arr = extract_jdouble_array!(env, center_of_mass, 3); - let pose_arr = extract_jdouble_array!(env, pose, 7); - let velocities_arr = extract_jdouble_array!(env, velocities, 6); let translation = Vector3::new( pose_arr[0] as Real, pose_arr[1] as Real, @@ -183,22 +153,16 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set } /// Add a chunk to a kinematic sub-level (4096 blocks, each as packed int) -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addKinematicContraptionChunkSection< - 'local, ->( - env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_kinematic_contraption_chunk_section( scene_id: jint, id: jint, x: jint, y: jint, z: jint, - data: JIntArray<'local>, + ints: Box<[jint; 4096]>, ) { - let ints = extract_jint_array!(env, data, 4096); let mut blocks = Vec::with_capacity(ints.len()); - for block in ints { + for block in ints.into_iter() { let block_collider_id = (block >> 16) as u16; let voxel_state_id = (block & 0xFFFF) as u16; blocks.push(( @@ -217,15 +181,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add } /// Remove a kinematic sub-level from a scene -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeKinematicContraption< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, -) { +pub fn remove_kinematic_contraption(scene_id: jint, id: jint) { let scene = get_scene_mut_ref(scene_id); let info = scene.level_colliders.remove(&(id as LevelColliderID)); let info = info.unwrap(); diff --git a/common/src/main/rust/rapier/src/joints.rs b/common/src/main/rust/rapier/src/joints.rs index 71f6a7d..5d01ced 100644 --- a/common/src/main/rust/rapier/src/joints.rs +++ b/common/src/main/rust/rapier/src/joints.rs @@ -1,8 +1,6 @@ use crate::config::{JOINT_SPRING_DAMPING_RATIO, JOINT_SPRING_FREQUENCY}; use crate::scene::LevelColliderID; use crate::{get_scene_mut_ref, get_scene_ref}; -use jni::JNIEnv; -use jni::objects::{JClass, JDoubleArray}; use jni::sys::{jboolean, jdouble, jint, jlong}; use marten::Real; use rapier3d::dynamics::{ @@ -118,12 +116,7 @@ const AXES: [JointAxis; 6] = [ JointAxis::AngZ, ]; -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setConstraintMotor< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn set_constraint_motor( scene_id: jint, joint_id: jlong, axis: jint, @@ -155,15 +148,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_isConstraintValid< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - joint_id: jlong, -) -> jboolean { +pub fn is_constraint_valid(scene_id: jint, joint_id: jlong) -> jboolean { let scene = get_scene_ref(scene_id); if scene.joint_set.joints.contains_key(&joint_id) { 1 @@ -172,43 +157,22 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_isC } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getConstraintImpulses< - 'local, ->( - env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - joint_id: jlong, - store: JDoubleArray<'local>, -) { +pub fn get_constraint_impulses(scene_id: jint, joint_id: jlong) -> [jdouble; 6] { let scene = get_scene_ref(scene_id); let joint = scene.joint_set.joints.get(&joint_id).unwrap(); let impulse_joint = scene.impulse_joint_set.get(joint.handle).unwrap(); let impulses = impulse_joint.impulses; - - let arr: [jdouble; 6] = [ + [ impulses[0] as jdouble, impulses[1] as jdouble, impulses[2] as jdouble, impulses[3] as jdouble, impulses[4] as jdouble, impulses[5] as jdouble, - ]; - - env.set_double_array_region(&store, 0, &arr).unwrap(); + ] } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setConstraintContactsEnabled< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - joint_id: jlong, - enabled: jboolean, -) { +pub fn set_constraint_contacts_enabled(scene_id: jint, joint_id: jlong, enabled: jboolean) { let scene = get_scene_mut_ref(scene_id); let Some(joint) = scene.joint_set.joints.get_mut(&joint_id) else { return; @@ -217,28 +181,15 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set joint.contacts_enabled = enabled > 0; } -// removes a constraint -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeConstraint< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - joint_id: jlong, -) { +/// removes a constraint +pub fn remove_constraint(scene_id: jint, joint_id: jlong) { let scene = get_scene_mut_ref(scene_id); if let Some(joint) = scene.joint_set.joints.remove(&joint_id) { scene.impulse_joint_set.remove(joint.handle, true); } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addRotaryConstraint< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_rotary_constraint( scene_id: jint, id_a: jint, id_b: jint, @@ -319,12 +270,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add handle_long } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addFixedConstraint< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_fixed_constraint( scene_id: jint, id_a: jint, id_b: jint, @@ -408,12 +354,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add handle_long } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addFreeConstraint< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_free_constraint( scene_id: jint, id_a: jint, id_b: jint, @@ -494,12 +435,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add handle_long } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addGenericConstraint< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_generic_constraint( scene_id: jint, id_a: jint, id_b: jint, @@ -595,12 +531,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add handle_long } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setConstraintFrame< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn set_constraint_frame( scene_id: jint, joint_id: jlong, side: jint, diff --git a/common/src/main/rust/rapier/src/lib.rs b/common/src/main/rust/rapier/src/lib.rs index 6e3f5eb..06a5d20 100644 --- a/common/src/main/rust/rapier/src/lib.rs +++ b/common/src/main/rust/rapier/src/lib.rs @@ -1,6 +1,7 @@ #![allow(static_mut_refs)] pub mod algo; +pub mod api; pub mod boxes; mod buoyancy; mod collider; @@ -15,9 +16,8 @@ pub mod rope; mod scene; mod voxel_collider; -use jni::objects::{JClass, JDoubleArray, JIntArray}; +use jni::JavaVM; use jni::sys::{jboolean, jdouble, jint}; -use jni::{JNIEnv, JavaVM}; use rapier3d::glamx::Quat; use rapier3d::math::Vector; use std::collections::HashMap; @@ -313,10 +313,8 @@ pub fn get_rigid_body(scene: &PhysicsScene, id: LevelColliderID) -> &RigidBody { &scene.rigid_body_set[*handle] } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_initialize<'local>( - env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn initialize( + current_step_vm: Option, scene_id: jint, x: jdouble, y: jdouble, @@ -403,7 +401,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_ini rope_map: RopeMap::default(), level_colliders: HashMap::::new(), rigid_bodies: HashMap::::new(), - current_step_vm: None, + current_step_vm, gravity: Vector::new(x as Real, y as Real, z as Real), universal_drag: universal_drag as Real, manifold_info_map: SableManifoldInfoMap::default(), @@ -411,8 +409,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_ini scene.collider_set.insert(collider); scene.ground_handle = Some(scene.rigid_body_set.insert(ground)); - scene.current_step_vm = - Some(JavaVM::from_raw(env.get_java_vm().unwrap().get_java_vm_pointer()).unwrap()); + state.scenes.insert(scene_id, scene); } } @@ -421,12 +418,9 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_ini } /// Computes buoyancy -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_tick<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn tick( scene_id: jint, - _time_step: jdouble, + // _time_step: jdouble ) { unsafe { if let Some(state) = &mut PHYSICS_STATE { @@ -443,13 +437,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_tic } /// Steps physics -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_step<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - time_step: jdouble, -) { +pub fn step(scene_id: jint, time_step: jdouble) { unsafe { if let Some(state) = &mut PHYSICS_STATE { rope::tick(scene_id); @@ -481,22 +469,14 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_ste } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getPose<'local>( - env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, - store: JDoubleArray<'local>, -) { +pub fn get_pose(scene_id: jint, id: jint) -> [jdouble; 7] { unsafe { let Some(scene) = get_physics_state().scenes.get(&scene_id) else { panic!("No scene with given ID!"); }; let rb: &RigidBody = &scene.rigid_body_set[scene.rigid_bodies[&(id as LevelColliderID)]]; - - let arr: [jdouble; 7] = [ + [ rb.translation().x as jdouble, rb.translation().y as jdouble, rb.translation().z as jdouble, @@ -504,24 +484,11 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_get rb.rotation().y as jdouble, rb.rotation().z as jdouble, rb.rotation().w as jdouble, - ]; - - env.set_double_array_region(&store, 0, &arr).unwrap(); + ] } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setCenterOfMass< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, - x: jdouble, - y: jdouble, - z: jdouble, -) { +pub fn set_center_of_mass(scene_id: jint, id: jint, x: jdouble, y: jdouble, z: jdouble) { unsafe { if let Some(state) = &mut PHYSICS_STATE { let Some(scene) = state.scenes.get_mut(&scene_id) else { @@ -537,12 +504,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setLocalBounds< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn set_local_bounds( scene_id: jint, id: jint, min_x: jint, @@ -571,19 +533,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createSubLevel< - 'local, ->( - env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, - pose: JDoubleArray<'local>, -) { - let mut pose_arr: [jdouble; 7] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; - env.get_double_array_region(pose, 0, &mut pose_arr).unwrap(); - +pub fn create_sub_level(scene_id: jint, id: jint, pose_arr: [jdouble; 7]) { let quat = Quat::from_xyzw( pose_arr[3] as Real, pose_arr[4] as Real, @@ -643,15 +593,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_cre } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeSubLevel< - 'local, ->( - mut _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, -) { +pub fn remove_sub_level(scene_id: jint, id: jint) { unsafe { if let Some(state) = &mut PHYSICS_STATE { let Some(scene) = state.scenes.get_mut(&scene_id) else { @@ -716,24 +658,18 @@ pub fn insert_block_octree( } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addChunk<'local>( - env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_chunk( scene_id: jint, x: jint, y: jint, z: jint, - data: JIntArray<'local>, + ints: Box<[jint; 4096]>, global: jboolean, object_id: jint, ) { - let mut ints: [jint; 4096] = [0; 4096]; - env.get_int_array_region(data, 0, &mut ints).unwrap(); - let mut blocks = Vec::with_capacity(ints.len()); - for block in ints { + for block in ints.into_iter() { // split it in half let block_collider_id = (block >> 16) as u16; let voxel_state_id = (block & 0xFFFF) as u16; @@ -856,16 +792,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeChunk<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - x: jint, - y: jint, - z: jint, - global: jboolean, -) { +pub fn remove_chunk(scene_id: jint, x: jint, y: jint, z: jint, global: jboolean) { unsafe { if let Some(state) = &mut PHYSICS_STATE { let Some(scene) = state.scenes.get_mut(&scene_id) else { @@ -924,16 +851,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_rem } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_changeBlock<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - x: jint, - y: jint, - z: jint, - block: jint, -) { +pub fn change_block(scene_id: jint, x: jint, y: jint, z: jint, block: jint) { let block_collider_id = (block >> 16) as u16; let voxel_state_id = (block & 0xFFFF) as u16; @@ -1035,26 +953,13 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_cha } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setMassProperties< - 'local, ->( - env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn set_mass_properties( scene_id: jint, id: jint, mass: jdouble, - center_of_mass: JDoubleArray<'local>, - inertia: JDoubleArray<'local>, + _com: [jdouble; 3], + inertia_arr: [jdouble; 9], ) { - let mut com: [jdouble; 3] = [0.0, 0.0, 0.0]; - env.get_double_array_region(center_of_mass, 0, &mut com) - .unwrap(); - - let mut inertia_arr: [jdouble; 9] = [0.0; 9]; - env.get_double_array_region(inertia, 0, &mut inertia_arr) - .unwrap(); - let inertia_tensor = Matrix3::new( inertia_arr[0] as Real, inertia_arr[1] as Real, @@ -1078,12 +983,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set } /// Teleports the object to the given position. -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_teleportObject< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn teleport_object( scene_id: jint, id: jint, x: jdouble, @@ -1104,26 +1004,13 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_tel } /// Wakes up an object. -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_wakeUpObject< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, -) { +pub fn wake_up_object(scene_id: jint, id: jint) { let scene = get_scene_mut_ref(scene_id); let rb = &mut scene.rigid_body_set[scene.rigid_bodies[&(id as LevelColliderID)]]; rb.wake_up(true); } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addLinearAngularVelocities< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn add_linear_velocities( scene_id: jint, id: jint, linear_x: jdouble, @@ -1157,14 +1044,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add /// /// A collision is formatted as follows: /// [body_a, body_b, force_amount, local_normal_a, local_normal_b, local_point_a, local_point_b] -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_clearCollisions< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, -) -> JDoubleArray<'local> { +pub fn clear_collisions(scene_id: jint) -> Vec { let scene = get_scene_mut_ref(scene_id); let max_collisions = 100; @@ -1201,21 +1081,12 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_cle arr.push(collision.local_point_b.y as jdouble); arr.push(collision.local_point_b.z as jdouble); } - - let double_array = _env.new_double_array(arr.len() as jint).unwrap(); - _env.set_double_array_region(&double_array, 0, &arr) - .unwrap(); - scene.reported_collisions.clear(); - - double_array + arr } /// Applies a force to a body -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_applyForce<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn apply_force( scene_id: jint, id: jint, x: jdouble, @@ -1257,12 +1128,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_app } /// Applies a force and torque -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_applyForceAndTorque< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn apply_force_and_torque( scene_id: jint, id: jint, fx: jdouble, @@ -1302,16 +1168,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_app } /// Gets the linear velocity of a body -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getLinearVelocity< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, - store: JDoubleArray<'local>, -) { +pub fn get_linear_velocity(scene_id: jint, id: jint) -> [jdouble; 3] { unsafe { let Some(state) = &mut PHYSICS_STATE else { panic!("No physics state!"); @@ -1325,27 +1182,12 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_get let rb = &scene.rigid_body_set[*body]; let vel = rb.linvel(); - - _env.set_double_array_region( - &store, - 0, - &[vel.x as jdouble, vel.y as jdouble, vel.z as jdouble], - ) - .unwrap(); + vel.as_dvec3().to_array() } } /// Gets the angular velocity of a body -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_getAngularVelocity< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jint, - store: JDoubleArray<'local>, -) { +pub fn get_angular_velocity(scene_id: jint, id: jint) -> [jdouble; 3] { unsafe { let Some(state) = &mut PHYSICS_STATE else { panic!("No physics state!"); @@ -1359,12 +1201,6 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_get let rb = &scene.rigid_body_set[*body]; let vel = rb.angvel(); - - _env.set_double_array_region( - &store, - 0, - &[vel.x as jdouble, vel.y as jdouble, vel.z as jdouble], - ) - .unwrap(); + vel.as_dvec3().to_array() } } diff --git a/common/src/main/rust/rapier/src/rope.rs b/common/src/main/rust/rapier/src/rope.rs index f2758e2..3ecad63 100644 --- a/common/src/main/rust/rapier/src/rope.rs +++ b/common/src/main/rust/rapier/src/rope.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; -use jni::JNIEnv; -use jni::objects::{JClass, JDoubleArray}; -use jni::sys::{jboolean, jdouble, jint, jlong, jsize}; +use jni::sys::{jboolean, jdouble, jint, jlong}; use marten::Real; use rapier3d::dynamics::{GenericJointBuilder, JointAxis, RigidBodyBuilder, SpringCoefficients}; use rapier3d::geometry::{ColliderBuilder, SharedShape}; @@ -95,20 +93,13 @@ pub fn tick(scene_id: jint) { } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_createRope<'local>( - env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn create_rope( scene_id: jint, point_radius: jdouble, first_joint_length: jdouble, - points: JDoubleArray<'local>, + coordinates: Vec, num_points: jint, ) -> jlong { - let mut coordinates = vec![0.0; (num_points * 3) as usize]; - env.get_double_array_region(points, 0, &mut coordinates) - .unwrap(); - let scene = get_scene_mut_ref(scene_id); let mut vec = Vec::with_capacity(num_points as usize); @@ -231,43 +222,23 @@ fn create_rope_body(scene_id: i32, coordinate: Vector, point_radius: Real) -> Ri handle } -/// Removes a rope -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_queryRope<'local>( - env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jlong, -) -> JDoubleArray<'local> { +pub fn query_rope(scene_id: jint, id: jlong) -> Vec { let scene = get_scene_mut_ref(scene_id); let strand = scene.rope_map.ropes.get(&(id as usize)).unwrap(); - let flattened: Vec = strand + strand .points .iter() .flat_map(|x| { let pos = scene.rigid_body_set.get(*x).unwrap().position().translation; vec![pos.x as f64, pos.y as f64, pos.z as f64] }) - .collect(); - - let double_array = env - .new_double_array((strand.points.len() * 3) as jsize) - .unwrap(); - env.set_double_array_region(&double_array, 0, &flattened) - .unwrap(); - double_array + .collect() } /// Removes a rope -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeRope<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jlong, -) { +pub fn remove_rope(scene_id: jint, id: jlong) { let scene = get_scene_mut_ref(scene_id); let strand = scene.rope_map.ropes.remove(&(id as usize)).unwrap(); @@ -284,16 +255,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_rem } /// Sets the joint -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setRopeFirstSegmentLength< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jlong, - length: jdouble, -) { +pub fn set_rope_first_segment_length(scene_id: jint, id: jlong, length: jdouble) { let scene = get_scene_mut_ref(scene_id); let strand = scene.rope_map.ropes.get_mut(&(id as usize)).unwrap(); @@ -313,15 +275,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_set ); } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_removeRopePointAtStart< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jlong, -) { +pub fn remove_rope_point_at_start(scene_id: jint, id: jlong) { let scene = get_scene_mut_ref(scene_id); let strand = scene.rope_map.ropes.get_mut(&(id as usize)).unwrap(); @@ -357,18 +311,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_rem } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addRopePointAtStart< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - id: jlong, - x: jdouble, - y: jdouble, - z: jdouble, -) { +pub fn add_rope_point_at_start(scene_id: jint, id: jlong, x: jdouble, y: jdouble, z: jdouble) { let scene = get_scene_mut_ref(scene_id); let strand = scene.rope_map.ropes.get_mut(&(id as usize)).unwrap(); @@ -407,13 +350,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_wakeUpRope<'local>( - _env: JNIEnv<'local>, - _class: JClass<'local>, - scene_id: jint, - rope_id: jlong, -) { +pub fn wake_up_rope(scene_id: jint, rope_id: jlong) { let scene = get_scene_mut_ref(scene_id); let strand = scene.rope_map.ropes.get_mut(&(rope_id as usize)).unwrap(); @@ -424,12 +361,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_wak } /// Sets the attachment at a given end -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_setRopeAttachment< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, +pub fn set_rope_attachment( scene_id: jint, rope_id: jlong, sub_level_id: jint, diff --git a/common/src/main/rust/rapier/src/voxel_collider.rs b/common/src/main/rust/rapier/src/voxel_collider.rs index 2badf7f..740bcae 100644 --- a/common/src/main/rust/rapier/src/voxel_collider.rs +++ b/common/src/main/rust/rapier/src/voxel_collider.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; -use jni::JNIEnv; -use jni::objects::{JClass, JDoubleArray, JObject}; +use jni::objects::GlobalRef; use jni::sys::{jboolean, jdouble, jint}; use marten::Real; use marten::level::{SableMethodID, VoxelColliderData}; @@ -41,45 +40,18 @@ impl VoxelColliderMap { } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_newVoxelCollider< - 'local, ->( - mut env: JNIEnv<'static>, - _class: JClass<'local>, +pub fn new_voxel_collider( friction: jdouble, volume: jdouble, restitution: jdouble, is_fluid: jboolean, - contact_events: JObject, dynamic: jboolean, + global_ref: Option, + global_method: Option, ) -> jint { let state = unsafe { get_physics_state_mut() }; let next_index = state.voxel_collider_map.voxel_colliders.len(); - - let global_ref = if contact_events.is_null() { - None - } else { - Some(env.new_global_ref(contact_events).unwrap()) - }; - - let global_method = if let Some(global_ref_value) = &global_ref { - let class = env.get_object_class(global_ref_value).unwrap(); - - let id = SableMethodID( - env.get_method_id( - class, - String::from("onCollision"), - String::from("(IIIDDDD)[D"), - ) - .unwrap(), - ); - Some(id) - } else { - None - }; - state .voxel_collider_map .voxel_colliders @@ -97,21 +69,8 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_new next_index as jint } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_addVoxelColliderBox< - 'local, ->( - env: JNIEnv<'local>, - _class: JClass<'local>, - index: jint, - box_bounds: JDoubleArray<'local>, -) { +pub fn add_voxel_collider_box(index: jint, bounds: [jdouble; 6]) { let state = unsafe { get_physics_state_mut() }; - - let mut bounds: [jdouble; 6] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; - env.get_double_array_region(box_bounds, 0, &mut bounds) - .unwrap(); - if let Some(data) = &mut state.voxel_collider_map.voxel_colliders[index as usize] { data.collision_boxes.push(( bounds[0] as f32, @@ -124,14 +83,7 @@ pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_add } } -#[unsafe(no_mangle)] -pub extern "system" fn Java_dev_ryanhcode_sable_physics_impl_rapier_Rapier3D_clearVoxelColliderBoxes< - 'local, ->( - _env: JNIEnv<'local>, - _class: JClass<'local>, - index: jint, -) { +pub fn clear_voxel_collider_boxes(index: jint) { let state = unsafe { get_physics_state_mut() }; if let Some(data) = &mut state.voxel_collider_map.voxel_colliders[index as usize] {