@enable3d/ammo-physics
Advanced tools
Comparing version 0.0.16 to 0.17.0
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
import PhysicsBody from './physicsBody'; | ||
import PhysicsBody from '@enable3d/common/dist/physicsBody'; | ||
import { XYZ } from '@enable3d/common/dist/types'; | ||
@@ -12,23 +12,42 @@ export default class Constraints { | ||
physicsWorld: Ammo.btDiscreteDynamicsWorld; | ||
protected tmpBtVector3: Ammo.btVector3; | ||
constructor(); | ||
private toAmmoV3; | ||
protected get addConstraints(): { | ||
lock: (body: PhysicsBody, targetBody: PhysicsBody) => void; | ||
fixed: (body: PhysicsBody, targetBody: PhysicsBody) => void; | ||
spring: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
lock: (body: PhysicsBody, targetBody: PhysicsBody) => Ammo.btGeneric6DofConstraint; | ||
fixed: (body: PhysicsBody, targetBody: PhysicsBody) => Ammo.btFixedConstraint; | ||
pointToPoint: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivotA?: XYZ | undefined; | ||
pivotB?: XYZ | undefined; | ||
}) => Ammo.btPoint2PointConstraint; | ||
hinge: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivotA?: XYZ | undefined; | ||
pivotB?: XYZ | undefined; | ||
axisA?: XYZ | undefined; | ||
axisB?: XYZ | undefined; | ||
}) => Ammo.btHingeConstraint; | ||
slider: (body: PhysicsBody, targetBody: PhysicsBody, config?: { | ||
frameA?: XYZ | undefined; | ||
frameB?: XYZ | undefined; | ||
linearLowerLimit?: number | undefined; | ||
linearUpperLimit?: number | undefined; | ||
angularLowerLimit?: number | undefined; | ||
angularUpperLimit?: number | undefined; | ||
}) => Ammo.btSliderConstraint; | ||
spring: (body: PhysicsBody, targetBody: PhysicsBody, config?: { | ||
stiffness?: number | undefined; | ||
damping?: number | undefined; | ||
angularLock?: boolean | undefined; | ||
}) => void; | ||
slider: (body: PhysicsBody, targetBody: PhysicsBody) => void; | ||
hinge: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivot?: XYZ | undefined; | ||
targetPivot?: XYZ | undefined; | ||
axis?: XYZ | undefined; | ||
targetAxis?: XYZ | undefined; | ||
}) => void; | ||
coneTwist: (body: PhysicsBody, targetPivot: XYZ) => void; | ||
pointToPoint: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivot?: XYZ | undefined; | ||
targetPivot?: XYZ | undefined; | ||
}) => void; | ||
linearLowerLimit?: XYZ | undefined; | ||
linearUpperLimit?: XYZ | undefined; | ||
}) => Ammo.btGeneric6DofSpringConstraint; | ||
coneTwist: (bodyA: PhysicsBody, bodyB: PhysicsBody, frameA?: XYZ, frameB?: XYZ) => Ammo.btConeTwistConstraint; | ||
dof: (bodyA: PhysicsBody, bodyB: PhysicsBody, config?: { | ||
linearLowerLimit?: XYZ | undefined; | ||
linearUpperLimit?: XYZ | undefined; | ||
angularLowerLimit?: XYZ | undefined; | ||
angularUpperLimit?: XYZ | undefined; | ||
center?: boolean | undefined; | ||
offset?: XYZ | undefined; | ||
} | undefined) => Ammo.btGeneric6DofConstraint; | ||
}; | ||
@@ -38,8 +57,9 @@ private getTransform; | ||
private fixed; | ||
private pointToPoint; | ||
private hinge; | ||
private slider; | ||
private spring; | ||
private slider; | ||
private hinge; | ||
private coneTwist; | ||
private pointToPoint; | ||
private dof; | ||
} | ||
//# sourceMappingURL=constraints.d.ts.map |
@@ -7,2 +7,13 @@ "use strict"; | ||
*/ | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -12,2 +23,6 @@ var Constraints = /** @class */ (function () { | ||
} | ||
Constraints.prototype.toAmmoV3 = function (v, d) { | ||
if (d === void 0) { d = 0; } | ||
return new Ammo.btVector3(typeof (v === null || v === void 0 ? void 0 : v.x) !== 'undefined' ? v.x : d, typeof (v === null || v === void 0 ? void 0 : v.y) !== 'undefined' ? v.y : d, typeof (v === null || v === void 0 ? void 0 : v.z) !== 'undefined' ? v.z : d); | ||
}; | ||
Object.defineProperty(Constraints.prototype, "addConstraints", { | ||
@@ -19,7 +34,18 @@ get: function () { | ||
fixed: function (body, targetBody) { return _this.fixed(body, targetBody); }, | ||
spring: function (body, targetBody, config) { return _this.spring(body, targetBody, config); }, | ||
slider: function (body, targetBody) { return _this.slider(body, targetBody); }, | ||
pointToPoint: function (body, targetBody, config) { return _this.pointToPoint(body, targetBody, config); }, | ||
hinge: function (body, targetBody, config) { return _this.hinge(body, targetBody, config); }, | ||
coneTwist: function (body, targetPivot) { return _this.coneTwist(body, targetPivot); }, | ||
pointToPoint: function (body, targetBody, config) { return _this.pointToPoint(body, targetBody, config); } | ||
slider: function (body, targetBody, config) { | ||
if (config === void 0) { config = {}; } | ||
return _this.slider(body, targetBody, config); | ||
}, | ||
spring: function (body, targetBody, config) { | ||
if (config === void 0) { config = {}; } | ||
return _this.spring(body, targetBody, config); | ||
}, | ||
coneTwist: function (bodyA, bodyB, frameA, frameB) { | ||
if (frameA === void 0) { frameA = {}; } | ||
if (frameB === void 0) { frameB = {}; } | ||
return _this.coneTwist(bodyA, bodyB, frameA, frameB); | ||
}, | ||
dof: function (bodyA, bodyB, config) { return _this.dof(bodyA, bodyB, config); } | ||
}; | ||
@@ -30,36 +56,101 @@ }, | ||
}); | ||
Constraints.prototype.getTransform = function (body, targetBody) { | ||
var bodyTransform = body.getCenterOfMassTransform().inverse().op_mul(targetBody.getWorldTransform()); | ||
var targetTransform = new Ammo.btTransform(); | ||
targetTransform.setIdentity(); | ||
return { body: bodyTransform, target: targetTransform }; | ||
Constraints.prototype.getTransform = function (bodyA, bodyB, offset, center) { | ||
if (offset === void 0) { offset = { x: 0, y: 0, z: 0 }; } | ||
if (center === void 0) { center = false; } | ||
offset = __assign({ x: 0, y: 0, z: 0 }, offset); | ||
var centerVector = function (v1, v2) { | ||
var dx = (v1.x() - v2.x()) / 2 + offset.x; | ||
var dy = (v1.y() - v2.y()) / 2 + offset.y; | ||
var dz = (v1.z() - v2.z()) / 2 + offset.z; | ||
return new Ammo.btVector3(dx, dy, dz); | ||
}; | ||
var transformB = new Ammo.btTransform(); | ||
transformB.setIdentity(); | ||
if (!center) { | ||
// offset | ||
transformB.setOrigin(new Ammo.btVector3(offset.x, offset.y, offset.z)); | ||
var transformA = bodyA | ||
.getCenterOfMassTransform() | ||
.inverse() | ||
.op_mul(bodyB.getWorldTransform()) | ||
.op_mul(transformB); | ||
return { transformA: transformA, transformB: transformB }; | ||
} | ||
else { | ||
var center_1 = centerVector(bodyA.getWorldTransform().getOrigin(), bodyB.getWorldTransform().getOrigin()); | ||
var transformB_1 = new Ammo.btTransform(); | ||
transformB_1.setIdentity(); | ||
transformB_1.setOrigin(center_1); | ||
var transformA = bodyA | ||
.getCenterOfMassTransform() | ||
.inverse() | ||
.op_mul(bodyB.getWorldTransform()); | ||
transformA.op_mul(transformB_1); | ||
return { transformA: transformA, transformB: transformB_1 }; | ||
} | ||
}; | ||
Constraints.prototype.lock = function (body, targetBody) { | ||
var transform = this.getTransform(body.ammo, targetBody.ammo); | ||
var constraint = new Ammo.btGeneric6DofConstraint(body.ammo, targetBody.ammo, transform.body, transform.target, true); | ||
var zero = new Ammo.btVector3(0, 0, 0); | ||
//TODO: allow these to be configurable | ||
constraint.setLinearLowerLimit(zero); | ||
constraint.setLinearUpperLimit(zero); | ||
constraint.setAngularLowerLimit(zero); | ||
constraint.setAngularUpperLimit(zero); | ||
Constraints.prototype.lock = function (bodyA, bodyB) { | ||
var zero = { x: 0, y: 0, z: 0 }; | ||
return this.dof(bodyA, bodyB, { angularLowerLimit: zero, angularUpperLimit: zero }); | ||
}; | ||
Constraints.prototype.fixed = function (bodyA, bodyB) { | ||
var transform = this.getTransform(bodyA.ammo, bodyB.ammo); | ||
transform.transformA.setRotation(bodyA.ammo.getWorldTransform().getRotation()); | ||
transform.transformB.setRotation(bodyB.ammo.getWorldTransform().getRotation()); | ||
var constraint = new Ammo.btFixedConstraint(bodyA.ammo, bodyB.ammo, transform.transformA, transform.transformB); | ||
this.physicsWorld.addConstraint(constraint); | ||
return constraint; | ||
}; | ||
Constraints.prototype.fixed = function (body, targetBody) { | ||
var transform = this.getTransform(body.ammo, targetBody.ammo); | ||
transform.body.setRotation(body.ammo.getWorldTransform().getRotation()); | ||
transform.target.setRotation(targetBody.ammo.getWorldTransform().getRotation()); | ||
var constraint = new Ammo.btFixedConstraint(body.ammo, targetBody.ammo, transform.body, transform.target); | ||
Constraints.prototype.pointToPoint = function (body, targetBody, config) { | ||
if (config === void 0) { config = {}; } | ||
var pivotA = config.pivotA, pivotB = config.pivotB; | ||
var pivotV3 = new Ammo.btVector3((pivotA === null || pivotA === void 0 ? void 0 : pivotA.x) || 0, (pivotA === null || pivotA === void 0 ? void 0 : pivotA.y) || 0, (pivotA === null || pivotA === void 0 ? void 0 : pivotA.z) || 0); | ||
var targetPivotV3 = new Ammo.btVector3((pivotB === null || pivotB === void 0 ? void 0 : pivotB.x) || 0, (pivotB === null || pivotB === void 0 ? void 0 : pivotB.y) || 0, (pivotB === null || pivotB === void 0 ? void 0 : pivotB.z) || 0); | ||
var constraint = new Ammo.btPoint2PointConstraint(body.ammo, targetBody.ammo, pivotV3, targetPivotV3); | ||
this.physicsWorld.addConstraint(constraint); | ||
return constraint; | ||
}; | ||
Constraints.prototype.hinge = function (body, targetBody, config) { | ||
if (config === void 0) { config = {}; } | ||
var pivotA = config.pivotA, pivotB = config.pivotB, axisA = config.axisA, axisB = config.axisB; | ||
var pivotV3 = new Ammo.btVector3((pivotA === null || pivotA === void 0 ? void 0 : pivotA.x) || 0, (pivotA === null || pivotA === void 0 ? void 0 : pivotA.y) || 0, (pivotA === null || pivotA === void 0 ? void 0 : pivotA.z) || 0); | ||
var targetPivotV3 = new Ammo.btVector3((pivotB === null || pivotB === void 0 ? void 0 : pivotB.x) || 0, (pivotB === null || pivotB === void 0 ? void 0 : pivotB.y) || 0, (pivotB === null || pivotB === void 0 ? void 0 : pivotB.z) || 0); | ||
var axisV3 = new Ammo.btVector3((axisA === null || axisA === void 0 ? void 0 : axisA.x) || 0, (axisA === null || axisA === void 0 ? void 0 : axisA.y) || 0, (axisA === null || axisA === void 0 ? void 0 : axisA.z) || 0); | ||
var targetAxisV3 = new Ammo.btVector3((axisB === null || axisB === void 0 ? void 0 : axisB.x) || 0, (axisB === null || axisB === void 0 ? void 0 : axisB.y) || 0, (axisB === null || axisB === void 0 ? void 0 : axisB.z) || 0); | ||
var constraint = new Ammo.btHingeConstraint(body.ammo, targetBody.ammo, pivotV3, targetPivotV3, axisV3, targetAxisV3, true); | ||
this.physicsWorld.addConstraint(constraint); | ||
return constraint; | ||
}; | ||
// https://pybullet.org/Bullet/phpBB3/viewtopic.php?f=9&t=12690&p=42152&hilit=btSliderConstraint#p42152 | ||
Constraints.prototype.slider = function (bodyA, bodyB, config) { | ||
if (config === void 0) { config = {}; } | ||
var transform = this.getTransform(bodyA.ammo, bodyB.ammo); | ||
var _a = config.frameA, frameA = _a === void 0 ? {} : _a, _b = config.frameB, frameB = _b === void 0 ? {} : _b, _c = config.linearLowerLimit, lll = _c === void 0 ? 0 : _c, _d = config.linearUpperLimit, lul = _d === void 0 ? 0 : _d, _e = config.angularLowerLimit, all = _e === void 0 ? 0 : _e, _f = config.angularUpperLimit, aul = _f === void 0 ? 0 : _f; | ||
var rotationA = transform.transformA.getRotation(); | ||
rotationA.setEulerZYX(frameA.x || 0, frameA.y || 0, frameA.z || 0); | ||
transform.transformA.setRotation(rotationA); | ||
var rotationB = transform.transformB.getRotation(); | ||
rotationB.setEulerZYX(frameB.x || 0, frameB.y || 0, frameB.z || 0); | ||
transform.transformB.setRotation(rotationB); | ||
var constraint = new Ammo.btSliderConstraint(bodyA.ammo, bodyB.ammo, transform.transformA, transform.transformB, true); | ||
constraint.setLowerLinLimit(lll); | ||
constraint.setUpperLinLimit(lul); | ||
constraint.setLowerAngLimit(all); | ||
constraint.setUpperAngLimit(aul); | ||
this.physicsWorld.addConstraint(constraint); | ||
return constraint; | ||
}; | ||
Constraints.prototype.spring = function (body, targetBody, config) { | ||
if (config === void 0) { config = {}; } | ||
var _a = config.stiffness, stiffness = _a === void 0 ? 50 : _a, _b = config.damping, damping = _b === void 0 ? 0.01 : _b, _c = config.angularLock, angularLock = _c === void 0 ? false : _c; | ||
var _a = config.stiffness, stiffness = _a === void 0 ? 50 : _a, _b = config.damping, damping = _b === void 0 ? 0.01 : _b, _c = config.angularLock, angularLock = _c === void 0 ? false : _c, _d = config.linearLowerLimit, lll = _d === void 0 ? {} : _d, _e = config.linearUpperLimit, lul = _e === void 0 ? {} : _e; | ||
var transform = this.getTransform(body.ammo, targetBody.ammo); | ||
var constraint = new Ammo.btGeneric6DofSpringConstraint(body.ammo, targetBody.ammo, transform.body, transform.target, true); | ||
constraint.setLinearLowerLimit(new Ammo.btVector3(-100, -100, -100)); | ||
constraint.setLinearUpperLimit(new Ammo.btVector3(100, 100, 100)); | ||
var constraint = new Ammo.btGeneric6DofSpringConstraint(body.ammo, targetBody.ammo, transform.transformA, transform.transformB, true); | ||
this.tmpBtVector3.setValue(lll.x || 0, lll.y || 0, lll.z || 0); | ||
constraint.setLinearLowerLimit(this.tmpBtVector3); | ||
this.tmpBtVector3.setValue(lul.x || 0, lul.y || 0, lul.z || 0); | ||
constraint.setLinearUpperLimit(this.tmpBtVector3); | ||
if (angularLock) { | ||
constraint.setAngularLowerLimit(new Ammo.btVector3(0, 0, 0)); | ||
constraint.setAngularUpperLimit(new Ammo.btVector3(0, 0, 0)); | ||
this.tmpBtVector3.setValue(0, 0, 0); | ||
constraint.setAngularLowerLimit(this.tmpBtVector3); | ||
constraint.setAngularUpperLimit(this.tmpBtVector3); | ||
} | ||
@@ -74,39 +165,43 @@ for (var i = 0; i < 3; i++) { | ||
this.physicsWorld.addConstraint(constraint); | ||
return constraint; | ||
}; | ||
Constraints.prototype.slider = function (body, targetBody) { | ||
var transform = this.getTransform(body.ammo, targetBody.ammo); | ||
//TODO: support setting linear and angular limits | ||
var constraint = new Ammo.btSliderConstraint(body.ammo, targetBody.ammo, transform.body, transform.target, true); | ||
constraint.setLowerLinLimit(-1); | ||
constraint.setUpperLinLimit(1); | ||
// constraint.setLowerAngLimit(); | ||
// constraint.setUpperAngLimit(); | ||
Constraints.prototype.coneTwist = function (bodyA, bodyB, frameA, frameB) { | ||
if (frameA === void 0) { frameA = {}; } | ||
if (frameB === void 0) { frameB = {}; } | ||
var rbAFrame = new Ammo.btTransform(); | ||
rbAFrame.setIdentity(); | ||
rbAFrame.getOrigin().setValue((frameA === null || frameA === void 0 ? void 0 : frameA.x) || 0, (frameA === null || frameA === void 0 ? void 0 : frameA.y) || 0, (frameA === null || frameA === void 0 ? void 0 : frameA.z) || 0); | ||
var rbBFrame = new Ammo.btTransform(); | ||
rbBFrame.setIdentity(); | ||
rbBFrame.getOrigin().setValue((frameB === null || frameB === void 0 ? void 0 : frameB.x) || 0, (frameB === null || frameB === void 0 ? void 0 : frameB.y) || 0, (frameB === null || frameB === void 0 ? void 0 : frameB.z) || 0); | ||
var t = this.getTransform(bodyA.ammo, bodyB.ammo); | ||
var constraint = new Ammo.btConeTwistConstraint(bodyB.ammo, bodyA.ammo, rbAFrame, rbBFrame); | ||
// does not work at all :/ | ||
// constraint.setLimit(-Math.PI / 50, Math.PI / 50) | ||
constraint.setAngularOnly(true); | ||
this.physicsWorld.addConstraint(constraint); | ||
return constraint; | ||
}; | ||
Constraints.prototype.hinge = function (body, targetBody, config) { | ||
Constraints.prototype.dof = function (bodyA, bodyB, config) { | ||
if (config === void 0) { config = {}; } | ||
var pivot = config.pivot, targetPivot = config.targetPivot, axis = config.axis, targetAxis = config.targetAxis; | ||
var pivotV3 = new Ammo.btVector3((pivot === null || pivot === void 0 ? void 0 : pivot.x) || 0, (pivot === null || pivot === void 0 ? void 0 : pivot.y) || 0, (pivot === null || pivot === void 0 ? void 0 : pivot.z) || 0); | ||
var targetPivotV3 = new Ammo.btVector3((targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.x) || 0, (targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.y) || 0, (targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.z) || 0); | ||
var axisV3 = new Ammo.btVector3((axis === null || axis === void 0 ? void 0 : axis.x) || 0, (axis === null || axis === void 0 ? void 0 : axis.y) || 0, (axis === null || axis === void 0 ? void 0 : axis.z) || 1); | ||
var targetAxisV3 = new Ammo.btVector3((targetAxis === null || targetAxis === void 0 ? void 0 : targetAxis.x) || 0, (targetAxis === null || targetAxis === void 0 ? void 0 : targetAxis.y) || 0, (targetAxis === null || targetAxis === void 0 ? void 0 : targetAxis.z) || 1); | ||
var constraint = new Ammo.btHingeConstraint(body.ammo, targetBody.ammo, pivotV3, targetPivotV3, axisV3, targetAxisV3, true); | ||
this.physicsWorld.addConstraint(constraint); | ||
var offset = config.offset, _a = config.center, center = _a === void 0 ? false : _a; | ||
var off = __assign({ x: 0, y: 0, z: 0 }, offset); | ||
var transform = this.getTransform(bodyA.ammo, bodyB.ammo, off, center); | ||
var constraint = new Ammo.btGeneric6DofConstraint(bodyA.ammo, bodyB.ammo, transform.transformA, transform.transformB, true); | ||
var linearLowerLimit = config.linearLowerLimit, linearUpperLimit = config.linearUpperLimit, angularLowerLimit = config.angularLowerLimit, angularUpperLimit = config.angularUpperLimit; | ||
var lll = this.toAmmoV3(linearLowerLimit); | ||
var lul = this.toAmmoV3(linearUpperLimit); | ||
var all = this.toAmmoV3(angularLowerLimit, -Math.PI); | ||
var aul = this.toAmmoV3(angularUpperLimit, Math.PI); | ||
constraint.setLinearLowerLimit(lll); | ||
constraint.setLinearUpperLimit(lul); | ||
constraint.setAngularLowerLimit(all); | ||
constraint.setAngularUpperLimit(aul); | ||
Ammo.destroy(lll); | ||
Ammo.destroy(lul); | ||
Ammo.destroy(all); | ||
Ammo.destroy(aul); | ||
this.physicsWorld.addConstraint(constraint, false); | ||
return constraint; | ||
}; | ||
Constraints.prototype.coneTwist = function (body, targetPivot) { | ||
if (targetPivot === void 0) { targetPivot = {}; } | ||
var pivotTransform = new Ammo.btTransform(); | ||
pivotTransform.setIdentity(); | ||
pivotTransform.getOrigin().setValue((targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.x) || 0, (targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.y) || 0, (targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.z) || 0); | ||
var constraint = new Ammo.btConeTwistConstraint(body.ammo, pivotTransform); | ||
this.physicsWorld.addConstraint(constraint); | ||
}; | ||
Constraints.prototype.pointToPoint = function (body, targetBody, config) { | ||
if (config === void 0) { config = {}; } | ||
var pivot = config.pivot, targetPivot = config.targetPivot; | ||
var pivotV3 = new Ammo.btVector3((pivot === null || pivot === void 0 ? void 0 : pivot.x) || 0, (pivot === null || pivot === void 0 ? void 0 : pivot.y) || 0, (pivot === null || pivot === void 0 ? void 0 : pivot.z) || 0); | ||
var targetPivotV3 = new Ammo.btVector3((targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.x) || 0, (targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.y) || 0, (targetPivot === null || targetPivot === void 0 ? void 0 : targetPivot.z) || 0); | ||
var constraint = new Ammo.btPoint2PointConstraint(body.ammo, targetBody.ammo, pivotV3, targetPivotV3); | ||
this.physicsWorld.addConstraint(constraint); | ||
}; | ||
return Constraints; | ||
@@ -113,0 +208,0 @@ }()); |
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
import PhysicsBody from './physicsBody'; | ||
import PhysicsBody from '@enable3d/common/dist/physicsBody'; | ||
import { PlaneConfig, SphereConfig, GroundConfig, MaterialConfig, BoxConfig, CylinderConfig, ConeConfig, ExtrudeConfig, Phaser3DConfig, AddExistingConfig, TorusConfig } from '@enable3d/common/dist/types'; | ||
@@ -21,2 +21,4 @@ import ExtendedObject3D from '@enable3d/common/dist/extendedObject3D'; | ||
import * as Types from '@enable3d/common/dist/types'; | ||
import { ClosestRaycaster, AllHitsRaycaster } from './raycaster/raycaster'; | ||
export { ClosestRaycaster, AllHitsRaycaster }; | ||
export { Types }; | ||
@@ -62,21 +64,38 @@ export { Clock } from './lib/Clock'; | ||
constraints: { | ||
lock: (body: PhysicsBody, targetBody: PhysicsBody) => void; | ||
fixed: (body: PhysicsBody, targetBody: PhysicsBody) => void; | ||
spring: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
lock: (body: PhysicsBody, targetBody: PhysicsBody) => Ammo.btGeneric6DofConstraint; | ||
fixed: (body: PhysicsBody, targetBody: PhysicsBody) => Ammo.btFixedConstraint; | ||
pointToPoint: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivotA?: Types.XYZ | undefined; | ||
pivotB?: Types.XYZ | undefined; | ||
}) => Ammo.btPoint2PointConstraint; | ||
hinge: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivotA?: Types.XYZ | undefined; | ||
pivotB?: Types.XYZ | undefined; | ||
axisA?: Types.XYZ | undefined; | ||
axisB?: Types.XYZ | undefined; | ||
}) => Ammo.btHingeConstraint; | ||
slider: (body: PhysicsBody, targetBody: PhysicsBody, config?: { | ||
frameA?: Types.XYZ | undefined; | ||
frameB?: Types.XYZ | undefined; | ||
linearLowerLimit?: number | undefined; | ||
linearUpperLimit?: number | undefined; | ||
angularLowerLimit?: number | undefined; | ||
angularUpperLimit?: number | undefined; | ||
}) => Ammo.btSliderConstraint; | ||
spring: (body: PhysicsBody, targetBody: PhysicsBody, config?: { | ||
stiffness?: number | undefined; | ||
damping?: number | undefined; | ||
angularLock?: boolean | undefined; | ||
}) => void; | ||
slider: (body: PhysicsBody, targetBody: PhysicsBody) => void; | ||
hinge: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivot?: Types.XYZ | undefined; | ||
targetPivot?: Types.XYZ | undefined; | ||
axis?: Types.XYZ | undefined; | ||
targetAxis?: Types.XYZ | undefined; | ||
}) => void; | ||
coneTwist: (body: PhysicsBody, targetPivot: Types.XYZ) => void; | ||
pointToPoint: (body: PhysicsBody, targetBody: PhysicsBody, config: { | ||
pivot?: Types.XYZ | undefined; | ||
targetPivot?: Types.XYZ | undefined; | ||
}) => void; | ||
linearLowerLimit?: Types.XYZ | undefined; | ||
linearUpperLimit?: Types.XYZ | undefined; | ||
}) => Ammo.btGeneric6DofSpringConstraint; | ||
coneTwist: (bodyA: PhysicsBody, bodyB: PhysicsBody, frameA?: Types.XYZ, frameB?: Types.XYZ) => Ammo.btConeTwistConstraint; | ||
dof: (bodyA: PhysicsBody, bodyB: PhysicsBody, config?: { | ||
linearLowerLimit?: Types.XYZ | undefined; | ||
linearUpperLimit?: Types.XYZ | undefined; | ||
angularLowerLimit?: Types.XYZ | undefined; | ||
angularUpperLimit?: Types.XYZ | undefined; | ||
center?: boolean | undefined; | ||
offset?: Types.XYZ | undefined; | ||
} | undefined) => Ammo.btGeneric6DofConstraint; | ||
}; | ||
@@ -92,2 +111,7 @@ existing: (object: ExtendedObject3D, config?: AddExistingConfig | undefined) => any; | ||
extrude: (extrudeConfig: ExtrudeConfig, materialConfig?: MaterialConfig) => ExtendedObject3D; | ||
/** | ||
* Creates a new Raycaster | ||
* @param type Returns only the closes body by default. Can be 'closest' or 'allHits'. | ||
*/ | ||
raycaster: (type?: string) => ClosestRaycaster | AllHitsRaycaster; | ||
}; | ||
@@ -94,0 +118,0 @@ addCompoundShape(shapes: any): Ammo.btCompoundShape; |
@@ -50,3 +50,3 @@ "use strict"; | ||
var logger_1 = __importDefault(require("@enable3d/common/dist/logger")); | ||
var physicsBody_1 = __importDefault(require("./physicsBody")); | ||
var physicsBody_1 = __importDefault(require("@enable3d/common/dist/physicsBody")); | ||
var applyMixins_1 = __importDefault(require("@enable3d/common/dist/applyMixins")); | ||
@@ -68,2 +68,5 @@ var shapes_1 = __importDefault(require("./shapes")); | ||
exports.Types = Types; | ||
var raycaster_1 = require("./raycaster/raycaster"); | ||
exports.ClosestRaycaster = raycaster_1.ClosestRaycaster; | ||
exports.AllHitsRaycaster = raycaster_1.AllHitsRaycaster; | ||
// Export THREE.Clock | ||
@@ -182,2 +185,13 @@ var Clock_1 = require("./lib/Clock"); | ||
return _this.addExtrude(extrudeConfig, materialConfig); | ||
}, | ||
/** | ||
* Creates a new Raycaster | ||
* @param type Returns only the closes body by default. Can be 'closest' or 'allHits'. | ||
*/ | ||
raycaster: function (type) { | ||
if (type === void 0) { type = 'closest'; } | ||
if (type === 'closest') | ||
return new raycaster_1.ClosestRaycaster(_this); | ||
else | ||
return new raycaster_1.AllHitsRaycaster(_this); | ||
} | ||
@@ -184,0 +198,0 @@ }; |
@@ -11,3 +11,3 @@ /** | ||
import DefaultMaterial from '@enable3d/common/dist/defaultMaterial'; | ||
import PhysicsBody from './physicsBody'; | ||
import PhysicsBody from '@enable3d/common/dist/physicsBody'; | ||
declare class Physics extends EventEmitter { | ||
@@ -14,0 +14,0 @@ protected scene: Scene | 'headless'; |
@@ -160,44 +160,42 @@ "use strict"; | ||
*/ | ||
if (this.scene !== 'headless') { | ||
for (var i = 0, il = this.rigidBodies.length; i < il; i++) { | ||
var objThree = this.rigidBodies[i]; | ||
var objPhys = objThree.body.ammo; | ||
var ms = objPhys.getMotionState(); | ||
if (ms) { | ||
ms.getWorldTransform(this.tmpTrans); | ||
// check if object did an update since last call | ||
if (objThree.body.didUpdate) { | ||
// @ts-ignore | ||
if (objThree.body._emitUpdateEvents) | ||
objThree.body.eventEmitter.emit('update'); | ||
objThree.body.didUpdate = false; | ||
} | ||
// update positions | ||
if (objThree.body.ammo.isKinematicObject() && objThree.body.needUpdate) { | ||
// get position and rotation | ||
objThree.getWorldQuaternion(this.tmpQuaternion); | ||
objThree.getWorldPosition(this.tmpVector3); | ||
// adjust tmp variables | ||
this.tmpBtVector3.setValue(this.tmpVector3.x, this.tmpVector3.y, this.tmpVector3.z); | ||
this.tmpBtQuaternion.setValue(this.tmpQuaternion.x, this.tmpQuaternion.y, this.tmpQuaternion.z, this.tmpQuaternion.w); | ||
// set position and rotation | ||
this.tmpTrans.setOrigin(this.tmpBtVector3); | ||
this.tmpTrans.setRotation(this.tmpBtQuaternion); | ||
// set transform | ||
ms.setWorldTransform(this.tmpTrans); | ||
// reset needsUpdate | ||
objThree.body.needUpdate = false; | ||
} | ||
else { | ||
// get position and rotation | ||
var p = this.tmpTrans.getOrigin(); | ||
var q = this.tmpTrans.getRotation(); | ||
// body offset | ||
var o = objThree.body.offset; | ||
// set position and rotation | ||
objThree.position.set(p.x() + o.x, p.y() + o.y, p.z() + o.z); | ||
objThree.quaternion.set(q.x(), q.y(), q.z(), q.w()); | ||
} | ||
objThree.body.collided = false; | ||
for (var i = 0, il = this.rigidBodies.length; i < il; i++) { | ||
var objThree = this.rigidBodies[i]; | ||
var objPhys = objThree.body.ammo; | ||
var ms = objPhys.getMotionState(); | ||
if (ms) { | ||
ms.getWorldTransform(this.tmpTrans); | ||
// check if object did an update since last call | ||
if (objThree.body.didUpdate) { | ||
// @ts-ignore | ||
if (objThree.body._emitUpdateEvents) | ||
objThree.body.eventEmitter.emit('update'); | ||
objThree.body.didUpdate = false; | ||
} | ||
// update positions | ||
if (objThree.body.ammo.isKinematicObject() && objThree.body.needUpdate) { | ||
// get position and rotation | ||
objThree.getWorldQuaternion(this.tmpQuaternion); | ||
objThree.getWorldPosition(this.tmpVector3); | ||
// adjust tmp variables | ||
this.tmpBtVector3.setValue(this.tmpVector3.x, this.tmpVector3.y, this.tmpVector3.z); | ||
this.tmpBtQuaternion.setValue(this.tmpQuaternion.x, this.tmpQuaternion.y, this.tmpQuaternion.z, this.tmpQuaternion.w); | ||
// set position and rotation | ||
this.tmpTrans.setOrigin(this.tmpBtVector3); | ||
this.tmpTrans.setRotation(this.tmpBtQuaternion); | ||
// set transform | ||
ms.setWorldTransform(this.tmpTrans); | ||
// reset needsUpdate | ||
objThree.body.needUpdate = false; | ||
} | ||
else { | ||
// get position and rotation | ||
var p = this.tmpTrans.getOrigin(); | ||
var q = this.tmpTrans.getRotation(); | ||
// body offset | ||
var o = objThree.body.offset; | ||
// set position and rotation | ||
objThree.position.set(p.x() + o.x, p.y() + o.y, p.z() + o.z); | ||
objThree.quaternion.set(q.x(), q.y(), q.z(), q.w()); | ||
} | ||
objThree.body.collided = false; | ||
} | ||
@@ -204,0 +202,0 @@ } |
{ | ||
"name": "@enable3d/ammo-physics", | ||
"version": "0.0.16", | ||
"version": "0.17.0", | ||
"description": "Physics Plugin for three.js", | ||
@@ -34,6 +34,6 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@enable3d/common": "^0.0.16", | ||
"@enable3d/three-wrapper": "^0.0.16", | ||
"@enable3d/common": "^0.17.0", | ||
"@enable3d/three-wrapper": "^0.17.0", | ||
"eventemitter3": "^4.0.0" | ||
} | ||
} |
<h1 align="center"> | ||
Physics Plugin for tree.js | ||
Physics Plugin for three.js | ||
</h1> | ||
@@ -4,0 +4,0 @@ |
@@ -9,4 +9,5 @@ /** | ||
import PhysicsBody from './physicsBody' | ||
import PhysicsBody from '@enable3d/common/dist/physicsBody' | ||
import { XYZ } from '@enable3d/common/dist/types' | ||
import Physics from './physics' | ||
@@ -17,3 +18,14 @@ export default class Constraints { | ||
protected tmpBtVector3: Ammo.btVector3 | ||
constructor() {} | ||
private toAmmoV3(v?: XYZ, d: number = 0) { | ||
return new Ammo.btVector3( | ||
typeof v?.x !== 'undefined' ? v.x : d, | ||
typeof v?.y !== 'undefined' ? v.y : d, | ||
typeof v?.z !== 'undefined' ? v.z : d | ||
) | ||
} | ||
protected get addConstraints() { | ||
@@ -23,12 +35,10 @@ return { | ||
fixed: (body: PhysicsBody, targetBody: PhysicsBody) => this.fixed(body, targetBody), | ||
spring: ( | ||
pointToPoint: ( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
config: { | ||
stiffness?: number | ||
damping?: number | ||
angularLock?: boolean | ||
pivotA?: XYZ | ||
pivotB?: XYZ | ||
} | ||
) => this.spring(body, targetBody, config), | ||
slider: (body: PhysicsBody, targetBody: PhysicsBody) => this.slider(body, targetBody), | ||
) => this.pointToPoint(body, targetBody, config), | ||
hinge: ( | ||
@@ -38,51 +48,200 @@ body: PhysicsBody, | ||
config: { | ||
pivot?: XYZ | ||
targetPivot?: XYZ | ||
axis?: XYZ | ||
targetAxis?: XYZ | ||
pivotA?: XYZ | ||
pivotB?: XYZ | ||
axisA?: XYZ | ||
axisB?: XYZ | ||
} | ||
) => this.hinge(body, targetBody, config), | ||
coneTwist: (body: PhysicsBody, targetPivot: XYZ) => this.coneTwist(body, targetPivot), | ||
pointToPoint: ( | ||
slider: ( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
config: { | ||
pivot?: XYZ | ||
targetPivot?: XYZ | ||
frameA?: XYZ | ||
frameB?: XYZ | ||
linearLowerLimit?: number | ||
linearUpperLimit?: number | ||
angularLowerLimit?: number | ||
angularUpperLimit?: number | ||
} = {} | ||
) => this.slider(body, targetBody, config), | ||
spring: ( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
config: { | ||
stiffness?: number | ||
damping?: number | ||
angularLock?: boolean | ||
linearLowerLimit?: XYZ | ||
linearUpperLimit?: XYZ | ||
} = {} | ||
) => this.spring(body, targetBody, config), | ||
coneTwist: (bodyA: PhysicsBody, bodyB: PhysicsBody, frameA: XYZ = {}, frameB: XYZ = {}) => | ||
this.coneTwist(bodyA, bodyB, frameA, frameB), | ||
dof: ( | ||
bodyA: PhysicsBody, | ||
bodyB: PhysicsBody, | ||
config?: { | ||
linearLowerLimit?: XYZ | ||
linearUpperLimit?: XYZ | ||
angularLowerLimit?: XYZ | ||
angularUpperLimit?: XYZ | ||
center?: boolean | ||
offset?: XYZ | ||
} | ||
) => this.pointToPoint(body, targetBody, config) | ||
) => this.dof(bodyA, bodyB, config) | ||
} | ||
} | ||
private getTransform(body: Ammo.btRigidBody, targetBody: Ammo.btRigidBody) { | ||
const bodyTransform = body.getCenterOfMassTransform().inverse().op_mul(targetBody.getWorldTransform()) | ||
const targetTransform = new Ammo.btTransform() | ||
targetTransform.setIdentity() | ||
return { body: bodyTransform, target: targetTransform } | ||
private getTransform( | ||
bodyA: Ammo.btRigidBody, | ||
bodyB: Ammo.btRigidBody, | ||
offset: { x: number; y: number; z: number } = { x: 0, y: 0, z: 0 }, | ||
center: boolean = false | ||
) { | ||
offset = { x: 0, y: 0, z: 0, ...offset } | ||
const centerVector = (v1: Ammo.btVector3, v2: Ammo.btVector3) => { | ||
var dx = (v1.x() - v2.x()) / 2 + offset.x | ||
var dy = (v1.y() - v2.y()) / 2 + offset.y | ||
var dz = (v1.z() - v2.z()) / 2 + offset.z | ||
return new Ammo.btVector3(dx, dy, dz) | ||
} | ||
const transformB = new Ammo.btTransform() | ||
transformB.setIdentity() | ||
if (!center) { | ||
// offset | ||
transformB.setOrigin(new Ammo.btVector3(offset.x, offset.y, offset.z)) | ||
const transformA = bodyA | ||
.getCenterOfMassTransform() | ||
.inverse() | ||
.op_mul(bodyB.getWorldTransform()) | ||
.op_mul(transformB) | ||
return { transformA: transformA, transformB: transformB } | ||
} else { | ||
const center = centerVector(bodyA.getWorldTransform().getOrigin(), bodyB.getWorldTransform().getOrigin()) | ||
const transformB = new Ammo.btTransform() | ||
transformB.setIdentity() | ||
transformB.setOrigin(center) | ||
const transformA = bodyA | ||
.getCenterOfMassTransform() | ||
.inverse() | ||
.op_mul(bodyB.getWorldTransform()) | ||
transformA.op_mul(transformB) | ||
return { transformA: transformA, transformB: transformB } | ||
} | ||
} | ||
private lock(body: PhysicsBody, targetBody: PhysicsBody) { | ||
const transform = this.getTransform(body.ammo, targetBody.ammo) | ||
const constraint = new Ammo.btGeneric6DofConstraint( | ||
private lock(bodyA: PhysicsBody, bodyB: PhysicsBody) { | ||
const zero = { x: 0, y: 0, z: 0 } | ||
return this.dof(bodyA, bodyB, { angularLowerLimit: zero, angularUpperLimit: zero }) | ||
} | ||
private fixed(bodyA: PhysicsBody, bodyB: PhysicsBody) { | ||
const transform = this.getTransform(bodyA.ammo, bodyB.ammo) | ||
transform.transformA.setRotation(bodyA.ammo.getWorldTransform().getRotation()) | ||
transform.transformB.setRotation(bodyB.ammo.getWorldTransform().getRotation()) | ||
const constraint = new Ammo.btFixedConstraint(bodyA.ammo, bodyB.ammo, transform.transformA, transform.transformB) | ||
this.physicsWorld.addConstraint(constraint) | ||
return constraint | ||
} | ||
private pointToPoint( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
config: { | ||
pivotA?: XYZ | ||
pivotB?: XYZ | ||
} = {} | ||
) { | ||
const { pivotA, pivotB } = config | ||
const pivotV3 = new Ammo.btVector3(pivotA?.x || 0, pivotA?.y || 0, pivotA?.z || 0) | ||
const targetPivotV3 = new Ammo.btVector3(pivotB?.x || 0, pivotB?.y || 0, pivotB?.z || 0) | ||
const constraint = new Ammo.btPoint2PointConstraint(body.ammo, targetBody.ammo, pivotV3, targetPivotV3) | ||
this.physicsWorld.addConstraint(constraint) | ||
return constraint | ||
} | ||
private hinge( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
config: { | ||
pivotA?: XYZ | ||
pivotB?: XYZ | ||
axisA?: XYZ | ||
axisB?: XYZ | ||
} = {} | ||
) { | ||
const { pivotA, pivotB, axisA, axisB } = config | ||
const pivotV3 = new Ammo.btVector3(pivotA?.x || 0, pivotA?.y || 0, pivotA?.z || 0) | ||
const targetPivotV3 = new Ammo.btVector3(pivotB?.x || 0, pivotB?.y || 0, pivotB?.z || 0) | ||
const axisV3 = new Ammo.btVector3(axisA?.x || 0, axisA?.y || 0, axisA?.z || 0) | ||
const targetAxisV3 = new Ammo.btVector3(axisB?.x || 0, axisB?.y || 0, axisB?.z || 0) | ||
const constraint = new Ammo.btHingeConstraint( | ||
body.ammo, | ||
targetBody.ammo, | ||
transform.body, | ||
transform.target, | ||
pivotV3, | ||
targetPivotV3, | ||
axisV3, | ||
targetAxisV3, | ||
true | ||
) | ||
const zero = new Ammo.btVector3(0, 0, 0) | ||
//TODO: allow these to be configurable | ||
constraint.setLinearLowerLimit(zero) | ||
constraint.setLinearUpperLimit(zero) | ||
constraint.setAngularLowerLimit(zero) | ||
constraint.setAngularUpperLimit(zero) | ||
this.physicsWorld.addConstraint(constraint) | ||
return constraint | ||
} | ||
private fixed(body: PhysicsBody, targetBody: PhysicsBody) { | ||
const transform = this.getTransform(body.ammo, targetBody.ammo) | ||
transform.body.setRotation(body.ammo.getWorldTransform().getRotation()) | ||
transform.target.setRotation(targetBody.ammo.getWorldTransform().getRotation()) | ||
const constraint = new Ammo.btFixedConstraint(body.ammo, targetBody.ammo, transform.body, transform.target) | ||
// https://pybullet.org/Bullet/phpBB3/viewtopic.php?f=9&t=12690&p=42152&hilit=btSliderConstraint#p42152 | ||
private slider( | ||
bodyA: PhysicsBody, | ||
bodyB: PhysicsBody, | ||
config: { | ||
frameA?: XYZ | ||
frameB?: XYZ | ||
linearLowerLimit?: number | ||
linearUpperLimit?: number | ||
angularLowerLimit?: number | ||
angularUpperLimit?: number | ||
} = {} | ||
) { | ||
const transform = this.getTransform(bodyA.ammo, bodyB.ammo) | ||
const { | ||
frameA = {}, | ||
frameB = {}, | ||
linearLowerLimit: lll = 0, | ||
linearUpperLimit: lul = 0, | ||
angularLowerLimit: all = 0, | ||
angularUpperLimit: aul = 0 | ||
} = config | ||
const rotationA = transform.transformA.getRotation() | ||
rotationA.setEulerZYX(frameA.x || 0, frameA.y || 0, frameA.z || 0) | ||
transform.transformA.setRotation(rotationA) | ||
const rotationB = transform.transformB.getRotation() | ||
rotationB.setEulerZYX(frameB.x || 0, frameB.y || 0, frameB.z || 0) | ||
transform.transformB.setRotation(rotationB) | ||
const constraint = new Ammo.btSliderConstraint( | ||
bodyA.ammo, | ||
bodyB.ammo, | ||
transform.transformA, | ||
transform.transformB, | ||
true | ||
) | ||
constraint.setLowerLinLimit(lll) | ||
constraint.setUpperLinLimit(lul) | ||
constraint.setLowerAngLimit(all) | ||
constraint.setUpperAngLimit(aul) | ||
this.physicsWorld.addConstraint(constraint) | ||
return constraint | ||
} | ||
@@ -97,5 +256,13 @@ | ||
angularLock?: boolean | ||
linearLowerLimit?: XYZ | ||
linearUpperLimit?: XYZ | ||
} = {} | ||
) { | ||
const { stiffness = 50, damping = 0.01, angularLock = false } = config | ||
const { | ||
stiffness = 50, | ||
damping = 0.01, | ||
angularLock = false, | ||
linearLowerLimit: lll = {}, | ||
linearUpperLimit: lul = {} | ||
} = config | ||
@@ -106,13 +273,17 @@ const transform = this.getTransform(body.ammo, targetBody.ammo) | ||
targetBody.ammo, | ||
transform.body, | ||
transform.target, | ||
transform.transformA, | ||
transform.transformB, | ||
true | ||
) | ||
constraint.setLinearLowerLimit(new Ammo.btVector3(-100, -100, -100)) | ||
constraint.setLinearUpperLimit(new Ammo.btVector3(100, 100, 100)) | ||
this.tmpBtVector3.setValue(lll.x || 0, lll.y || 0, lll.z || 0) | ||
constraint.setLinearLowerLimit(this.tmpBtVector3) | ||
this.tmpBtVector3.setValue(lul.x || 0, lul.y || 0, lul.z || 0) | ||
constraint.setLinearUpperLimit(this.tmpBtVector3) | ||
if (angularLock) { | ||
constraint.setAngularLowerLimit(new Ammo.btVector3(0, 0, 0)) | ||
constraint.setAngularUpperLimit(new Ammo.btVector3(0, 0, 0)) | ||
this.tmpBtVector3.setValue(0, 0, 0) | ||
constraint.setAngularLowerLimit(this.tmpBtVector3) | ||
constraint.setAngularUpperLimit(this.tmpBtVector3) | ||
} | ||
@@ -125,67 +296,80 @@ | ||
} | ||
// I have no idea what setEquilibriumPoint does :/ | ||
// constraint.setEquilibriumPoint() | ||
this.physicsWorld.addConstraint(constraint) | ||
return constraint | ||
} | ||
private slider(body: PhysicsBody, targetBody: PhysicsBody) { | ||
const transform = this.getTransform(body.ammo, targetBody.ammo) | ||
//TODO: support setting linear and angular limits | ||
const constraint = new Ammo.btSliderConstraint(body.ammo, targetBody.ammo, transform.body, transform.target, true) | ||
constraint.setLowerLinLimit(-1) | ||
constraint.setUpperLinLimit(1) | ||
// constraint.setLowerAngLimit(); | ||
// constraint.setUpperAngLimit(); | ||
private coneTwist(bodyA: PhysicsBody, bodyB: PhysicsBody, frameA: XYZ = {}, frameB: XYZ = {}) { | ||
const rbAFrame = new Ammo.btTransform() | ||
rbAFrame.setIdentity() | ||
rbAFrame.getOrigin().setValue(frameA?.x || 0, frameA?.y || 0, frameA?.z || 0) | ||
const rbBFrame = new Ammo.btTransform() | ||
rbBFrame.setIdentity() | ||
rbBFrame.getOrigin().setValue(frameB?.x || 0, frameB?.y || 0, frameB?.z || 0) | ||
const t = this.getTransform(bodyA.ammo, bodyB.ammo) | ||
const constraint = new Ammo.btConeTwistConstraint(bodyB.ammo, bodyA.ammo, rbAFrame, rbBFrame) | ||
// does not work at all :/ | ||
// constraint.setLimit(-Math.PI / 50, Math.PI / 50) | ||
constraint.setAngularOnly(true) | ||
this.physicsWorld.addConstraint(constraint) | ||
return constraint | ||
} | ||
private hinge( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
private dof( | ||
bodyA: PhysicsBody, | ||
bodyB: PhysicsBody, | ||
config: { | ||
pivot?: XYZ | ||
targetPivot?: XYZ | ||
axis?: XYZ | ||
targetAxis?: XYZ | ||
linearLowerLimit?: XYZ | ||
linearUpperLimit?: XYZ | ||
angularLowerLimit?: XYZ | ||
angularUpperLimit?: XYZ | ||
center?: boolean | ||
offset?: XYZ | ||
} = {} | ||
) { | ||
const { pivot, targetPivot, axis, targetAxis } = config | ||
const pivotV3 = new Ammo.btVector3(pivot?.x || 0, pivot?.y || 0, pivot?.z || 0) | ||
const targetPivotV3 = new Ammo.btVector3(targetPivot?.x || 0, targetPivot?.y || 0, targetPivot?.z || 0) | ||
const axisV3 = new Ammo.btVector3(axis?.x || 0, axis?.y || 0, axis?.z || 1) | ||
const targetAxisV3 = new Ammo.btVector3(targetAxis?.x || 0, targetAxis?.y || 0, targetAxis?.z || 1) | ||
const constraint = new Ammo.btHingeConstraint( | ||
body.ammo, | ||
targetBody.ammo, | ||
pivotV3, | ||
targetPivotV3, | ||
axisV3, | ||
targetAxisV3, | ||
const { offset, center = false } = config | ||
const off = { x: 0, y: 0, z: 0, ...offset } | ||
const transform = this.getTransform(bodyA.ammo, bodyB.ammo, off, center) | ||
const constraint = new Ammo.btGeneric6DofConstraint( | ||
bodyA.ammo, | ||
bodyB.ammo, | ||
transform.transformA, | ||
transform.transformB, | ||
true | ||
) | ||
this.physicsWorld.addConstraint(constraint) | ||
} | ||
private coneTwist(body: PhysicsBody, targetPivot: XYZ = {}) { | ||
const pivotTransform = new Ammo.btTransform() | ||
pivotTransform.setIdentity() | ||
pivotTransform.getOrigin().setValue(targetPivot?.x || 0, targetPivot?.y || 0, targetPivot?.z || 0) | ||
const constraint = new Ammo.btConeTwistConstraint(body.ammo, pivotTransform) | ||
this.physicsWorld.addConstraint(constraint) | ||
} | ||
const { linearLowerLimit, linearUpperLimit, angularLowerLimit, angularUpperLimit } = config | ||
private pointToPoint( | ||
body: PhysicsBody, | ||
targetBody: PhysicsBody, | ||
config: { | ||
pivot?: XYZ | ||
targetPivot?: XYZ | ||
} = {} | ||
) { | ||
const { pivot, targetPivot } = config | ||
const pivotV3 = new Ammo.btVector3(pivot?.x || 0, pivot?.y || 0, pivot?.z || 0) | ||
const targetPivotV3 = new Ammo.btVector3(targetPivot?.x || 0, targetPivot?.y || 0, targetPivot?.z || 0) | ||
const constraint = new Ammo.btPoint2PointConstraint(body.ammo, targetBody.ammo, pivotV3, targetPivotV3) | ||
this.physicsWorld.addConstraint(constraint) | ||
const lll = this.toAmmoV3(linearLowerLimit) | ||
const lul = this.toAmmoV3(linearUpperLimit) | ||
const all = this.toAmmoV3(angularLowerLimit, -Math.PI) | ||
const aul = this.toAmmoV3(angularUpperLimit, Math.PI) | ||
constraint.setLinearLowerLimit(lll) | ||
constraint.setLinearUpperLimit(lul) | ||
constraint.setAngularLowerLimit(all) | ||
constraint.setAngularUpperLimit(aul) | ||
Ammo.destroy(lll) | ||
Ammo.destroy(lul) | ||
Ammo.destroy(all) | ||
Ammo.destroy(aul) | ||
this.physicsWorld.addConstraint(constraint, false) | ||
return constraint | ||
} | ||
} |
@@ -8,3 +8,3 @@ /** | ||
import logger from '@enable3d/common/dist/logger' | ||
import PhysicsBody from './physicsBody' | ||
import PhysicsBody from '@enable3d/common/dist/physicsBody' | ||
import { | ||
@@ -41,2 +41,4 @@ PlaneConfig, | ||
import * as Types from '@enable3d/common/dist/types' | ||
import { ClosestRaycaster, AllHitsRaycaster } from './raycaster/raycaster' | ||
export { ClosestRaycaster, AllHitsRaycaster } | ||
export { Types } | ||
@@ -156,3 +158,11 @@ | ||
extrude: (extrudeConfig: ExtrudeConfig, materialConfig: MaterialConfig = {}) => | ||
this.addExtrude(extrudeConfig, materialConfig) | ||
this.addExtrude(extrudeConfig, materialConfig), | ||
/** | ||
* Creates a new Raycaster | ||
* @param type Returns only the closes body by default. Can be 'closest' or 'allHits'. | ||
*/ | ||
raycaster: (type = 'closest') => { | ||
if (type === 'closest') return new ClosestRaycaster(this) as ClosestRaycaster | ||
else return new AllHitsRaycaster(this) as AllHitsRaycaster | ||
} | ||
} | ||
@@ -159,0 +169,0 @@ } |
@@ -13,3 +13,3 @@ /** | ||
import DefaultMaterial from '@enable3d/common/dist/defaultMaterial' | ||
import PhysicsBody from './physicsBody' | ||
import PhysicsBody from '@enable3d/common/dist/physicsBody' | ||
@@ -178,51 +178,49 @@ class Physics extends EventEmitter { | ||
*/ | ||
if (this.scene !== 'headless') { | ||
for (var i = 0, il = this.rigidBodies.length; i < il; i++) { | ||
var objThree = this.rigidBodies[i] | ||
var objPhys = objThree.body.ammo | ||
var ms = objPhys.getMotionState() | ||
for (var i = 0, il = this.rigidBodies.length; i < il; i++) { | ||
var objThree = this.rigidBodies[i] | ||
var objPhys = objThree.body.ammo | ||
var ms = objPhys.getMotionState() | ||
if (ms) { | ||
ms.getWorldTransform(this.tmpTrans) | ||
if (ms) { | ||
ms.getWorldTransform(this.tmpTrans) | ||
// check if object did an update since last call | ||
if (objThree.body.didUpdate) { | ||
// @ts-ignore | ||
if (objThree.body._emitUpdateEvents) objThree.body.eventEmitter.emit('update') | ||
objThree.body.didUpdate = false | ||
} | ||
// check if object did an update since last call | ||
if (objThree.body.didUpdate) { | ||
// @ts-ignore | ||
if (objThree.body._emitUpdateEvents) objThree.body.eventEmitter.emit('update') | ||
objThree.body.didUpdate = false | ||
} | ||
// update positions | ||
if (objThree.body.ammo.isKinematicObject() && objThree.body.needUpdate) { | ||
// get position and rotation | ||
objThree.getWorldQuaternion(this.tmpQuaternion) | ||
objThree.getWorldPosition(this.tmpVector3) | ||
// adjust tmp variables | ||
this.tmpBtVector3.setValue(this.tmpVector3.x, this.tmpVector3.y, this.tmpVector3.z) | ||
this.tmpBtQuaternion.setValue( | ||
this.tmpQuaternion.x, | ||
this.tmpQuaternion.y, | ||
this.tmpQuaternion.z, | ||
this.tmpQuaternion.w | ||
) | ||
// set position and rotation | ||
this.tmpTrans.setOrigin(this.tmpBtVector3) | ||
this.tmpTrans.setRotation(this.tmpBtQuaternion) | ||
// set transform | ||
ms.setWorldTransform(this.tmpTrans) | ||
// reset needsUpdate | ||
objThree.body.needUpdate = false | ||
} else { | ||
// get position and rotation | ||
let p = this.tmpTrans.getOrigin() | ||
let q = this.tmpTrans.getRotation() | ||
// body offset | ||
let o = objThree.body.offset | ||
// set position and rotation | ||
objThree.position.set(p.x() + o.x, p.y() + o.y, p.z() + o.z) | ||
objThree.quaternion.set(q.x(), q.y(), q.z(), q.w()) | ||
} | ||
// update positions | ||
if (objThree.body.ammo.isKinematicObject() && objThree.body.needUpdate) { | ||
// get position and rotation | ||
objThree.getWorldQuaternion(this.tmpQuaternion) | ||
objThree.getWorldPosition(this.tmpVector3) | ||
// adjust tmp variables | ||
this.tmpBtVector3.setValue(this.tmpVector3.x, this.tmpVector3.y, this.tmpVector3.z) | ||
this.tmpBtQuaternion.setValue( | ||
this.tmpQuaternion.x, | ||
this.tmpQuaternion.y, | ||
this.tmpQuaternion.z, | ||
this.tmpQuaternion.w | ||
) | ||
// set position and rotation | ||
this.tmpTrans.setOrigin(this.tmpBtVector3) | ||
this.tmpTrans.setRotation(this.tmpBtQuaternion) | ||
// set transform | ||
ms.setWorldTransform(this.tmpTrans) | ||
// reset needsUpdate | ||
objThree.body.needUpdate = false | ||
} else { | ||
// get position and rotation | ||
let p = this.tmpTrans.getOrigin() | ||
let q = this.tmpTrans.getRotation() | ||
// body offset | ||
let o = objThree.body.offset | ||
// set position and rotation | ||
objThree.position.set(p.x() + o.x, p.y() + o.y, p.z() + o.z) | ||
objThree.quaternion.set(q.x(), q.y(), q.z(), q.w()) | ||
} | ||
objThree.body.collided = false | ||
} | ||
objThree.body.collided = false | ||
} | ||
@@ -229,0 +227,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3523365
79
16156
+ Added@enable3d/common@0.17.0(transitive)
+ Added@enable3d/three-wrapper@0.17.0(transitive)
- Removed@enable3d/common@0.0.16(transitive)
- Removed@enable3d/three-wrapper@0.0.16(transitive)
Updated@enable3d/common@^0.17.0