tirbofish/dropbear · diff
fix: implemented rotation for KCC Unverified
@@ -35,7 +35,7 @@ glam = { version = "0.30", features = ["serde", "mint"] } hecs = { version = "0.11", features = ["serde"] } log = "0.4" log-once = "0.4" -model_to_image = "0.1" +#model_to_image = "0.1" once_cell = "1.21" parking_lot = {version = "0.12", features = ["deadlock_detection"] } rfd = "0.17" @@ -40,6 +40,7 @@ pub mod jni { use jni::objects::{JClass, JObject}; use jni::sys::{jboolean, jdouble, jlong}; use rapier3d::dynamics::RigidBodyType; + use rapier3d::math::Rotation; use rapier3d::prelude::QueryFilter; use crate::{convert_jlong_to_entity, convert_ptr}; use crate::physics::kcc::KCC; @@ -155,6 +156,72 @@ pub mod jni { } #[unsafe(no_mangle)] + pub extern "system" fn Java_com_dropbear_physics_KinematicCharacterControllerNative_setRotation( + mut env: JNIEnv, + _: JClass, + world_handle: jlong, + physics_handle: jlong, + entity: jlong, + rotation: JObject, + ) { + let world = convert_ptr!(world_handle => World); + let physics_state = convert_ptr!(mut physics_handle => PhysicsState); + let entity = convert_jlong_to_entity!(entity); + + let class = match env.find_class("com/dropbear/math/Quaterniond") { + Ok(cls) => cls, + Err(_) => { + let _ = env.throw_new("java/lang/RuntimeException", "Unable to find Quaterniond class"); + return; + } + }; + + if let Ok(false) = env.is_instance_of(&rotation, &class) { + let _ = env.throw_new("java/lang/IllegalArgumentException", "rotation must be Quaterniond"); + return; + } + + let mut get_double = |field: &str| -> Option<f64> { + env.get_field(&rotation, field, "D").ok()?.d().ok() + }; + + let Some(rx) = get_double("x") else { return; }; + let Some(ry) = get_double("y") else { return; }; + let Some(rz) = get_double("z") else { return; }; + let Some(rw) = get_double("w") else { return; }; + + let len = (rx * rx + ry * ry + rz * rz + rw * rw).sqrt(); + let (x, y, z, w) = if len > 0.0 { + (rx / len, ry / len, rz / len, rw / len) + } else { + (0.0, 0.0, 0.0, 1.0) + }; + + if let Ok((label, _kcc)) = world.query_one::<(&Label, &KCC)>(entity).get() { + let Some(rigid_body_handle) = physics_state.bodies_entity_map.get(label) else { + return; + }; + + let body_type = { + let Some(body) = physics_state.bodies.get(*rigid_body_handle) else { + return; + }; + body.body_type() + }; + + match body_type { + RigidBodyType::KinematicPositionBased => {} + _ => return, + } + + if let Some(body) = physics_state.bodies.get_mut(*rigid_body_handle) { + let rot = Rotation::from_xyzw(x as f32, y as f32, z as f32, w as f32); + body.set_next_kinematic_rotation(rot); + } + } + } + + #[unsafe(no_mangle)] pub extern "system" fn Java_com_dropbear_physics_KinematicCharacterControllerNative_getHitNative( mut env: JNIEnv, _: JClass, @@ -28,7 +28,7 @@ glam.workspace = true hecs.workspace = true log.workspace = true log-once.workspace = true -model_to_image.workspace = true +#model_to_image.workspace = true parking_lot.workspace = true transform-gizmo-egui.workspace = true wgpu.workspace = true @@ -3,6 +3,7 @@ package com.dropbear.physics import com.dropbear.EntityId import com.dropbear.ecs.Component import com.dropbear.ecs.ComponentType +import com.dropbear.math.Quaterniond import com.dropbear.math.Vector3d import com.dropbear.math.degreesToRadians import kotlin.math.cos @@ -28,6 +29,16 @@ class KinematicCharacterController( } /** + * Sets the kinematic rotation for this tick. + * + * This is useful for facing the character toward the camera direction while still + * using KCC movement. + */ + fun setRotation(rotation: Quaterniond) { + setRotationNative(rotation) + } + + /** * This function fetches the hits that are cached in the `KCC` struct. * * # Note @@ -62,4 +73,5 @@ class KinematicCharacterController( internal expect fun kccExistsForEntity(entityId: EntityId): Boolean internal expect fun KinematicCharacterController.moveCharacter(dt: Double, translation: Vector3d) +internal expect fun KinematicCharacterController.setRotationNative(rotation: Quaterniond) internal expect fun KinematicCharacterController.getHitsNative(): List<CharacterCollision> @@ -2,6 +2,7 @@ package com.dropbear.physics; import com.dropbear.EucalyptusCoreLoader; import com.dropbear.math.Vector3d; +import com.dropbear.math.Quaterniond; // fuck, this got a long ass name public class KinematicCharacterControllerNative { @@ -12,5 +13,6 @@ public class KinematicCharacterControllerNative { public static native boolean existsForEntity(long worldHandle, long entityHandle); public static native void moveCharacter(long worldHandle, long physicsHandle, long entityHandle, Vector3d translation, double deltaTime); + public static native void setRotation(long worldHandle, long physicsHandle, long entityHandle, Quaterniond rotation); public static native CharacterCollision[] getHitNative(long worldHandle, long entity); } @@ -18,6 +18,15 @@ internal actual fun KinematicCharacterController.moveCharacter(dt: Double, trans ) } +internal actual fun KinematicCharacterController.setRotationNative(rotation: com.dropbear.math.Quaterniond) { + return KinematicCharacterControllerNative.setRotation( + DropbearEngine.native.worldHandle, + DropbearEngine.native.physicsEngineHandle, + entity.raw, + rotation + ) +} + internal actual fun KinematicCharacterController.getHitsNative(): List<CharacterCollision> { return KinematicCharacterControllerNative.getHitNative( DropbearEngine.native.worldHandle, @@ -1,11 +1,16 @@ package com.dropbear.physics import com.dropbear.EntityId +import com.dropbear.math.Quaterniond import com.dropbear.math.Vector3d internal actual fun KinematicCharacterController.moveCharacter(dt: Double, translation: Vector3d) { } +internal actual fun KinematicCharacterController.setRotationNative(rotation: Quaterniond) { + TODO("Not yet implemented") +} + internal actual fun kccExistsForEntity(entityId: EntityId): Boolean { TODO("Not yet implemented") }