armory/Sources/armory/trait/physics/bullet/RigidBody.hx

606 lines
17 KiB
Haxe
Raw Normal View History

2017-09-30 00:32:06 +02:00
package armory.trait.physics.bullet;
2015-11-26 22:30:19 +01:00
2017-09-30 02:15:21 +02:00
#if arm_bullet
2016-07-10 00:51:39 +02:00
import iron.math.Vec4;
2018-08-28 13:50:52 +02:00
import iron.math.Quat;
2016-08-25 00:26:01 +02:00
import iron.object.Transform;
import iron.object.MeshObject;
2019-01-07 15:41:06 +01:00
import iron.data.MeshData;
2015-11-26 22:30:19 +01:00
2018-08-23 20:26:40 +02:00
/**
* RigidBody is used to allow objects to interact with Physics in your game including collisions and gravity.
* RigidBody can also be used with the getContacts method to detect collisions and run appropriate code.
* The Bullet physics engine is used for these calculations.
*/
2018-08-17 17:01:54 +02:00
@:access(armory.trait.physics.bullet.PhysicsWorld)
2018-07-24 21:28:03 +02:00
class RigidBody extends iron.Trait {
2015-11-26 22:30:19 +01:00
2016-07-19 19:42:46 +02:00
var shape:Shape;
2015-11-26 22:30:19 +01:00
public var physics:PhysicsWorld;
2016-10-09 16:06:18 +02:00
public var transform:Transform = null;
2015-11-26 22:30:19 +01:00
public var mass:Float;
public var friction:Float;
2017-05-14 11:59:12 +02:00
public var restitution:Float;
2016-05-06 23:46:04 +02:00
public var collisionMargin:Float;
2016-12-08 14:30:39 +01:00
public var linearDamping:Float;
public var angularDamping:Float;
2017-11-13 10:18:37 +01:00
public var animated:Bool;
public var staticObj:Bool;
2018-08-27 07:35:39 +02:00
public var destroyed = false;
2017-11-06 13:01:08 +01:00
var linearFactors:Array<Float>;
var angularFactors:Array<Float>;
var deactivationParams:Array<Float>;
2018-10-30 12:56:49 +01:00
var ccd = false; // Continuous collision detection
2017-10-29 19:34:10 +01:00
public var group = 1;
2019-09-05 22:21:31 +02:00
public var mask = 1;
2019-01-14 11:27:03 +01:00
var trigger = false;
2017-12-12 13:39:15 +01:00
var bodyScaleX:Float; // Transform scale at creation time
var bodyScaleY:Float;
var bodyScaleZ:Float;
var currentScaleX:Float;
var currentScaleY:Float;
var currentScaleZ:Float;
2015-11-26 22:30:19 +01:00
2018-12-20 18:04:49 +01:00
public var body:bullet.Bt.RigidBody = null;
public var motionState:bullet.Bt.MotionState;
public var btshape:bullet.Bt.CollisionShape;
2016-12-07 02:01:42 +01:00
public var ready = false;
2015-11-26 22:30:19 +01:00
static var nextId = 0;
public var id = 0;
2016-10-02 19:52:40 +02:00
public var onReady:Void->Void = null;
2018-08-17 10:20:46 +02:00
public var onContact:Array<RigidBody->Void> = null;
2019-01-17 21:34:38 +01:00
public var heightData:haxe.io.Bytes = null;
#if js
static var ammoArray:Int = -1;
#end
2015-11-26 22:30:19 +01:00
2018-08-23 20:26:40 +02:00
static var nullvec = true;
2018-12-20 18:04:49 +01:00
static var vec1:bullet.Bt.Vector3;
static var vec2:bullet.Bt.Vector3;
static var vec3:bullet.Bt.Vector3;
static var quat1:bullet.Bt.Quaternion;
static var trans1:bullet.Bt.Transform;
static var trans2:bullet.Bt.Transform;
2018-08-28 13:50:52 +02:00
static var quat = new Quat();
2018-08-23 20:26:40 +02:00
static var CF_STATIC_OBJECT= 1;
static var CF_KINEMATIC_OBJECT= 2;
static var CF_NO_CONTACT_RESPONSE = 4;
static var CF_CHARACTER_OBJECT = 16;
2019-01-07 15:41:06 +01:00
static var convexHullCache = new Map<MeshData, bullet.Bt.ConvexHullShape>();
static var triangleMeshCache = new Map<MeshData, bullet.Bt.TriangleMesh>();
static var usersCache = new Map<MeshData, Int>();
2019-09-05 22:21:31 +02:00
public function new(shape = Shape.Box, mass = 1.0, friction = 0.5, restitution = 0.0, group = 1, mask=1,
2018-12-31 16:55:46 +01:00
params:Array<Float> = null, flags:Array<Bool> = null) {
2015-11-26 22:30:19 +01:00
super();
2018-08-23 20:26:40 +02:00
if (nullvec) {
nullvec = false;
2018-12-20 18:04:49 +01:00
vec1 = new bullet.Bt.Vector3(0, 0, 0);
vec2 = new bullet.Bt.Vector3(0, 0, 0);
vec3 = new bullet.Bt.Vector3(0, 0, 0);
quat1 = new bullet.Bt.Quaternion(0, 0, 0, 0);
trans1 = new bullet.Bt.Transform();
trans2 = new bullet.Bt.Transform();
2018-08-23 20:26:40 +02:00
}
2015-11-26 22:30:19 +01:00
this.shape = shape;
2018-12-20 18:04:49 +01:00
this.mass = mass;
2015-11-26 22:30:19 +01:00
this.friction = friction;
2017-05-14 11:59:12 +02:00
this.restitution = restitution;
2017-10-29 19:34:10 +01:00
this.group = group;
2019-09-05 22:21:31 +02:00
this.mask = mask;
2018-12-20 18:04:49 +01:00
if (params == null) params = [0.04, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0];
if (flags == null) flags = [false, false, false];
this.linearDamping = params[0];
this.angularDamping = params[1];
this.linearFactors = [params[2], params[3], params[4]];
this.angularFactors = [params[5], params[6], params[7]];
this.collisionMargin = params[8];
this.deactivationParams = [params[9], params[10], params[11]];
this.animated = flags[0];
this.trigger = flags[1];
this.ccd = flags[2];
this.staticObj = flags[3];
2017-04-16 14:46:35 +02:00
notifyOnAdd(init);
2015-11-26 22:30:19 +01:00
}
2018-12-20 18:04:49 +01:00
2016-05-06 23:46:04 +02:00
inline function withMargin(f:Float) {
return f - f * collisionMargin;
}
2015-11-26 22:30:19 +01:00
2016-10-02 19:52:40 +02:00
public function notifyOnReady(f:Void->Void) {
onReady = f;
2017-04-20 11:13:33 +02:00
if (ready) onReady();
2016-10-02 19:52:40 +02:00
}
2015-11-26 22:30:19 +01:00
public function init() {
2016-12-07 02:01:42 +01:00
if (ready) return;
ready = true;
2018-02-04 22:57:12 +01:00
if (!Std.is(object, MeshObject)) return; // No mesh data
2017-04-02 13:13:43 +02:00
transform = object.transform;
2017-09-30 00:32:06 +02:00
physics = armory.trait.physics.PhysicsWorld.active;
2017-04-02 13:13:43 +02:00
2016-07-19 19:42:46 +02:00
if (shape == Shape.Box) {
2018-08-23 20:26:40 +02:00
vec1.setX(withMargin(transform.dim.x / 2));
vec1.setY(withMargin(transform.dim.y / 2));
vec1.setZ(withMargin(transform.dim.z / 2));
2018-12-20 18:04:49 +01:00
btshape = new bullet.Bt.BoxShape(vec1);
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Sphere) {
2018-12-20 18:04:49 +01:00
btshape = new bullet.Bt.SphereShape(withMargin(transform.dim.x / 2));
2015-11-26 22:30:19 +01:00
}
2018-08-17 17:01:54 +02:00
else if (shape == Shape.ConvexHull) {
2019-01-07 15:41:06 +01:00
var shapeConvex = fillConvexHull(transform.scale, collisionMargin);
2018-08-23 20:26:40 +02:00
btshape = shapeConvex;
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Cone) {
2018-12-20 18:04:49 +01:00
var coneZ = new bullet.Bt.ConeShapeZ(
withMargin(transform.dim.x / 2), // Radius
withMargin(transform.dim.z)); // Height
2018-12-20 18:04:49 +01:00
var cone:bullet.Bt.ConeShape = coneZ;
btshape = cone;
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Cylinder) {
2018-08-23 20:26:40 +02:00
vec1.setX(withMargin(transform.dim.x / 2));
vec1.setY(withMargin(transform.dim.y / 2));
vec1.setZ(withMargin(transform.dim.z / 2));
2018-12-20 18:04:49 +01:00
var cylZ = new bullet.Bt.CylinderShapeZ(vec1);
var cyl:bullet.Bt.CylinderShape = cylZ;
btshape = cyl;
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Capsule) {
var r = transform.dim.x / 2;
2018-12-20 18:04:49 +01:00
var capsZ = new bullet.Bt.CapsuleShapeZ(
2016-12-08 14:30:39 +01:00
withMargin(r), // Radius
withMargin(transform.dim.z - r * 2)); // Height between 2 sphere centers
2018-12-20 18:04:49 +01:00
var caps:bullet.Bt.CapsuleShape = capsZ;
btshape = caps;
2015-11-26 22:30:19 +01:00
}
2019-01-17 21:34:38 +01:00
else if (shape == Shape.Mesh) {
2019-01-07 15:41:06 +01:00
var meshInterface = fillTriangleMesh(transform.scale);
2018-08-17 17:01:54 +02:00
if (mass > 0) {
2018-12-20 18:04:49 +01:00
var shapeGImpact = new bullet.Bt.GImpactMeshShape(meshInterface);
2018-08-23 20:26:40 +02:00
shapeGImpact.updateBound();
2018-12-20 18:04:49 +01:00
var shapeConcave:bullet.Bt.ConcaveShape = shapeGImpact;
btshape = shapeConcave;
2018-08-17 17:01:54 +02:00
if (!physics.gimpactRegistered) {
2018-08-21 13:08:19 +02:00
#if js
2018-12-20 18:04:49 +01:00
new bullet.Bt.GImpactCollisionAlgorithm().registerAlgorithm(physics.dispatcher);
2018-08-21 13:08:19 +02:00
#else
2018-12-20 18:04:49 +01:00
shapeGImpact.registerAlgorithm(physics.dispatcher);
2018-08-21 13:08:19 +02:00
#end
2018-08-17 17:01:54 +02:00
physics.gimpactRegistered = true;
}
}
else {
2018-12-20 18:04:49 +01:00
var shapeBvh = new bullet.Bt.BvhTriangleMeshShape(meshInterface, true, true);
var shapeTri:bullet.Bt.TriangleMeshShape = shapeBvh;
var shapeConcave:bullet.Bt.ConcaveShape = shapeTri;
btshape = shapeConcave;
2018-08-17 17:01:54 +02:00
}
2015-11-26 22:30:19 +01:00
}
2019-01-17 21:34:38 +01:00
else if (shape == Shape.Terrain) {
#if js
var length = heightData.length;
if (ammoArray == -1) {
ammoArray = bullet.Bt.Ammo._malloc(length);
}
// From texture bytes
for (i in 0...length) {
bullet.Bt.Ammo.HEAPU8[ammoArray + i] = heightData.get(i);
}
var slice = Std.int(Math.sqrt(length)); // Assuming square terrain data
var axis = 2; // z
var dataType = 5; // u8
btshape = new bullet.Bt.HeightfieldTerrainShape(slice, slice, ammoArray, 1 / 255, 0, 1, axis, dataType, false);
vec1.setX(transform.dim.x / slice);
vec1.setY(transform.dim.y / slice);
vec1.setZ(transform.dim.z);
btshape.setLocalScaling(vec1);
#end
}
2015-11-26 22:30:19 +01:00
2018-08-23 20:26:40 +02:00
trans1.setIdentity();
vec1.setX(transform.worldx());
vec1.setY(transform.worldy());
vec1.setZ(transform.worldz());
trans1.setOrigin(vec1);
2018-08-28 13:50:52 +02:00
quat.fromMat(transform.world);
2018-12-20 18:04:49 +01:00
quat1.setValue(quat.x, quat.y, quat.z, quat.w);
2018-08-23 20:26:40 +02:00
trans1.setRotation(quat1);
var centerOfMassOffset = trans2;
centerOfMassOffset.setIdentity();
2018-12-20 18:04:49 +01:00
motionState = new bullet.Bt.DefaultMotionState(trans1, centerOfMassOffset);
2018-08-23 20:26:40 +02:00
vec1.setX(0);
vec1.setY(0);
vec1.setZ(0);
var inertia = vec1;
if(staticObj || animated) mass = 0;
2018-08-23 20:26:40 +02:00
if (mass > 0) btshape.calculateLocalInertia(mass, inertia);
2018-12-20 18:04:49 +01:00
var bodyCI = new bullet.Bt.RigidBodyConstructionInfo(mass, motionState, btshape, inertia);
body = new bullet.Bt.RigidBody(bodyCI);
var bodyColl:bullet.Bt.CollisionObject = body;
bodyColl.setFriction(friction);
2018-11-12 10:44:15 +01:00
// body.setRollingFriction(friction); // This causes bodies to get stuck, apply angular damping instead
if (shape == Shape.Sphere || shape == Shape.Cylinder || shape == Shape.Cone || shape == Shape.Capsule) {
angularDamping += friction;
}
2018-12-20 18:04:49 +01:00
bodyColl.setRestitution(restitution);
2015-11-26 22:30:19 +01:00
2017-11-06 13:01:08 +01:00
if (deactivationParams != null) {
setDeactivationParams(deactivationParams[0], deactivationParams[1], deactivationParams[2]);
}
else {
setActivationState(ActivationState.NoDeactivation);
}
2015-11-26 22:30:19 +01:00
2016-12-08 14:30:39 +01:00
if (linearDamping != 0.04 || angularDamping != 0.1) {
2017-02-26 15:09:36 +01:00
body.setDamping(linearDamping, angularDamping);
2016-12-08 14:30:39 +01:00
}
2017-11-06 13:01:08 +01:00
if (linearFactors != null) {
setLinearFactor(linearFactors[0], linearFactors[1], linearFactors[2]);
}
2017-11-06 13:01:08 +01:00
if (angularFactors != null) {
setAngularFactor(angularFactors[0], angularFactors[1], angularFactors[2]);
}
if (trigger) bodyColl.setCollisionFlags(bodyColl.getCollisionFlags() | CF_NO_CONTACT_RESPONSE);
if (animated){
bodyColl.setCollisionFlags(bodyColl.getCollisionFlags() | CF_KINEMATIC_OBJECT);
bodyColl.setCollisionFlags(bodyColl.getCollisionFlags() & ~CF_STATIC_OBJECT);
}
if (staticObj && !animated) bodyColl.setCollisionFlags(bodyColl.getCollisionFlags() | CF_STATIC_OBJECT);
2017-11-02 13:32:21 +01:00
2018-10-30 12:56:49 +01:00
if (ccd) setCcd(transform.radius);
2017-12-12 13:39:15 +01:00
bodyScaleX = currentScaleX = transform.scale.x;
bodyScaleY = currentScaleY = transform.scale.y;
bodyScaleZ = currentScaleZ = transform.scale.z;
2017-11-06 13:01:08 +01:00
id = nextId;
nextId++;
2015-11-26 22:30:19 +01:00
#if js
//body.setUserIndex(nextId);
untyped body.userIndex = id;
2018-12-20 18:04:49 +01:00
#else
bodyColl.setUserIndex(id);
2015-11-26 22:30:19 +01:00
#end
physics.addRigidBody(this);
2018-09-13 14:49:34 +02:00
notifyOnRemove(removeFromWorld);
2015-11-26 22:30:19 +01:00
2016-10-02 19:52:40 +02:00
if (onReady != null) onReady();
2018-08-23 20:26:40 +02:00
#if js
2018-12-20 18:04:49 +01:00
bullet.Bt.Ammo.destroy(bodyCI);
#else
bodyCI.delete();
2018-08-23 20:26:40 +02:00
#end
2015-11-26 22:30:19 +01:00
}
2018-09-13 14:49:34 +02:00
function physicsUpdate() {
2016-12-07 02:01:42 +01:00
if (!ready) return;
if (animated) {
2016-10-09 16:06:18 +02:00
syncTransform();
}
else {
2018-12-20 18:04:49 +01:00
var bodyColl:bullet.Bt.CollisionObject = body;
var trans = bodyColl.getWorldTransform();
2016-10-09 16:06:18 +02:00
var p = trans.getOrigin();
var q = trans.getRotation();
2018-12-20 18:04:49 +01:00
var qw:bullet.Bt.QuadWord = q;
2016-10-09 16:06:18 +02:00
transform.loc.set(p.x(), p.y(), p.z());
2018-12-20 18:04:49 +01:00
transform.rot.set(qw.x(), qw.y(), qw.z(), qw.w());
2017-08-23 00:53:26 +02:00
if (object.parent != null) {
var ptransform = object.parent.transform;
transform.loc.x -= ptransform.worldx();
transform.loc.y -= ptransform.worldy();
transform.loc.z -= ptransform.worldz();
}
2017-03-12 17:29:22 +01:00
transform.buildMatrix();
2016-10-09 16:06:18 +02:00
}
2018-08-17 10:20:46 +02:00
if (onContact != null) {
var rbs = physics.getContacts(this);
if (rbs != null) for (rb in rbs) for (f in onContact) f(rb);
}
2015-11-26 22:30:19 +01:00
}
2016-04-27 10:29:32 +02:00
public function removeFromWorld() {
2016-09-14 11:49:32 +02:00
if (physics != null) physics.removeRigidBody(this);
2015-11-26 22:30:19 +01:00
}
2016-04-27 10:29:32 +02:00
public function activate() {
2018-12-20 18:04:49 +01:00
var bodyColl:bullet.Bt.CollisionObject = body;
bodyColl.activate(false);
2015-11-26 22:30:19 +01:00
}
2016-04-27 10:29:32 +02:00
public function disableGravity() {
2018-12-20 18:04:49 +01:00
vec1.setValue(0, 0, 0);
2018-08-23 20:26:40 +02:00
body.setGravity(vec1);
2015-11-26 22:30:19 +01:00
}
public function enableGravity() {
body.setGravity(physics.world.getGravity());
}
public function setGravity(v:Vec4) {
2018-12-20 18:04:49 +01:00
vec1.setValue(v.x, v.y, v.z);
2018-08-23 20:26:40 +02:00
body.setGravity(vec1);
}
2015-11-26 22:30:19 +01:00
2017-01-19 00:26:18 +01:00
public function setActivationState(newState:Int) {
2018-12-20 18:04:49 +01:00
var bodyColl:bullet.Bt.CollisionObject = body;
bodyColl.setActivationState(newState);
2017-01-19 00:26:18 +01:00
}
2015-11-26 22:30:19 +01:00
2017-11-06 13:01:08 +01:00
public function setDeactivationParams(linearThreshold:Float, angularThreshold:Float, time:Float) {
body.setSleepingThresholds(linearThreshold, angularThreshold);
// body.setDeactivationTime(time); // not available in ammo
}
public function applyForce(force:Vec4, loc:Vec4 = null) {
activate();
2018-12-20 18:04:49 +01:00
vec1.setValue(force.x, force.y, force.z);
if (loc == null) {
2018-08-23 20:26:40 +02:00
body.applyCentralForce(vec1);
}
else {
2018-12-20 18:04:49 +01:00
vec2.setValue(loc.x, loc.y, loc.z);
2018-08-23 20:26:40 +02:00
body.applyForce(vec1, vec2);
}
}
2016-08-25 00:26:01 +02:00
public function applyImpulse(impulse:Vec4, loc:Vec4 = null) {
2017-08-07 10:47:29 +02:00
activate();
2018-12-20 18:04:49 +01:00
vec1.setValue(impulse.x, impulse.y, impulse.z);
2016-08-25 00:26:01 +02:00
if (loc == null) {
2018-08-23 20:26:40 +02:00
body.applyCentralImpulse(vec1);
2015-11-26 22:30:19 +01:00
}
else {
2018-12-20 18:04:49 +01:00
vec2.setValue(loc.x, loc.y, loc.z);
2018-08-23 20:26:40 +02:00
body.applyImpulse(vec1, vec2);
2015-11-26 22:30:19 +01:00
}
}
2018-11-12 21:06:12 +01:00
public function applyTorque(torque:Vec4) {
activate();
2018-12-20 18:04:49 +01:00
vec1.setValue(torque.x, torque.y, torque.z);
2018-11-12 21:06:12 +01:00
body.applyTorque(vec1);
}
public function applyTorqueImpulse(torque:Vec4) {
activate();
2018-12-20 18:04:49 +01:00
vec1.setValue(torque.x, torque.y, torque.z);
2018-11-12 21:06:12 +01:00
body.applyTorqueImpulse(vec1);
}
2016-04-27 10:29:32 +02:00
public function setLinearFactor(x:Float, y:Float, z:Float) {
2018-12-20 18:04:49 +01:00
vec1.setValue(x, y, z);
2018-08-23 20:26:40 +02:00
body.setLinearFactor(vec1);
2015-11-26 22:30:19 +01:00
}
2016-04-27 10:29:32 +02:00
public function setAngularFactor(x:Float, y:Float, z:Float) {
2018-12-20 18:04:49 +01:00
vec1.setValue(x, y, z);
2018-08-23 20:26:40 +02:00
body.setAngularFactor(vec1);
2015-11-26 22:30:19 +01:00
}
public function getLinearVelocity():Vec4 {
var v = body.getLinearVelocity();
return new Vec4(v.x(), v.y(), v.z());
2016-05-05 19:50:03 +02:00
}
2015-11-26 22:30:19 +01:00
2016-04-27 10:29:32 +02:00
public function setLinearVelocity(x:Float, y:Float, z:Float) {
2018-12-20 18:04:49 +01:00
vec1.setValue(x, y, z);
2018-08-23 20:26:40 +02:00
body.setLinearVelocity(vec1);
2015-11-26 22:30:19 +01:00
}
public function getAngularVelocity():Vec4 {
var v = body.getAngularVelocity();
return new Vec4(v.x(), v.y(), v.z());
}
2015-11-26 22:30:19 +01:00
2016-04-27 10:29:32 +02:00
public function setAngularVelocity(x:Float, y:Float, z:Float) {
2018-12-20 18:04:49 +01:00
vec1.setValue(x, y, z);
2018-08-23 20:26:40 +02:00
body.setAngularVelocity(vec1);
2015-11-26 22:30:19 +01:00
}
public function setFriction(f:Float) {
2018-12-20 18:04:49 +01:00
var bodyColl:bullet.Bt.CollisionObject = body;
bodyColl.setFriction(f);
// bodyColl.setRollingFriction(f);
this.friction = f;
}
2018-08-17 10:20:46 +02:00
public function notifyOnContact(f:RigidBody->Void) {
if (onContact == null) onContact = [];
onContact.push(f);
}
public function removeContact(f:RigidBody->Void) {
onContact.remove(f);
}
2018-12-20 18:04:49 +01:00
function setScale(v:Vec4) {
currentScaleX = v.x;
currentScaleY = v.y;
currentScaleZ = v.z;
2019-02-12 12:33:43 +01:00
vec1.setX(v.x / bodyScaleX);
vec1.setY(v.y / bodyScaleY);
vec1.setZ(v.z / bodyScaleZ);
2018-12-20 18:04:49 +01:00
btshape.setLocalScaling(vec1);
var worldDyn:bullet.Bt.DynamicsWorld = physics.world;
var worldCol:bullet.Bt.CollisionWorld = worldDyn;
worldCol.updateSingleAabb(body);
}
2015-11-26 22:30:19 +01:00
public function syncTransform() {
2017-12-12 13:39:15 +01:00
var t = transform;
t.buildMatrix();
2018-12-20 18:04:49 +01:00
vec1.setValue(t.worldx(), t.worldy(), t.worldz());
2018-08-23 20:26:40 +02:00
trans1.setOrigin(vec1);
2018-08-28 13:50:52 +02:00
quat.fromMat(t.world);
2018-12-20 18:04:49 +01:00
quat1.setValue(quat.x, quat.y, quat.z, quat.w);
2018-08-23 20:26:40 +02:00
trans1.setRotation(quat1);
if(animated)
body.getMotionState().setWorldTransform(trans1);
else
body.setCenterOfMassTransform(trans1);
2017-12-12 13:39:15 +01:00
if (currentScaleX != t.scale.x || currentScaleY != t.scale.y || currentScaleZ != t.scale.z) setScale(t.scale);
2017-07-01 13:12:22 +02:00
activate();
2015-11-26 22:30:19 +01:00
}
2018-10-30 12:56:49 +01:00
// Continuous collision detection
public function setCcd(sphereRadius:Float, motionThreshold = 1e-7) {
2018-12-20 18:04:49 +01:00
var bodyColl:bullet.Bt.CollisionObject = body;
bodyColl.setCcdSweptSphereRadius(sphereRadius);
bodyColl.setCcdMotionThreshold(motionThreshold);
2017-12-12 13:39:15 +01:00
}
2019-01-07 15:41:06 +01:00
function fillConvexHull(scale:Vec4, margin:kha.FastFloat):bullet.Bt.ConvexHullShape {
// Check whether shape already exists
2018-12-15 23:10:11 +01:00
var data = cast(object, MeshObject).data;
2019-01-07 15:41:06 +01:00
var shape = convexHullCache.get(data);
if (shape != null) {
usersCache.set(data, usersCache.get(data) + 1);
return shape;
}
shape = new bullet.Bt.ConvexHullShape();
convexHullCache.set(data, shape);
usersCache.set(data, 1);
2018-12-15 23:10:11 +01:00
var positions = data.geom.positions;
2015-11-26 22:30:19 +01:00
2018-12-20 18:04:49 +01:00
var sx:kha.FastFloat = scale.x * (1.0 - margin) * (1 / 32767);
var sy:kha.FastFloat = scale.y * (1.0 - margin) * (1 / 32767);
var sz:kha.FastFloat = scale.z * (1.0 - margin) * (1 / 32767);
2018-12-15 23:10:11 +01:00
if (data.raw.scale_pos != null) {
sx *= data.raw.scale_pos;
sy *= data.raw.scale_pos;
sz *= data.raw.scale_pos;
}
2018-12-14 15:27:43 +01:00
for (i in 0...Std.int(positions.length / 4)) {
2018-12-15 23:10:11 +01:00
vec1.setX(positions[i * 4 ] * sx);
vec1.setY(positions[i * 4 + 1] * sy);
vec1.setZ(positions[i * 4 + 2] * sz);
2018-08-23 20:26:40 +02:00
shape.addPoint(vec1, true);
2015-11-26 22:30:19 +01:00
}
2019-01-07 15:41:06 +01:00
return shape;
2015-11-26 22:30:19 +01:00
}
2019-01-07 15:41:06 +01:00
function fillTriangleMesh(scale:Vec4):bullet.Bt.TriangleMesh {
// Check whether shape already exists
2018-12-15 23:10:11 +01:00
var data = cast(object, MeshObject).data;
2019-01-07 15:41:06 +01:00
var triangleMesh = triangleMeshCache.get(data);
if (triangleMesh != null) {
usersCache.set(data, usersCache.get(data) + 1);
return triangleMesh;
}
triangleMesh = new bullet.Bt.TriangleMesh(true, true);
triangleMeshCache.set(data, triangleMesh);
usersCache.set(data, 1);
2018-12-15 23:10:11 +01:00
var positions = data.geom.positions;
var indices = data.geom.indices;
2015-11-26 22:30:19 +01:00
2018-12-20 18:04:49 +01:00
var sx:kha.FastFloat = scale.x * (1 / 32767);
var sy:kha.FastFloat = scale.y * (1 / 32767);
var sz:kha.FastFloat = scale.z * (1 / 32767);
2018-12-14 15:27:43 +01:00
2018-12-15 23:10:11 +01:00
if (data.raw.scale_pos != null) {
sx *= data.raw.scale_pos;
sy *= data.raw.scale_pos;
sz *= data.raw.scale_pos;
}
2018-01-10 21:10:08 +01:00
for (ar in indices) {
for (i in 0...Std.int(ar.length / 3)) {
2019-01-07 15:41:06 +01:00
vec1.setX(positions[ar[i * 3 ] * 4 ] * sx);
vec1.setY(positions[ar[i * 3 ] * 4 + 1] * sy);
vec1.setZ(positions[ar[i * 3 ] * 4 + 2] * sz);
vec2.setX(positions[ar[i * 3 + 1] * 4 ] * sx);
2018-12-15 23:10:11 +01:00
vec2.setY(positions[ar[i * 3 + 1] * 4 + 1] * sy);
vec2.setZ(positions[ar[i * 3 + 1] * 4 + 2] * sz);
2019-01-07 15:41:06 +01:00
vec3.setX(positions[ar[i * 3 + 2] * 4 ] * sx);
2018-12-15 23:10:11 +01:00
vec3.setY(positions[ar[i * 3 + 2] * 4 + 1] * sy);
vec3.setZ(positions[ar[i * 3 + 2] * 4 + 2] * sz);
2018-08-23 20:26:40 +02:00
triangleMesh.addTriangle(vec1, vec2, vec3);
2018-01-10 21:10:08 +01:00
}
2015-11-26 22:30:19 +01:00
}
2019-01-07 15:41:06 +01:00
return triangleMesh;
}
public function delete() {
#if js
bullet.Bt.Ammo.destroy(motionState);
bullet.Bt.Ammo.destroy(body);
#else
motionState.delete();
body.delete();
#end
// Delete shape if no other user is found
if (shape == Shape.ConvexHull || shape == Shape.Mesh) {
var data = cast(object, MeshObject).data;
var i = usersCache.get(data) - 1;
usersCache.set(data, i);
if (i <= 0) {
deleteShape();
shape == Shape.ConvexHull ?
convexHullCache.remove(data) :
triangleMeshCache.remove(data);
}
}
else deleteShape();
}
inline function deleteShape() {
#if js
bullet.Bt.Ammo.destroy(btshape);
#else
btshape.delete();
#end
2015-11-26 22:30:19 +01:00
}
}
2016-07-19 19:42:46 +02:00
2017-11-06 13:01:08 +01:00
@:enum abstract Shape(Int) from Int to Int {
2016-07-19 19:42:46 +02:00
var Box = 0;
var Sphere = 1;
var ConvexHull = 2;
var Mesh = 3;
var Cone = 4;
var Cylinder = 5;
var Capsule = 6;
var Terrain = 7;
}
2017-01-19 00:26:18 +01:00
2017-11-06 13:01:08 +01:00
@:enum abstract ActivationState(Int) from Int to Int {
2017-01-19 00:26:18 +01:00
var Active = 1;
var NoDeactivation = 4;
var NoSimulation = 5;
}
2017-09-30 02:15:21 +02:00
#end