armory/Sources/armory/trait/internal/RigidBody.hx

313 lines
8.9 KiB
Haxe
Raw Normal View History

2016-07-10 00:51:39 +02:00
package armory.trait.internal;
2015-11-26 22:30:19 +01:00
2016-10-12 18:26:56 +02:00
#if arm_physics
2015-11-26 22:30:19 +01:00
import haxebullet.Bullet;
2016-01-11 13:50:54 +01:00
#end
2016-07-10 00:51:39 +02:00
import iron.Trait;
import iron.math.Vec4;
2016-08-25 00:26:01 +02:00
import iron.object.Transform;
import iron.object.MeshObject;
2015-11-26 22:30:19 +01:00
2016-10-12 17:52:27 +02:00
@:keep
2015-11-26 22:30:19 +01:00
class RigidBody extends Trait {
2016-10-12 18:26:56 +02:00
#if (!arm_physics)
2015-12-24 16:12:32 +01:00
public function new() { super(); }
#else
2016-07-19 19:42:46 +02:00
var shape:Shape;
2016-10-23 15:32:26 +02:00
var _motionState:BtMotionStatePointer;
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;
public var passive:Bool;
2015-11-26 22:30:19 +01:00
2016-01-21 02:37:36 +01:00
public var body:BtRigidBodyPointer = null;
2016-12-07 02:01:42 +01:00
public var ready = false;
2016-07-19 19:42:46 +02:00
public var shapeConvexCreated:Bool;
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;
2015-11-26 22:30:19 +01:00
2017-05-14 11:59:12 +02:00
public function new(mass = 1.0, shape = Shape.Box, friction = 0.5, restitution = 0.0, collisionMargin = 0.0,
2016-12-08 14:30:39 +01:00
linearDamping = 0.04, angularDamping = 0.1, passive = false) {
2015-11-26 22:30:19 +01:00
super();
this.mass = mass;
this.shape = shape;
this.friction = friction;
2017-05-14 11:59:12 +02:00
this.restitution = restitution;
2016-05-06 23:46:04 +02:00
this.collisionMargin = collisionMargin;
2016-12-08 14:30:39 +01:00
this.linearDamping = linearDamping;
this.angularDamping = angularDamping;
this.passive = passive;
2017-04-16 14:46:35 +02:00
notifyOnAdd(init);
notifyOnLateUpdate(lateUpdate);
notifyOnRemove(removeFromWorld);
2015-11-26 22:30:19 +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;
2015-11-26 22:30:19 +01:00
2017-04-02 13:13:43 +02:00
transform = object.transform;
// Parented rigid body - clear parent location
if (object.parent != null && object.parent.name != "") {
transform.loc.x += object.parent.transform.absx();
transform.loc.y += object.parent.transform.absy();
transform.loc.z += object.parent.transform.absz();
transform.localOnly = true;
transform.buildMatrix();
}
physics = armory.trait.internal.PhysicsWorld.active;
2016-01-21 02:37:36 +01:00
var _shape:BtCollisionShapePointer = null;
var _shapeConvex:BtConvexHullShapePointer = null;
2016-04-27 10:29:32 +02:00
shapeConvexCreated = false;
var _inertia = BtVector3.create(0, 0, 0);
2015-11-26 22:30:19 +01:00
2016-07-19 19:42:46 +02:00
if (shape == Shape.Box) {
2015-11-26 22:30:19 +01:00
_shape = BtBoxShape.create(BtVector3.create(
2016-05-06 23:46:04 +02:00
withMargin(transform.size.x / 2),
withMargin(transform.size.y / 2),
2017-02-26 15:09:36 +01:00
withMargin(transform.size.z / 2)));
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Sphere) {
2016-05-06 23:46:04 +02:00
_shape = BtSphereShape.create(withMargin(transform.size.x / 2));
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.ConvexHull || shape == Shape.Mesh) { // Use convex hull for mesh for now
2015-11-26 22:30:19 +01:00
_shapeConvex = BtConvexHullShape.create();
2016-04-27 10:29:32 +02:00
shapeConvexCreated = true;
addPointsToConvexHull(_shapeConvex, transform.scale, collisionMargin);
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Cone) {
2016-01-21 02:37:36 +01:00
_shape = BtConeShapeZ.create(
2016-05-06 23:46:04 +02:00
withMargin(transform.size.x / 2), // Radius
withMargin(transform.size.z)); // Height
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Cylinder) {
2015-11-26 22:30:19 +01:00
_shape = BtCylinderShapeZ.create(BtVector3.create(
2016-05-06 23:46:04 +02:00
withMargin(transform.size.x / 2),
withMargin(transform.size.y / 2),
2017-02-26 15:09:36 +01:00
withMargin(transform.size.z / 2)));
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.Capsule) {
2016-12-08 14:30:39 +01:00
var r = transform.size.x / 2;
2016-01-21 02:37:36 +01:00
_shape = BtCapsuleShapeZ.create(
2016-12-08 14:30:39 +01:00
withMargin(r), // Radius
withMargin(transform.size.z - r * 2)); // Height between 2 sphere centers
2015-11-26 22:30:19 +01:00
}
//else if (shape == SHAPE_TERRAIN) {
2016-05-07 00:32:52 +02:00
// var data:Array<Dynamic> = [];
// _shape = BtHeightfieldTerrainShape.create(3, 3, data, 1, -10, 10, 2, 0, true);
2015-11-26 22:30:19 +01:00
//}
2016-07-19 19:42:46 +02:00
else if (shape == Shape.StaticMesh || shape == Shape.Terrain) {
2015-11-26 22:30:19 +01:00
var meshInterface = BtTriangleMesh.create(true, true);
fillTriangleMesh(meshInterface, transform.scale);
2015-11-26 22:30:19 +01:00
_shape = BtBvhTriangleMeshShape.create(meshInterface, true, true);
}
var _transform = BtTransform.create();
2017-02-26 15:09:36 +01:00
_transform.setIdentity();
_transform.setOrigin(BtVector3.create(
2016-08-25 00:26:01 +02:00
transform.loc.x,
transform.loc.y,
2017-02-26 15:09:36 +01:00
transform.loc.z));
_transform.setRotation(BtQuaternion.create(
2015-11-26 22:30:19 +01:00
transform.rot.x,
transform.rot.y,
transform.rot.z,
2017-02-26 15:09:36 +01:00
transform.rot.w));
2015-11-26 22:30:19 +01:00
var _centerOfMassOffset = BtTransform.create();
2017-02-26 15:09:36 +01:00
_centerOfMassOffset.setIdentity();
_motionState = BtDefaultMotionState.create(_transform, _centerOfMassOffset);
2015-11-26 22:30:19 +01:00
2016-04-27 10:29:32 +02:00
if (!shapeConvexCreated) {
2016-07-19 19:42:46 +02:00
if (shape != Shape.StaticMesh && shape != Shape.Terrain) {
2017-02-26 15:09:36 +01:00
_shape.calculateLocalInertia(mass, _inertia);
2015-11-26 22:30:19 +01:00
}
2017-02-26 15:09:36 +01:00
var _bodyCI = BtRigidBodyConstructionInfo.create(mass, _motionState, _shape, _inertia);
body = BtRigidBody.create(_bodyCI);
2015-11-26 22:30:19 +01:00
}
else {
2017-02-26 15:09:36 +01:00
_shapeConvex.calculateLocalInertia(mass, _inertia);
var _bodyCI = BtRigidBodyConstructionInfo.create(mass, _motionState, _shapeConvex, _inertia);
body = BtRigidBody.create(_bodyCI);
2015-11-26 22:30:19 +01:00
}
2017-04-02 13:13:43 +02:00
body.setFriction(friction);
body.setRollingFriction(friction);
2017-05-14 11:59:12 +02:00
body.setRestitution(restitution);
2015-11-26 22:30:19 +01:00
id = nextId;
nextId++;
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
}
2015-11-26 22:30:19 +01:00
#if js
//body.setUserIndex(nextId);
untyped body.userIndex = id;
#elseif cpp
2017-02-26 15:09:36 +01:00
body.setUserIndex(id);
2015-11-26 22:30:19 +01:00
#end
physics.addRigidBody(this);
2016-10-02 19:52:40 +02:00
if (onReady != null) onReady();
2015-11-26 22:30:19 +01:00
}
2016-03-28 23:02:42 +02:00
function lateUpdate() {
2016-12-07 02:01:42 +01:00
if (!ready) return;
2016-12-08 14:30:39 +01:00
if (object.animation != null || passive) {
2016-10-09 16:06:18 +02:00
syncTransform();
}
else {
2017-02-26 15:09:36 +01:00
var trans = body.getWorldTransform();
2016-10-09 16:06:18 +02:00
var p = trans.getOrigin();
var q = trans.getRotation();
transform.loc.set(p.x(), p.y(), p.z());
transform.rot.set(q.x(), q.y(), q.z(), q.w());
2017-03-12 17:29:22 +01:00
transform.buildMatrix();
2016-10-09 16:06:18 +02:00
}
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() {
2017-02-26 15:09:36 +01:00
body.activate(false);
2015-11-26 22:30:19 +01:00
}
2016-04-27 10:29:32 +02:00
public function disableGravity() {
2015-11-26 22:30:19 +01:00
// TODO: use setGravity instead
setLinearFactor(0, 0, 0);
setAngularFactor(0, 0, 0);
}
2016-04-27 10:29:32 +02:00
/*public function setGravity(v:Vec4) {
2017-02-26 15:09:36 +01:00
body.setGravity(BtVector3.create(v.x, v.y, v.z));
2015-11-26 22:30:19 +01:00
}*/
2017-01-19 00:26:18 +01:00
public function setActivationState(newState:Int) {
2017-02-26 15:09:36 +01:00
body.setActivationState(newState);
2017-01-19 00:26:18 +01:00
}
2015-11-26 22:30:19 +01:00
2016-08-25 00:26:01 +02:00
public function applyImpulse(impulse:Vec4, loc:Vec4 = null) {
if (loc == null) {
2017-02-26 15:09:36 +01:00
body.applyCentralImpulse(BtVector3.create(impulse.x, impulse.y, impulse.z));
2015-11-26 22:30:19 +01:00
}
else {
2017-02-26 15:09:36 +01:00
body.applyImpulse(BtVector3.create(impulse.x, impulse.y, impulse.z),
BtVector3.create(loc.x, loc.y, loc.z));
2015-11-26 22:30:19 +01:00
}
}
2016-04-27 10:29:32 +02:00
public function setLinearFactor(x:Float, y:Float, z:Float) {
2017-02-26 15:09:36 +01:00
body.setLinearFactor(BtVector3.create(x, y, z));
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) {
2017-02-26 15:09:36 +01:00
body.setAngularFactor(BtVector3.create(x, y, z));
2015-11-26 22:30:19 +01:00
}
2016-05-05 19:50:03 +02:00
public function getLinearVelocity():BtVector3 {
2017-02-26 15:09:36 +01:00
return body.getLinearVelocity(); // Unable to compile in cpp
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) {
2017-02-26 15:09:36 +01:00
body.setLinearVelocity(BtVector3.create(x, y, z));
2015-11-26 22:30:19 +01:00
}
2016-04-27 10:29:32 +02:00
// public function getAngularVelocity():BtVector3 {
2017-02-26 15:09:36 +01:00
// return body.getAngularVelocity();
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) {
2017-02-26 15:09:36 +01:00
body.setAngularVelocity(BtVector3.create(x, y, z));
2015-11-26 22:30:19 +01:00
}
public function syncTransform() {
var trans = BtTransform.create();
2017-02-26 15:09:36 +01:00
trans.setOrigin(BtVector3.create(transform.loc.x, transform.loc.y, transform.loc.z));
trans.setRotation(BtQuaternion.create(transform.rot.x, transform.rot.y, transform.rot.z, transform.rot.w));
body.setCenterOfMassTransform(trans);
2016-10-09 16:06:18 +02:00
// _motionState.getWorldTransform(trans);
2017-02-26 15:09:36 +01:00
// trans.setOrigin(BtVector3.create(transform.loc.x, transform.loc.y, transform.loc.z));
2016-10-09 16:06:18 +02:00
// _motionState.setWorldTransform(trans);
2015-11-26 22:30:19 +01:00
}
function addPointsToConvexHull(shape:BtConvexHullShapePointer, scale:Vec4, margin:Float) {
2017-05-14 09:27:47 +02:00
var positions = cast(object, MeshObject).data.geom.positions;
2015-11-26 22:30:19 +01:00
var sx = scale.x * (1.0 - margin);
var sy = scale.y * (1.0 - margin);
var sz = scale.z * (1.0 - margin);
2015-11-26 22:30:19 +01:00
for (i in 0...Std.int(positions.length / 3)) {
2017-02-26 15:09:36 +01:00
shape.addPoint(BtVector3.create(positions[i * 3] * sx, positions[i * 3 + 1] * sy, positions[i * 3 + 2] * sz), true);
2015-11-26 22:30:19 +01:00
}
}
function fillTriangleMesh(triangleMesh:BtTriangleMeshPointer, scale:Vec4) {
2017-05-14 09:27:47 +02:00
var positions = cast(object, MeshObject).data.geom.positions;
2017-06-02 16:41:36 +02:00
var indices = cast(object, MeshObject).data.geom.indices;
2015-11-26 22:30:19 +01:00
for (i in 0...Std.int(indices[0].length / 3)) {
2017-02-26 15:09:36 +01:00
triangleMesh.addTriangle(
BtVector3.create(positions[indices[0][i * 3 + 0] * 3 + 0] * scale.x,
positions[indices[0][i * 3 + 0] * 3 + 1] * scale.y,
2017-02-26 15:09:36 +01:00
positions[indices[0][i * 3 + 0] * 3 + 2] * scale.z),
BtVector3.create(positions[indices[0][i * 3 + 1] * 3 + 0] * scale.x,
positions[indices[0][i * 3 + 1] * 3 + 1] * scale.y,
2017-02-26 15:09:36 +01:00
positions[indices[0][i * 3 + 1] * 3 + 2] * scale.z),
BtVector3.create(positions[indices[0][i * 3 + 2] * 3 + 0] * scale.x,
positions[indices[0][i * 3 + 2] * 3 + 1] * scale.y,
2017-02-26 15:09:36 +01:00
positions[indices[0][i * 3 + 2] * 3 + 2] * scale.z)
2015-11-26 22:30:19 +01:00
);
}
}
2015-12-24 16:12:32 +01:00
#end
2015-11-26 22:30:19 +01:00
}
2016-07-19 19:42:46 +02:00
@:enum abstract Shape(Int) from Int {
var Box = 0;
var Sphere = 1;
var ConvexHull = 2;
var Mesh = 3;
var Cone = 4;
var Cylinder = 5;
var Capsule = 6;
var Terrain = 7;
var StaticMesh = 8;
}
2017-01-19 00:26:18 +01:00
@:enum abstract ActivationState(Int) from Int {
var Active = 1;
var NoDeactivation = 4;
var NoSimulation = 5;
}