forked from LeenkxTeam/LNXSDK
123 lines
3.4 KiB
Haxe
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
|