Files
LNXSDK/leenkx/Sources/leenkx/trait/physics/jolt/PhysicsHook.hx
2026-02-24 21:30:00 -08:00

123 lines
3.4 KiB
Haxe

package leenkx.trait.physics.jolt;
#if lnx_jolt
import iron.math.Vec4;
import iron.math.Mat4;
import iron.math.Quat;
import iron.Trait;
import iron.object.Object;
import iron.object.MeshObject;
import iron.object.Transform;
import iron.data.MeshData;
import iron.data.SceneFormat;
class PhysicsHook extends Trait {
var target:Object;
var targetName:String;
var targetTransform:Transform;
var verts:Array<Float>;
var hookBodyId:jolt.Jt.BodyID = null;
var constraintId:Int = -1;
static var nullvec = true;
static var vec1:jolt.Jt.Vec3;
static var quat1:jolt.Jt.Quat;
static var quat = new Quat();
public function new(targetName:String, verts:Array<Float>) {
super();
this.targetName = targetName;
this.verts = verts;
iron.Scene.active.notifyOnInit(function() {
notifyOnInit(init);
notifyOnUpdate(update);
});
}
function init() {
if (nullvec) {
nullvec = false;
vec1 = new jolt.Jt.Vec3(0, 0, 0);
quat1 = new jolt.Jt.Quat(0, 0, 0, 1);
}
target = targetName != "" ? iron.Scene.active.getChild(targetName) : null;
targetTransform = target != null ? target.transform : iron.Scene.global.transform;
var physics = PhysicsWorld.active;
if (physics == null)
return;
#if lnx_physics_soft
var sb:SoftBody = object.getTrait(SoftBody);
if (sb != null && sb.ready) {
// For soft body hooks, pin vertices near the target
var numVerts = Std.int(verts.length / 3);
for (j in 0...numVerts) {
var x = verts[j * 3] + sb.vertOffsetX + sb.object.transform.loc.x;
var y = verts[j * 3 + 1] + sb.vertOffsetY + sb.object.transform.loc.y;
var z = verts[j * 3 + 2] + sb.vertOffsetZ + sb.object.transform.loc.z;
// Find and pin matching vertices
for (i in 0...@:privateAccess sb.particles.length) {
var p = @:privateAccess sb.particles[i];
if (Math.abs(p.position.x - x) < 0.01 && Math.abs(p.position.y - y) < 0.01 && Math.abs(p.position.z - z) < 0.01) {
sb.pinVertex(i);
}
}
}
return;
}
#end
// Rigid body hook using fixed constraint
var rb1:RigidBody = object.getTrait(RigidBody);
if (rb1 != null && rb1.ready) {
var settings = new jolt.Jt.FixedConstraintSettings();
settings.mAutoDetectPoint = true;
var constraint = settings.Create(rb1.body, rb1.body);
physics.physicsSystem.AddConstraint(constraint);
return;
}
// Rigid body or soft body not initialized yet
notifyOnInit(init);
}
function update() {
#if lnx_physics_soft
// Soft body hook - update pinned vertex positions to follow target
var sb:SoftBody = object.getTrait(SoftBody);
if (sb != null && sb.ready) {
var numVerts = Std.int(verts.length / 3);
for (j in 0...numVerts) {
var x = verts[j * 3] + sb.vertOffsetX + sb.object.transform.loc.x;
var y = verts[j * 3 + 1] + sb.vertOffsetY + sb.object.transform.loc.y;
var z = verts[j * 3 + 2] + sb.vertOffsetZ + sb.object.transform.loc.z;
// Update pinned vertex positions to target
for (i in 0...@:privateAccess sb.particles.length) {
var p = @:privateAccess sb.particles[i];
if (p.pinned) {
// Move pinned vertex with target
var dx = targetTransform.worldx() - targetTransform.loc.x;
var dy = targetTransform.worldy() - targetTransform.loc.y;
var dz = targetTransform.worldz() - targetTransform.loc.z;
p.position.x = x + dx;
p.position.y = y + dy;
p.position.z = z + dz;
}
}
}
}
#end
}
}
#end