4505 lines
486 KiB
JavaScript
4505 lines
486 KiB
JavaScript
|
(function (global, factory) {
|
||
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three'), require('whs')) :
|
||
|
typeof define === 'function' && define.amd ? define(['exports', 'three', 'whs'], factory) :
|
||
|
(factory((global.PHYSICS = {}),global.THREE,global.WHS));
|
||
|
}(this, (function (exports,three,whs) { 'use strict';
|
||
|
|
||
|
var MESSAGE_TYPES = {
|
||
|
WORLDREPORT: 0,
|
||
|
COLLISIONREPORT: 1,
|
||
|
VEHICLEREPORT: 2,
|
||
|
CONSTRAINTREPORT: 3,
|
||
|
SOFTREPORT: 4
|
||
|
};
|
||
|
|
||
|
var REPORT_ITEMSIZE = 14,
|
||
|
COLLISIONREPORT_ITEMSIZE = 5,
|
||
|
VEHICLEREPORT_ITEMSIZE = 9,
|
||
|
CONSTRAINTREPORT_ITEMSIZE = 6;
|
||
|
|
||
|
var temp1Vector3 = new three.Vector3(),
|
||
|
temp2Vector3 = new three.Vector3(),
|
||
|
temp1Matrix4 = new three.Matrix4(),
|
||
|
temp1Quat = new three.Quaternion();
|
||
|
|
||
|
var getEulerXYZFromQuaternion = function getEulerXYZFromQuaternion(x, y, z, w) {
|
||
|
return new three.Vector3(Math.atan2(2 * (x * w - y * z), w * w - x * x - y * y + z * z), Math.asin(2 * (x * z + y * w)), Math.atan2(2 * (z * w - x * y), w * w + x * x - y * y - z * z));
|
||
|
};
|
||
|
|
||
|
var getQuatertionFromEuler = function getQuatertionFromEuler(x, y, z) {
|
||
|
var c1 = Math.cos(y);
|
||
|
var s1 = Math.sin(y);
|
||
|
var c2 = Math.cos(-z);
|
||
|
var s2 = Math.sin(-z);
|
||
|
var c3 = Math.cos(x);
|
||
|
var s3 = Math.sin(x);
|
||
|
var c1c2 = c1 * c2;
|
||
|
var s1s2 = s1 * s2;
|
||
|
|
||
|
return {
|
||
|
w: c1c2 * c3 - s1s2 * s3,
|
||
|
x: c1c2 * s3 + s1s2 * c3,
|
||
|
y: s1 * c2 * c3 + c1 * s2 * s3,
|
||
|
z: c1 * s2 * c3 - s1 * c2 * s3
|
||
|
};
|
||
|
};
|
||
|
|
||
|
var convertWorldPositionToObject = function convertWorldPositionToObject(position, object) {
|
||
|
temp1Matrix4.identity(); // reset temp matrix
|
||
|
|
||
|
// Set the temp matrix's rotation to the object's rotation
|
||
|
temp1Matrix4.identity().makeRotationFromQuaternion(object.quaternion);
|
||
|
|
||
|
// Invert rotation matrix in order to "unrotate" a point back to object space
|
||
|
temp1Matrix4.getInverse(temp1Matrix4);
|
||
|
|
||
|
// Yay! Temp vars!
|
||
|
temp1Vector3.copy(position);
|
||
|
temp2Vector3.copy(object.position);
|
||
|
|
||
|
// Apply the rotation
|
||
|
return temp1Vector3.sub(temp2Vector3).applyMatrix4(temp1Matrix4);
|
||
|
};
|
||
|
|
||
|
var addObjectChildren = function addObjectChildren(parent, object) {
|
||
|
for (var i = 0; i < object.children.length; i++) {
|
||
|
var child = object.children[i];
|
||
|
var physics = child.component ? child.component.use('physics') : false;
|
||
|
|
||
|
if (physics) {
|
||
|
var data = physics.data;
|
||
|
|
||
|
child.updateMatrix();
|
||
|
child.updateMatrixWorld();
|
||
|
|
||
|
temp1Vector3.setFromMatrixPosition(child.matrixWorld);
|
||
|
temp1Quat.setFromRotationMatrix(child.matrixWorld);
|
||
|
|
||
|
data.position_offset = {
|
||
|
x: temp1Vector3.x,
|
||
|
y: temp1Vector3.y,
|
||
|
z: temp1Vector3.z
|
||
|
};
|
||
|
|
||
|
data.rotation = {
|
||
|
x: temp1Quat.x,
|
||
|
y: temp1Quat.y,
|
||
|
z: temp1Quat.z,
|
||
|
w: temp1Quat.w
|
||
|
};
|
||
|
|
||
|
parent.component.use('physics').data.children.push(data);
|
||
|
}
|
||
|
|
||
|
addObjectChildren(parent, child);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var classCallCheck = function (instance, Constructor) {
|
||
|
if (!(instance instanceof Constructor)) {
|
||
|
throw new TypeError("Cannot call a class as a function");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var createClass = function () {
|
||
|
function defineProperties(target, props) {
|
||
|
for (var i = 0; i < props.length; i++) {
|
||
|
var descriptor = props[i];
|
||
|
descriptor.enumerable = descriptor.enumerable || false;
|
||
|
descriptor.configurable = true;
|
||
|
if ("value" in descriptor) descriptor.writable = true;
|
||
|
Object.defineProperty(target, descriptor.key, descriptor);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return function (Constructor, protoProps, staticProps) {
|
||
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
||
|
if (staticProps) defineProperties(Constructor, staticProps);
|
||
|
return Constructor;
|
||
|
};
|
||
|
}();
|
||
|
|
||
|
var _extends = Object.assign || function (target) {
|
||
|
for (var i = 1; i < arguments.length; i++) {
|
||
|
var source = arguments[i];
|
||
|
|
||
|
for (var key in source) {
|
||
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||
|
target[key] = source[key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return target;
|
||
|
};
|
||
|
|
||
|
var inherits = function (subClass, superClass) {
|
||
|
if (typeof superClass !== "function" && superClass !== null) {
|
||
|
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
|
||
|
}
|
||
|
|
||
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
||
|
constructor: {
|
||
|
value: subClass,
|
||
|
enumerable: false,
|
||
|
writable: true,
|
||
|
configurable: true
|
||
|
}
|
||
|
});
|
||
|
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
||
|
};
|
||
|
|
||
|
var possibleConstructorReturn = function (self, call) {
|
||
|
if (!self) {
|
||
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||
|
}
|
||
|
|
||
|
return call && (typeof call === "object" || typeof call === "function") ? call : self;
|
||
|
};
|
||
|
|
||
|
var toConsumableArray = function (arr) {
|
||
|
if (Array.isArray(arr)) {
|
||
|
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
|
||
|
|
||
|
return arr2;
|
||
|
} else {
|
||
|
return Array.from(arr);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var Eventable = function () {
|
||
|
function Eventable() {
|
||
|
classCallCheck(this, Eventable);
|
||
|
|
||
|
this._eventListeners = {};
|
||
|
}
|
||
|
|
||
|
createClass(Eventable, [{
|
||
|
key: "addEventListener",
|
||
|
value: function addEventListener(event_name, callback) {
|
||
|
if (!this._eventListeners.hasOwnProperty(event_name)) this._eventListeners[event_name] = [];
|
||
|
|
||
|
this._eventListeners[event_name].push(callback);
|
||
|
}
|
||
|
}, {
|
||
|
key: "removeEventListener",
|
||
|
value: function removeEventListener(event_name, callback) {
|
||
|
var index = void 0;
|
||
|
|
||
|
if (!this._eventListeners.hasOwnProperty(event_name)) return false;
|
||
|
|
||
|
if ((index = this._eventListeners[event_name].indexOf(callback)) >= 0) {
|
||
|
this._eventListeners[event_name].splice(index, 1);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}, {
|
||
|
key: "dispatchEvent",
|
||
|
value: function dispatchEvent(event_name) {
|
||
|
var i = void 0;
|
||
|
var parameters = Array.prototype.splice.call(arguments, 1);
|
||
|
|
||
|
if (this._eventListeners.hasOwnProperty(event_name)) {
|
||
|
for (i = 0; i < this._eventListeners[event_name].length; i++) {
|
||
|
this._eventListeners[event_name][i].apply(this, parameters);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}], [{
|
||
|
key: "make",
|
||
|
value: function make(obj) {
|
||
|
obj.prototype.addEventListener = Eventable.prototype.addEventListener;
|
||
|
obj.prototype.removeEventListener = Eventable.prototype.removeEventListener;
|
||
|
obj.prototype.dispatchEvent = Eventable.prototype.dispatchEvent;
|
||
|
}
|
||
|
}]);
|
||
|
return Eventable;
|
||
|
}();
|
||
|
|
||
|
var ConeTwistConstraint = function () {
|
||
|
function ConeTwistConstraint(obja, objb, position) {
|
||
|
classCallCheck(this, ConeTwistConstraint);
|
||
|
|
||
|
var objecta = obja;
|
||
|
var objectb = obja;
|
||
|
|
||
|
if (position === undefined) console.error('Both objects must be defined in a ConeTwistConstraint.');
|
||
|
|
||
|
this.type = 'conetwist';
|
||
|
this.appliedImpulse = 0;
|
||
|
this.worldModule = null; // Will be redefined by .addConstraint
|
||
|
this.objecta = objecta.use('physics').data.id;
|
||
|
this.positiona = convertWorldPositionToObject(position, objecta).clone();
|
||
|
this.objectb = objectb.use('physics').data.id;
|
||
|
this.positionb = convertWorldPositionToObject(position, objectb).clone();
|
||
|
this.axisa = { x: objecta.rotation.x, y: objecta.rotation.y, z: objecta.rotation.z };
|
||
|
this.axisb = { x: objectb.rotation.x, y: objectb.rotation.y, z: objectb.rotation.z };
|
||
|
}
|
||
|
|
||
|
createClass(ConeTwistConstraint, [{
|
||
|
key: 'getDefinition',
|
||
|
value: function getDefinition() {
|
||
|
return {
|
||
|
type: this.type,
|
||
|
id: this.id,
|
||
|
objecta: this.objecta,
|
||
|
objectb: this.objectb,
|
||
|
positiona: this.positiona,
|
||
|
positionb: this.positionb,
|
||
|
axisa: this.axisa,
|
||
|
axisb: this.axisb
|
||
|
};
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLimit',
|
||
|
value: function setLimit(x, y, z) {
|
||
|
if (this.worldModule) this.worldModule.execute('conetwist_setLimit', { constraint: this.id, x: x, y: y, z: z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'enableMotor',
|
||
|
value: function enableMotor() {
|
||
|
if (this.worldModule) this.worldModule.execute('conetwist_enableMotor', { constraint: this.id });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setMaxMotorImpulse',
|
||
|
value: function setMaxMotorImpulse(max_impulse) {
|
||
|
if (this.worldModule) this.worldModule.execute('conetwist_setMaxMotorImpulse', { constraint: this.id, max_impulse: max_impulse });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setMotorTarget',
|
||
|
value: function setMotorTarget(target) {
|
||
|
if (target instanceof three.Vector3) target = new three.Quaternion().setFromEuler(new three.Euler(target.x, target.y, target.z));else if (target instanceof three.Euler) target = new three.Quaternion().setFromEuler(target);else if (target instanceof three.Matrix4) target = new three.Quaternion().setFromRotationMatrix(target);
|
||
|
|
||
|
if (this.worldModule) this.worldModule.execute('conetwist_setMotorTarget', {
|
||
|
constraint: this.id,
|
||
|
x: target.x,
|
||
|
y: target.y,
|
||
|
z: target.z,
|
||
|
w: target.w
|
||
|
});
|
||
|
}
|
||
|
}]);
|
||
|
return ConeTwistConstraint;
|
||
|
}();
|
||
|
|
||
|
var HingeConstraint = function () {
|
||
|
function HingeConstraint(obja, objb, position, axis) {
|
||
|
classCallCheck(this, HingeConstraint);
|
||
|
|
||
|
var objecta = obja;
|
||
|
var objectb = objb;
|
||
|
|
||
|
if (axis === undefined) {
|
||
|
axis = position;
|
||
|
position = objectb;
|
||
|
objectb = undefined;
|
||
|
}
|
||
|
|
||
|
this.type = 'hinge';
|
||
|
this.appliedImpulse = 0;
|
||
|
this.worldModule = null; // Will be redefined by .addConstraint
|
||
|
this.objecta = objecta.use('physics').data.id;
|
||
|
this.positiona = convertWorldPositionToObject(position, objecta).clone();
|
||
|
this.position = position.clone();
|
||
|
this.axis = axis;
|
||
|
|
||
|
if (objectb) {
|
||
|
this.objectb = objectb.use('physics').data.id;
|
||
|
this.positionb = convertWorldPositionToObject(position, objectb).clone();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createClass(HingeConstraint, [{
|
||
|
key: 'getDefinition',
|
||
|
value: function getDefinition() {
|
||
|
return {
|
||
|
type: this.type,
|
||
|
id: this.id,
|
||
|
objecta: this.objecta,
|
||
|
objectb: this.objectb,
|
||
|
positiona: this.positiona,
|
||
|
positionb: this.positionb,
|
||
|
axis: this.axis
|
||
|
};
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLimits',
|
||
|
value: function setLimits(low, high, bias_factor, relaxation_factor) {
|
||
|
if (this.worldModule) this.worldModule.execute('hinge_setLimits', {
|
||
|
constraint: this.id,
|
||
|
low: low,
|
||
|
high: high,
|
||
|
bias_factor: bias_factor,
|
||
|
relaxation_factor: relaxation_factor
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'enableAngularMotor',
|
||
|
value: function enableAngularMotor(velocity, acceleration) {
|
||
|
if (this.worldModule) this.worldModule.execute('hinge_enableAngularMotor', {
|
||
|
constraint: this.id,
|
||
|
velocity: velocity,
|
||
|
acceleration: acceleration
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'disableMotor',
|
||
|
value: function disableMotor() {
|
||
|
if (this.worldModule) this.worldModule.execute('hinge_disableMotor', { constraint: this.id });
|
||
|
}
|
||
|
}]);
|
||
|
return HingeConstraint;
|
||
|
}();
|
||
|
|
||
|
var PointConstraint = function () {
|
||
|
function PointConstraint(obja, objb, position) {
|
||
|
classCallCheck(this, PointConstraint);
|
||
|
|
||
|
var objecta = obja;
|
||
|
var objectb = objb;
|
||
|
|
||
|
if (position === undefined) {
|
||
|
position = objectb;
|
||
|
objectb = undefined;
|
||
|
}
|
||
|
|
||
|
this.type = 'point';
|
||
|
this.appliedImpulse = 0;
|
||
|
this.objecta = objecta.use('physics').data.id;
|
||
|
this.positiona = convertWorldPositionToObject(position, objecta).clone();
|
||
|
|
||
|
if (objectb) {
|
||
|
this.objectb = objectb.use('physics').data.id;
|
||
|
this.positionb = convertWorldPositionToObject(position, objectb).clone();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createClass(PointConstraint, [{
|
||
|
key: 'getDefinition',
|
||
|
value: function getDefinition() {
|
||
|
return {
|
||
|
type: this.type,
|
||
|
id: this.id,
|
||
|
objecta: this.objecta,
|
||
|
objectb: this.objectb,
|
||
|
positiona: this.positiona,
|
||
|
positionb: this.positionb
|
||
|
};
|
||
|
}
|
||
|
}]);
|
||
|
return PointConstraint;
|
||
|
}();
|
||
|
|
||
|
var SliderConstraint = function () {
|
||
|
function SliderConstraint(obja, objb, position, axis) {
|
||
|
classCallCheck(this, SliderConstraint);
|
||
|
|
||
|
var objecta = obja;
|
||
|
var objectb = objb;
|
||
|
|
||
|
if (axis === undefined) {
|
||
|
axis = position;
|
||
|
position = objectb;
|
||
|
objectb = undefined;
|
||
|
}
|
||
|
|
||
|
this.type = 'slider';
|
||
|
this.appliedImpulse = 0;
|
||
|
this.worldModule = null; // Will be redefined by .addConstraint
|
||
|
this.objecta = objecta.use('physics').data.id;
|
||
|
this.positiona = convertWorldPositionToObject(position, objecta).clone();
|
||
|
this.axis = axis;
|
||
|
|
||
|
if (objectb) {
|
||
|
this.objectb = objectb.use('physics').data.id;
|
||
|
this.positionb = convertWorldPositionToObject(position, objectb).clone();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createClass(SliderConstraint, [{
|
||
|
key: 'getDefinition',
|
||
|
value: function getDefinition() {
|
||
|
return {
|
||
|
type: this.type,
|
||
|
id: this.id,
|
||
|
objecta: this.objecta,
|
||
|
objectb: this.objectb,
|
||
|
positiona: this.positiona,
|
||
|
positionb: this.positionb,
|
||
|
axis: this.axis
|
||
|
};
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLimits',
|
||
|
value: function setLimits(lin_lower, lin_upper, ang_lower, ang_upper) {
|
||
|
if (this.worldModule) this.worldModule.execute('slider_setLimits', {
|
||
|
constraint: this.id,
|
||
|
lin_lower: lin_lower,
|
||
|
lin_upper: lin_upper,
|
||
|
ang_lower: ang_lower,
|
||
|
ang_upper: ang_upper
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setRestitution',
|
||
|
value: function setRestitution(linear, angular) {
|
||
|
if (this.worldModule) this.worldModule.execute('slider_setRestitution', {
|
||
|
constraint: this.id,
|
||
|
linear: linear,
|
||
|
angular: angular
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'enableLinearMotor',
|
||
|
value: function enableLinearMotor(velocity, acceleration) {
|
||
|
if (this.worldModule) this.worldModule.execute('slider_enableLinearMotor', {
|
||
|
constraint: this.id,
|
||
|
velocity: velocity,
|
||
|
acceleration: acceleration
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'disableLinearMotor',
|
||
|
value: function disableLinearMotor() {
|
||
|
if (this.worldModule) this.worldModule.execute('slider_disableLinearMotor', { constraint: this.id });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'enableAngularMotor',
|
||
|
value: function enableAngularMotor(velocity, acceleration) {
|
||
|
this.scene.execute('slider_enableAngularMotor', {
|
||
|
constraint: this.id,
|
||
|
velocity: velocity,
|
||
|
acceleration: acceleration
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'disableAngularMotor',
|
||
|
value: function disableAngularMotor() {
|
||
|
if (this.worldModule) this.worldModule.execute('slider_disableAngularMotor', { constraint: this.id });
|
||
|
}
|
||
|
}]);
|
||
|
return SliderConstraint;
|
||
|
}();
|
||
|
|
||
|
var DOFConstraint = function () {
|
||
|
function DOFConstraint(obja, objb, position) {
|
||
|
classCallCheck(this, DOFConstraint);
|
||
|
|
||
|
var objecta = obja;
|
||
|
var objectb = objb;
|
||
|
|
||
|
if (position === undefined) {
|
||
|
position = objectb;
|
||
|
objectb = undefined;
|
||
|
}
|
||
|
|
||
|
this.type = 'dof';
|
||
|
this.appliedImpulse = 0;
|
||
|
this.worldModule = null; // Will be redefined by .addConstraint
|
||
|
this.objecta = objecta.use('physics').data.id;
|
||
|
this.positiona = convertWorldPositionToObject(position, objecta).clone();
|
||
|
this.axisa = { x: objecta.rotation.x, y: objecta.rotation.y, z: objecta.rotation.z };
|
||
|
|
||
|
if (objectb) {
|
||
|
this.objectb = objectb.use('physics').data.id;
|
||
|
this.positionb = convertWorldPositionToObject(position, objectb).clone();
|
||
|
this.axisb = { x: objectb.rotation.x, y: objectb.rotation.y, z: objectb.rotation.z };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createClass(DOFConstraint, [{
|
||
|
key: 'getDefinition',
|
||
|
value: function getDefinition() {
|
||
|
return {
|
||
|
type: this.type,
|
||
|
id: this.id,
|
||
|
objecta: this.objecta,
|
||
|
objectb: this.objectb,
|
||
|
positiona: this.positiona,
|
||
|
positionb: this.positionb,
|
||
|
axisa: this.axisa,
|
||
|
axisb: this.axisb
|
||
|
};
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLinearLowerLimit',
|
||
|
value: function setLinearLowerLimit(limit) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_setLinearLowerLimit', { constraint: this.id, x: limit.x, y: limit.y, z: limit.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLinearUpperLimit',
|
||
|
value: function setLinearUpperLimit(limit) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_setLinearUpperLimit', { constraint: this.id, x: limit.x, y: limit.y, z: limit.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setAngularLowerLimit',
|
||
|
value: function setAngularLowerLimit(limit) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_setAngularLowerLimit', { constraint: this.id, x: limit.x, y: limit.y, z: limit.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setAngularUpperLimit',
|
||
|
value: function setAngularUpperLimit(limit) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_setAngularUpperLimit', { constraint: this.id, x: limit.x, y: limit.y, z: limit.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'enableAngularMotor',
|
||
|
value: function enableAngularMotor(which) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_enableAngularMotor', { constraint: this.id, which: which });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'configureAngularMotor',
|
||
|
value: function configureAngularMotor(which, low_angle, high_angle, velocity, max_force) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_configureAngularMotor', { constraint: this.id, which: which, low_angle: low_angle, high_angle: high_angle, velocity: velocity, max_force: max_force });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'disableAngularMotor',
|
||
|
value: function disableAngularMotor(which) {
|
||
|
if (this.worldModule) this.worldModule.execute('dof_disableAngularMotor', { constraint: this.id, which: which });
|
||
|
}
|
||
|
}]);
|
||
|
return DOFConstraint;
|
||
|
}();
|
||
|
|
||
|
var Vehicle = function () {
|
||
|
function Vehicle(mesh) {
|
||
|
var tuning = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new VehicleTuning();
|
||
|
classCallCheck(this, Vehicle);
|
||
|
|
||
|
this.mesh = mesh;
|
||
|
this.wheels = [];
|
||
|
|
||
|
this._physijs = {
|
||
|
id: getObjectId(),
|
||
|
rigidBody: mesh._physijs.id,
|
||
|
suspension_stiffness: tuning.suspension_stiffness,
|
||
|
suspension_compression: tuning.suspension_compression,
|
||
|
suspension_damping: tuning.suspension_damping,
|
||
|
max_suspension_travel: tuning.max_suspension_travel,
|
||
|
friction_slip: tuning.friction_slip,
|
||
|
max_suspension_force: tuning.max_suspension_force
|
||
|
};
|
||
|
}
|
||
|
|
||
|
createClass(Vehicle, [{
|
||
|
key: 'addWheel',
|
||
|
value: function addWheel(wheel_geometry, wheel_material, connection_point, wheel_direction, wheel_axle, suspension_rest_length, wheel_radius, is_front_wheel, tuning) {
|
||
|
var wheel = new three.Mesh(wheel_geometry, wheel_material);
|
||
|
|
||
|
wheel.castShadow = wheel.receiveShadow = true;
|
||
|
wheel.position.copy(wheel_direction).multiplyScalar(suspension_rest_length / 100).add(connection_point);
|
||
|
|
||
|
this.world.add(wheel);
|
||
|
this.wheels.push(wheel);
|
||
|
|
||
|
this.world.execute('addWheel', {
|
||
|
id: this._physijs.id,
|
||
|
connection_point: { x: connection_point.x, y: connection_point.y, z: connection_point.z },
|
||
|
wheel_direction: { x: wheel_direction.x, y: wheel_direction.y, z: wheel_direction.z },
|
||
|
wheel_axle: { x: wheel_axle.x, y: wheel_axle.y, z: wheel_axle.z },
|
||
|
suspension_rest_length: suspension_rest_length,
|
||
|
wheel_radius: wheel_radius,
|
||
|
is_front_wheel: is_front_wheel,
|
||
|
tuning: tuning
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setSteering',
|
||
|
value: function setSteering(amount, wheel) {
|
||
|
if (wheel !== undefined && this.wheels[wheel] !== undefined) this.world.execute('setSteering', { id: this._physijs.id, wheel: wheel, steering: amount });else if (this.wheels.length > 0) {
|
||
|
for (var i = 0; i < this.wheels.length; i++) {
|
||
|
this.world.execute('setSteering', { id: this._physijs.id, wheel: i, steering: amount });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setBrake',
|
||
|
value: function setBrake(amount, wheel) {
|
||
|
if (wheel !== undefined && this.wheels[wheel] !== undefined) this.world.execute('setBrake', { id: this._physijs.id, wheel: wheel, brake: amount });else if (this.wheels.length > 0) {
|
||
|
for (var i = 0; i < this.wheels.length; i++) {
|
||
|
this.world.execute('setBrake', { id: this._physijs.id, wheel: i, brake: amount });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'applyEngineForce',
|
||
|
value: function applyEngineForce(amount, wheel) {
|
||
|
if (wheel !== undefined && this.wheels[wheel] !== undefined) this.world.execute('applyEngineForce', { id: this._physijs.id, wheel: wheel, force: amount });else if (this.wheels.length > 0) {
|
||
|
for (var i = 0; i < this.wheels.length; i++) {
|
||
|
this.world.execute('applyEngineForce', { id: this._physijs.id, wheel: i, force: amount });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}]);
|
||
|
return Vehicle;
|
||
|
}();
|
||
|
|
||
|
var _class, _temp2;
|
||
|
|
||
|
var WorldModuleBase = (_temp2 = _class = function (_Eventable) {
|
||
|
inherits(WorldModuleBase, _Eventable);
|
||
|
|
||
|
function WorldModuleBase(options) {
|
||
|
classCallCheck(this, WorldModuleBase);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (WorldModuleBase.__proto__ || Object.getPrototypeOf(WorldModuleBase)).call(this));
|
||
|
|
||
|
_this.bridge = {
|
||
|
onAdd: function onAdd(component, self) {
|
||
|
if (component.use('physics')) return self.defer(self.onAddCallback.bind(self), [component]);
|
||
|
return;
|
||
|
},
|
||
|
onRemove: function onRemove(component, self) {
|
||
|
if (component.use('physics')) return self.defer(self.onRemoveCallback.bind(self), [component]);
|
||
|
return;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
_this.options = Object.assign(WorldModuleBase.defaults, options);
|
||
|
|
||
|
_this.objects = {};
|
||
|
_this.vehicles = {};
|
||
|
_this.constraints = {};
|
||
|
_this.isSimulating = false;
|
||
|
|
||
|
_this.getObjectId = function () {
|
||
|
var id = 1;
|
||
|
return function () {
|
||
|
return id++;
|
||
|
};
|
||
|
}();
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
createClass(WorldModuleBase, [{
|
||
|
key: 'setup',
|
||
|
value: function setup() {
|
||
|
var _this2 = this;
|
||
|
|
||
|
this.receive(function (event) {
|
||
|
var _temp = void 0,
|
||
|
data = event.data;
|
||
|
|
||
|
if (data instanceof ArrayBuffer && data.byteLength !== 1) // byteLength === 1 is the worker making a SUPPORT_TRANSFERABLE test
|
||
|
data = new Float32Array(data);
|
||
|
|
||
|
if (data instanceof Float32Array) {
|
||
|
// transferable object
|
||
|
switch (data[0]) {
|
||
|
case MESSAGE_TYPES.WORLDREPORT:
|
||
|
_this2.updateScene(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.SOFTREPORT:
|
||
|
_this2.updateSoftbodies(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.COLLISIONREPORT:
|
||
|
_this2.updateCollisions(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.VEHICLEREPORT:
|
||
|
_this2.updateVehicles(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.CONSTRAINTREPORT:
|
||
|
_this2.updateConstraints(data);
|
||
|
break;
|
||
|
default:
|
||
|
}
|
||
|
} else if (data.cmd) {
|
||
|
// non-transferable object
|
||
|
switch (data.cmd) {
|
||
|
case 'objectReady':
|
||
|
_temp = data.params;
|
||
|
if (_this2.objects[_temp]) _this2.objects[_temp].dispatchEvent('ready');
|
||
|
break;
|
||
|
|
||
|
case 'worldReady':
|
||
|
_this2.dispatchEvent('ready');
|
||
|
break;
|
||
|
|
||
|
case 'ammoLoaded':
|
||
|
_this2.dispatchEvent('loaded');
|
||
|
// console.log("Physics loading time: " + (performance.now() - start) + "ms");
|
||
|
break;
|
||
|
|
||
|
case 'vehicle':
|
||
|
window.test = data;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
// Do nothing, just show the message
|
||
|
console.debug('Received: ' + data.cmd);
|
||
|
console.dir(data.params);
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
switch (data[0]) {
|
||
|
case MESSAGE_TYPES.WORLDREPORT:
|
||
|
_this2.updateScene(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.COLLISIONREPORT:
|
||
|
_this2.updateCollisions(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.VEHICLEREPORT:
|
||
|
_this2.updateVehicles(data);
|
||
|
break;
|
||
|
|
||
|
case MESSAGE_TYPES.CONSTRAINTREPORT:
|
||
|
_this2.updateConstraints(data);
|
||
|
break;
|
||
|
default:
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'updateScene',
|
||
|
value: function updateScene(info) {
|
||
|
var index = info[1];
|
||
|
|
||
|
while (index--) {
|
||
|
var offset = 2 + index * REPORT_ITEMSIZE;
|
||
|
var object = this.objects[info[offset]];
|
||
|
var component = object.component;
|
||
|
var data = component.use('physics').data;
|
||
|
|
||
|
if (object === null) continue;
|
||
|
|
||
|
if (component.__dirtyPosition === false) {
|
||
|
object.position.set(info[offset + 1], info[offset + 2], info[offset + 3]);
|
||
|
|
||
|
component.__dirtyPosition = false;
|
||
|
}
|
||
|
|
||
|
if (component.__dirtyRotation === false) {
|
||
|
object.quaternion.set(info[offset + 4], info[offset + 5], info[offset + 6], info[offset + 7]);
|
||
|
|
||
|
component.__dirtyRotation = false;
|
||
|
}
|
||
|
|
||
|
data.linearVelocity.set(info[offset + 8], info[offset + 9], info[offset + 10]);
|
||
|
|
||
|
data.angularVelocity.set(info[offset + 11], info[offset + 12], info[offset + 13]);
|
||
|
}
|
||
|
|
||
|
if (this.SUPPORT_TRANSFERABLE) this.send(info.buffer, [info.buffer]); // Give the typed array back to the worker
|
||
|
|
||
|
this.isSimulating = false;
|
||
|
this.dispatchEvent('update');
|
||
|
}
|
||
|
}, {
|
||
|
key: 'updateSoftbodies',
|
||
|
value: function updateSoftbodies(info) {
|
||
|
var index = info[1],
|
||
|
offset = 2;
|
||
|
|
||
|
while (index--) {
|
||
|
var size = info[offset + 1];
|
||
|
var object = this.objects[info[offset]];
|
||
|
|
||
|
if (object === null) continue;
|
||
|
|
||
|
var data = object.component.use('physics').data;
|
||
|
|
||
|
var attributes = object.geometry.attributes;
|
||
|
var volumePositions = attributes.position.array;
|
||
|
|
||
|
var offsetVert = offset + 2;
|
||
|
|
||
|
// console.log(data.id);
|
||
|
if (!data.isSoftBodyReset) {
|
||
|
object.position.set(0, 0, 0);
|
||
|
object.quaternion.set(0, 0, 0, 0);
|
||
|
|
||
|
data.isSoftBodyReset = true;
|
||
|
}
|
||
|
|
||
|
if (data.type === "softTrimesh") {
|
||
|
var volumeNormals = attributes.normal.array;
|
||
|
|
||
|
for (var i = 0; i < size; i++) {
|
||
|
var offs = offsetVert + i * 18;
|
||
|
|
||
|
var x1 = info[offs];
|
||
|
var y1 = info[offs + 1];
|
||
|
var z1 = info[offs + 2];
|
||
|
|
||
|
var nx1 = info[offs + 3];
|
||
|
var ny1 = info[offs + 4];
|
||
|
var nz1 = info[offs + 5];
|
||
|
|
||
|
var x2 = info[offs + 6];
|
||
|
var y2 = info[offs + 7];
|
||
|
var z2 = info[offs + 8];
|
||
|
|
||
|
var nx2 = info[offs + 9];
|
||
|
var ny2 = info[offs + 10];
|
||
|
var nz2 = info[offs + 11];
|
||
|
|
||
|
var x3 = info[offs + 12];
|
||
|
var y3 = info[offs + 13];
|
||
|
var z3 = info[offs + 14];
|
||
|
|
||
|
var nx3 = info[offs + 15];
|
||
|
var ny3 = info[offs + 16];
|
||
|
var nz3 = info[offs + 17];
|
||
|
|
||
|
var i9 = i * 9;
|
||
|
|
||
|
volumePositions[i9] = x1;
|
||
|
volumePositions[i9 + 1] = y1;
|
||
|
volumePositions[i9 + 2] = z1;
|
||
|
|
||
|
volumePositions[i9 + 3] = x2;
|
||
|
volumePositions[i9 + 4] = y2;
|
||
|
volumePositions[i9 + 5] = z2;
|
||
|
|
||
|
volumePositions[i9 + 6] = x3;
|
||
|
volumePositions[i9 + 7] = y3;
|
||
|
volumePositions[i9 + 8] = z3;
|
||
|
|
||
|
volumeNormals[i9] = nx1;
|
||
|
volumeNormals[i9 + 1] = ny1;
|
||
|
volumeNormals[i9 + 2] = nz1;
|
||
|
|
||
|
volumeNormals[i9 + 3] = nx2;
|
||
|
volumeNormals[i9 + 4] = ny2;
|
||
|
volumeNormals[i9 + 5] = nz2;
|
||
|
|
||
|
volumeNormals[i9 + 6] = nx3;
|
||
|
volumeNormals[i9 + 7] = ny3;
|
||
|
volumeNormals[i9 + 8] = nz3;
|
||
|
}
|
||
|
|
||
|
attributes.normal.needsUpdate = true;
|
||
|
offset += 2 + size * 18;
|
||
|
} else if (data.type === "softRopeMesh") {
|
||
|
for (var _i = 0; _i < size; _i++) {
|
||
|
var _offs = offsetVert + _i * 3;
|
||
|
|
||
|
var x = info[_offs];
|
||
|
var y = info[_offs + 1];
|
||
|
var z = info[_offs + 2];
|
||
|
|
||
|
volumePositions[_i * 3] = x;
|
||
|
volumePositions[_i * 3 + 1] = y;
|
||
|
volumePositions[_i * 3 + 2] = z;
|
||
|
}
|
||
|
|
||
|
offset += 2 + size * 3;
|
||
|
} else {
|
||
|
var _volumeNormals = attributes.normal.array;
|
||
|
|
||
|
for (var _i2 = 0; _i2 < size; _i2++) {
|
||
|
var _offs2 = offsetVert + _i2 * 6;
|
||
|
|
||
|
var _x = info[_offs2];
|
||
|
var _y = info[_offs2 + 1];
|
||
|
var _z = info[_offs2 + 2];
|
||
|
|
||
|
var nx = info[_offs2 + 3];
|
||
|
var ny = info[_offs2 + 4];
|
||
|
var nz = info[_offs2 + 5];
|
||
|
|
||
|
volumePositions[_i2 * 3] = _x;
|
||
|
volumePositions[_i2 * 3 + 1] = _y;
|
||
|
volumePositions[_i2 * 3 + 2] = _z;
|
||
|
|
||
|
// FIXME: Normals are pointed to look inside;
|
||
|
_volumeNormals[_i2 * 3] = nx;
|
||
|
_volumeNormals[_i2 * 3 + 1] = ny;
|
||
|
_volumeNormals[_i2 * 3 + 2] = nz;
|
||
|
}
|
||
|
|
||
|
attributes.normal.needsUpdate = true;
|
||
|
offset += 2 + size * 6;
|
||
|
}
|
||
|
|
||
|
attributes.position.needsUpdate = true;
|
||
|
}
|
||
|
|
||
|
// if (this.SUPPORT_TRANSFERABLE)
|
||
|
// this.send(info.buffer, [info.buffer]); // Give the typed array back to the worker
|
||
|
|
||
|
this.isSimulating = false;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'updateVehicles',
|
||
|
value: function updateVehicles(data) {
|
||
|
var vehicle = void 0,
|
||
|
wheel = void 0;
|
||
|
|
||
|
for (var i = 0; i < (data.length - 1) / VEHICLEREPORT_ITEMSIZE; i++) {
|
||
|
var offset = 1 + i * VEHICLEREPORT_ITEMSIZE;
|
||
|
vehicle = this.vehicles[data[offset]];
|
||
|
|
||
|
if (vehicle === null) continue;
|
||
|
|
||
|
wheel = vehicle.wheels[data[offset + 1]];
|
||
|
|
||
|
wheel.position.set(data[offset + 2], data[offset + 3], data[offset + 4]);
|
||
|
|
||
|
wheel.quaternion.set(data[offset + 5], data[offset + 6], data[offset + 7], data[offset + 8]);
|
||
|
}
|
||
|
|
||
|
if (this.SUPPORT_TRANSFERABLE) this.send(data.buffer, [data.buffer]); // Give the typed array back to the worker
|
||
|
}
|
||
|
}, {
|
||
|
key: 'updateConstraints',
|
||
|
value: function updateConstraints(data) {
|
||
|
var constraint = void 0,
|
||
|
object = void 0;
|
||
|
|
||
|
for (var i = 0; i < (data.length - 1) / CONSTRAINTREPORT_ITEMSIZE; i++) {
|
||
|
var offset = 1 + i * CONSTRAINTREPORT_ITEMSIZE;
|
||
|
constraint = this.constraints[data[offset]];
|
||
|
object = this.objects[data[offset + 1]];
|
||
|
|
||
|
if (constraint === undefined || object === undefined) continue;
|
||
|
|
||
|
temp1Vector3.set(data[offset + 2], data[offset + 3], data[offset + 4]);
|
||
|
|
||
|
temp1Matrix4.extractRotation(object.matrix);
|
||
|
temp1Vector3.applyMatrix4(temp1Matrix4);
|
||
|
|
||
|
constraint.positiona.addVectors(object.position, temp1Vector3);
|
||
|
constraint.appliedImpulse = data[offset + 5];
|
||
|
}
|
||
|
|
||
|
if (this.SUPPORT_TRANSFERABLE) this.send(data.buffer, [data.buffer]); // Give the typed array back to the worker
|
||
|
}
|
||
|
}, {
|
||
|
key: 'updateCollisions',
|
||
|
value: function updateCollisions(info) {
|
||
|
/**
|
||
|
* #TODO
|
||
|
* This is probably the worst way ever to handle collisions. The inherent evilness is a residual
|
||
|
* effect from the previous version's evilness which mutated when switching to transferable objects.
|
||
|
*
|
||
|
* If you feel inclined to make this better, please do so.
|
||
|
*/
|
||
|
|
||
|
var collisions = {},
|
||
|
normal_offsets = {};
|
||
|
|
||
|
// Build collision manifest
|
||
|
for (var i = 0; i < info[1]; i++) {
|
||
|
var offset = 2 + i * COLLISIONREPORT_ITEMSIZE;
|
||
|
var object = info[offset];
|
||
|
var object2 = info[offset + 1];
|
||
|
|
||
|
normal_offsets[object + '-' + object2] = offset + 2;
|
||
|
normal_offsets[object2 + '-' + object] = -1 * (offset + 2);
|
||
|
|
||
|
// Register collisions for both the object colliding and the object being collided with
|
||
|
if (!collisions[object]) collisions[object] = [];
|
||
|
collisions[object].push(object2);
|
||
|
|
||
|
if (!collisions[object2]) collisions[object2] = [];
|
||
|
collisions[object2].push(object);
|
||
|
}
|
||
|
|
||
|
// Deal with collisions
|
||
|
for (var id1 in this.objects) {
|
||
|
if (!this.objects.hasOwnProperty(id1)) continue;
|
||
|
var _object = this.objects[id1];
|
||
|
var component = _object.component;
|
||
|
var data = component.use('physics').data;
|
||
|
|
||
|
if (_object === null) continue;
|
||
|
|
||
|
// If object touches anything, ...
|
||
|
if (collisions[id1]) {
|
||
|
// Clean up touches array
|
||
|
for (var j = 0; j < data.touches.length; j++) {
|
||
|
if (collisions[id1].indexOf(data.touches[j]) === -1) data.touches.splice(j--, 1);
|
||
|
}
|
||
|
|
||
|
// Handle each colliding object
|
||
|
for (var _j = 0; _j < collisions[id1].length; _j++) {
|
||
|
var id2 = collisions[id1][_j];
|
||
|
var _object2 = this.objects[id2];
|
||
|
|
||
|
if (_object2) {
|
||
|
var component2 = _object2.component;
|
||
|
var data2 = component2.use('physics').data;
|
||
|
// If object was not already touching object2, notify object
|
||
|
if (data.touches.indexOf(id2) === -1) {
|
||
|
data.touches.push(id2);
|
||
|
|
||
|
var vel = component.use('physics').getLinearVelocity();
|
||
|
var vel2 = component2.use('physics').getLinearVelocity();
|
||
|
|
||
|
temp1Vector3.subVectors(vel, vel2);
|
||
|
var temp1 = temp1Vector3.clone();
|
||
|
|
||
|
temp1Vector3.subVectors(vel, vel2);
|
||
|
var temp2 = temp1Vector3.clone();
|
||
|
|
||
|
var normal_offset = normal_offsets[data.id + '-' + data2.id];
|
||
|
|
||
|
if (normal_offset > 0) {
|
||
|
temp1Vector3.set(-info[normal_offset], -info[normal_offset + 1], -info[normal_offset + 2]);
|
||
|
} else {
|
||
|
normal_offset *= -1;
|
||
|
|
||
|
temp1Vector3.set(info[normal_offset], info[normal_offset + 1], info[normal_offset + 2]);
|
||
|
}
|
||
|
|
||
|
component.emit('collision', _object2, temp1, temp2, temp1Vector3);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else data.touches.length = 0; // not touching other objects
|
||
|
}
|
||
|
|
||
|
this.collisions = collisions;
|
||
|
|
||
|
if (this.SUPPORT_TRANSFERABLE) this.send(info.buffer, [info.buffer]); // Give the typed array back to the worker
|
||
|
}
|
||
|
}, {
|
||
|
key: 'addConstraint',
|
||
|
value: function addConstraint(constraint, show_marker) {
|
||
|
constraint.id = this.getObjectId();
|
||
|
this.constraints[constraint.id] = constraint;
|
||
|
constraint.worldModule = this;
|
||
|
this.execute('addConstraint', constraint.getDefinition());
|
||
|
|
||
|
if (show_marker) {
|
||
|
var marker = void 0;
|
||
|
|
||
|
switch (constraint.type) {
|
||
|
case 'point':
|
||
|
marker = new three.Mesh(new three.SphereGeometry(1.5), new three.MeshNormalMaterial());
|
||
|
|
||
|
marker.position.copy(constraint.positiona);
|
||
|
this.objects[constraint.objecta].add(marker);
|
||
|
break;
|
||
|
|
||
|
case 'hinge':
|
||
|
marker = new three.Mesh(new three.SphereGeometry(1.5), new three.MeshNormalMaterial());
|
||
|
|
||
|
marker.position.copy(constraint.positiona);
|
||
|
this.objects[constraint.objecta].add(marker);
|
||
|
break;
|
||
|
|
||
|
case 'slider':
|
||
|
marker = new three.Mesh(new three.BoxGeometry(10, 1, 1), new three.MeshNormalMaterial());
|
||
|
|
||
|
marker.position.copy(constraint.positiona);
|
||
|
|
||
|
// This rotation isn't right if all three axis are non-0 values
|
||
|
// TODO: change marker's rotation order to ZYX
|
||
|
marker.rotation.set(constraint.axis.y, // yes, y and
|
||
|
constraint.axis.x, // x axis are swapped
|
||
|
constraint.axis.z);
|
||
|
this.objects[constraint.objecta].add(marker);
|
||
|
break;
|
||
|
|
||
|
case 'conetwist':
|
||
|
marker = new three.Mesh(new three.SphereGeometry(1.5), new three.MeshNormalMaterial());
|
||
|
|
||
|
marker.position.copy(constraint.positiona);
|
||
|
this.objects[constraint.objecta].add(marker);
|
||
|
break;
|
||
|
|
||
|
case 'dof':
|
||
|
marker = new three.Mesh(new three.SphereGeometry(1.5), new three.MeshNormalMaterial());
|
||
|
|
||
|
marker.position.copy(constraint.positiona);
|
||
|
this.objects[constraint.objecta].add(marker);
|
||
|
break;
|
||
|
default:
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return constraint;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onSimulationResume',
|
||
|
value: function onSimulationResume() {
|
||
|
this.execute('onSimulationResume', {});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'removeConstraint',
|
||
|
value: function removeConstraint(constraint) {
|
||
|
if (this.constraints[constraint.id] !== undefined) {
|
||
|
this.execute('removeConstraint', { id: constraint.id });
|
||
|
delete this.constraints[constraint.id];
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'execute',
|
||
|
value: function execute(cmd, params) {
|
||
|
this.send({ cmd: cmd, params: params });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onAddCallback',
|
||
|
value: function onAddCallback(component) {
|
||
|
var object = component.native;
|
||
|
var data = object.component.use('physics').data;
|
||
|
|
||
|
if (data) {
|
||
|
component.manager.set('module:world', this);
|
||
|
data.id = this.getObjectId();
|
||
|
object.component.use('physics').data = data;
|
||
|
|
||
|
if (object instanceof Vehicle) {
|
||
|
this.onAddCallback(object.mesh);
|
||
|
this.vehicles[data.id] = object;
|
||
|
this.execute('addVehicle', data);
|
||
|
} else {
|
||
|
component.__dirtyPosition = false;
|
||
|
component.__dirtyRotation = false;
|
||
|
this.objects[data.id] = object;
|
||
|
|
||
|
if (object.children.length) {
|
||
|
data.children = [];
|
||
|
addObjectChildren(object, object);
|
||
|
}
|
||
|
|
||
|
// object.quaternion.setFromEuler(object.rotation);
|
||
|
//
|
||
|
// console.log(object.component);
|
||
|
// console.log(object.rotation);
|
||
|
|
||
|
// Object starting position + rotation
|
||
|
data.position = {
|
||
|
x: object.position.x,
|
||
|
y: object.position.y,
|
||
|
z: object.position.z
|
||
|
};
|
||
|
|
||
|
data.rotation = {
|
||
|
x: object.quaternion.x,
|
||
|
y: object.quaternion.y,
|
||
|
z: object.quaternion.z,
|
||
|
w: object.quaternion.w
|
||
|
};
|
||
|
|
||
|
if (data.width) data.width *= object.scale.x;
|
||
|
if (data.height) data.height *= object.scale.y;
|
||
|
if (data.depth) data.depth *= object.scale.z;
|
||
|
|
||
|
this.execute('addObject', data);
|
||
|
}
|
||
|
|
||
|
component.emit('physics:added');
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'onRemoveCallback',
|
||
|
value: function onRemoveCallback(component) {
|
||
|
var object = component.native;
|
||
|
|
||
|
if (object instanceof Vehicle) {
|
||
|
this.execute('removeVehicle', { id: object._physijs.id });
|
||
|
while (object.wheels.length) {
|
||
|
this.remove(object.wheels.pop());
|
||
|
}this.remove(object.mesh);
|
||
|
this.vehicles[object._physijs.id] = null;
|
||
|
} else {
|
||
|
// Mesh.prototype.remove.call(this, object);
|
||
|
|
||
|
if (object._physijs) {
|
||
|
component.manager.remove('module:world');
|
||
|
this.objects[object._physijs.id] = null;
|
||
|
this.execute('removeObject', { id: object._physijs.id });
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}, {
|
||
|
key: 'defer',
|
||
|
value: function defer(func, args) {
|
||
|
var _this3 = this;
|
||
|
|
||
|
return new Promise(function (resolve) {
|
||
|
if (_this3.isLoaded) {
|
||
|
func.apply(undefined, toConsumableArray(args));
|
||
|
resolve();
|
||
|
} else _this3.loader.then(function () {
|
||
|
func.apply(undefined, toConsumableArray(args));
|
||
|
resolve();
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'manager',
|
||
|
value: function manager(_manager) {
|
||
|
_manager.define('physics');
|
||
|
_manager.set('physicsWorker', this.worker);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'integrate',
|
||
|
value: function integrate(self) {
|
||
|
var _this4 = this;
|
||
|
|
||
|
// ...
|
||
|
|
||
|
this.setFixedTimeStep = function (fixedTimeStep) {
|
||
|
if (fixedTimeStep) self.execute('setFixedTimeStep', fixedTimeStep);
|
||
|
};
|
||
|
|
||
|
this.setGravity = function (gravity) {
|
||
|
if (gravity) self.execute('setGravity', gravity);
|
||
|
};
|
||
|
|
||
|
this.addConstraint = self.addConstraint.bind(self);
|
||
|
|
||
|
this.simulate = function (timeStep, maxSubSteps) {
|
||
|
if (self._stats) self._stats.begin();
|
||
|
|
||
|
if (self.isSimulating) return false;
|
||
|
self.isSimulating = true;
|
||
|
|
||
|
for (var object_id in self.objects) {
|
||
|
if (!self.objects.hasOwnProperty(object_id)) continue;
|
||
|
|
||
|
var object = self.objects[object_id];
|
||
|
var component = object.component;
|
||
|
var data = component.use('physics').data;
|
||
|
|
||
|
if (object !== null && (component.__dirtyPosition || component.__dirtyRotation)) {
|
||
|
var update = { id: data.id };
|
||
|
|
||
|
if (component.__dirtyPosition) {
|
||
|
update.pos = {
|
||
|
x: object.position.x,
|
||
|
y: object.position.y,
|
||
|
z: object.position.z
|
||
|
};
|
||
|
|
||
|
if (data.isSoftbody) object.position.set(0, 0, 0);
|
||
|
|
||
|
component.__dirtyPosition = false;
|
||
|
}
|
||
|
|
||
|
if (component.__dirtyRotation) {
|
||
|
update.quat = {
|
||
|
x: object.quaternion.x,
|
||
|
y: object.quaternion.y,
|
||
|
z: object.quaternion.z,
|
||
|
w: object.quaternion.w
|
||
|
};
|
||
|
|
||
|
if (data.isSoftbody) object.rotation.set(0, 0, 0);
|
||
|
|
||
|
component.__dirtyRotation = false;
|
||
|
}
|
||
|
|
||
|
self.execute('updateTransform', update);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self.execute('simulate', { timeStep: timeStep, maxSubSteps: maxSubSteps });
|
||
|
|
||
|
if (self._stats) self._stats.end();
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
// const simulateProcess = (t) => {
|
||
|
// window.requestAnimationFrame(simulateProcess);
|
||
|
|
||
|
// this.simulate(1/60, 1); // delta, 1
|
||
|
// }
|
||
|
|
||
|
// simulateProcess();
|
||
|
|
||
|
self.loader.then(function () {
|
||
|
self.simulateLoop = new whs.Loop(function (clock) {
|
||
|
_this4.simulate(clock.getDelta(), 1); // delta, 1
|
||
|
});
|
||
|
|
||
|
self.simulateLoop.start(_this4);
|
||
|
|
||
|
console.log(self.options.gravity);
|
||
|
_this4.setGravity(self.options.gravity);
|
||
|
});
|
||
|
}
|
||
|
}]);
|
||
|
return WorldModuleBase;
|
||
|
}(Eventable), _class.defaults = {
|
||
|
fixedTimeStep: 1 / 60,
|
||
|
rateLimit: true,
|
||
|
ammo: "",
|
||
|
softbody: false,
|
||
|
gravity: new three.Vector3(0, -100, 0)
|
||
|
}, _temp2);
|
||
|
|
||
|
var TARGET = typeof Symbol === 'undefined' ? '__target' : Symbol(),
|
||
|
SCRIPT_TYPE = 'application/javascript',
|
||
|
BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder,
|
||
|
URL = window.URL || window.webkitURL,
|
||
|
Worker = window.Worker;
|
||
|
|
||
|
/**
|
||
|
* Returns a wrapper around Web Worker code that is constructible.
|
||
|
*
|
||
|
* @function shimWorker
|
||
|
*
|
||
|
* @param { String } filename The name of the file
|
||
|
* @param { Function } fn Function wrapping the code of the worker
|
||
|
*/
|
||
|
function shimWorker(filename, fn) {
|
||
|
return function ShimWorker(forceFallback) {
|
||
|
var o = this;
|
||
|
|
||
|
if (!fn) {
|
||
|
return new Worker(filename);
|
||
|
} else if (Worker && !forceFallback) {
|
||
|
// Convert the function's inner code to a string to construct the worker
|
||
|
var source = fn.toString().replace(/^function.+?{/, '').slice(0, -1),
|
||
|
objURL = createSourceObject(source);
|
||
|
|
||
|
this[TARGET] = new Worker(objURL);
|
||
|
URL.revokeObjectURL(objURL);
|
||
|
return this[TARGET];
|
||
|
} else {
|
||
|
var selfShim = {
|
||
|
postMessage: function postMessage(m) {
|
||
|
if (o.onmessage) {
|
||
|
setTimeout(function () {
|
||
|
o.onmessage({ data: m, target: selfShim });
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
fn.call(selfShim);
|
||
|
this.postMessage = function (m) {
|
||
|
setTimeout(function () {
|
||
|
selfShim.onmessage({ data: m, target: o });
|
||
|
});
|
||
|
};
|
||
|
this.isThisThread = true;
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
// Test Worker capabilities
|
||
|
if (Worker) {
|
||
|
var testWorker,
|
||
|
objURL = createSourceObject('self.onmessage = function () {}'),
|
||
|
testArray = new Uint8Array(1);
|
||
|
|
||
|
try {
|
||
|
// No workers via blobs in Edge 12 and IE 11 and lower :(
|
||
|
if (/(?:Trident|Edge)\/(?:[567]|12)/i.test(navigator.userAgent)) {
|
||
|
throw new Error('Not available');
|
||
|
}
|
||
|
testWorker = new Worker(objURL);
|
||
|
|
||
|
// Native browser on some Samsung devices throws for transferables, let's detect it
|
||
|
testWorker.postMessage(testArray, [testArray.buffer]);
|
||
|
} catch (e) {
|
||
|
Worker = null;
|
||
|
} finally {
|
||
|
URL.revokeObjectURL(objURL);
|
||
|
if (testWorker) {
|
||
|
testWorker.terminate();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function createSourceObject(str) {
|
||
|
try {
|
||
|
return URL.createObjectURL(new Blob([str], { type: SCRIPT_TYPE }));
|
||
|
} catch (e) {
|
||
|
var blob = new BlobBuilder();
|
||
|
blob.append(str);
|
||
|
return URL.createObjectURL(blob.getBlob(type));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var PhysicsWorker = new shimWorker("../worker.js", function (window, document) {
|
||
|
var self = this;
|
||
|
function Events(target) {
|
||
|
var events = {},
|
||
|
empty = [];
|
||
|
target = target || this;
|
||
|
/**
|
||
|
* On: listen to events
|
||
|
*/
|
||
|
target.on = function (type, func, ctx) {
|
||
|
(events[type] = events[type] || []).push([func, ctx]);
|
||
|
return target;
|
||
|
};
|
||
|
/**
|
||
|
* Off: stop listening to event / specific callback
|
||
|
*/
|
||
|
target.off = function (type, func) {
|
||
|
type || (events = {});
|
||
|
var list = events[type] || empty,
|
||
|
i = list.length = func ? list.length : 0;
|
||
|
while (i--) {
|
||
|
func == list[i][0] && list.splice(i, 1);
|
||
|
}return target;
|
||
|
};
|
||
|
/**
|
||
|
* Emit: send event, callbacks will be triggered
|
||
|
*/
|
||
|
target.emit = function (type) {
|
||
|
var e = events[type] || empty,
|
||
|
list = e.length > 0 ? e.slice(0, e.length) : e,
|
||
|
i = 0,
|
||
|
j;
|
||
|
while (j = list[i++]) {
|
||
|
j[0].apply(j[1], empty.slice.call(arguments, 1));
|
||
|
}return target;
|
||
|
};
|
||
|
}
|
||
|
var insideWorker = !self.document;
|
||
|
if (!insideWorker) self = new Events();
|
||
|
|
||
|
var send = insideWorker ? self.webkitPostMessage || self.postMessage : function (data) {
|
||
|
self.emit('message', { data: data });
|
||
|
};
|
||
|
|
||
|
self.send = send;
|
||
|
|
||
|
var SUPPORT_TRANSFERABLE = void 0;
|
||
|
|
||
|
if (insideWorker) {
|
||
|
var ab = new ArrayBuffer(1);
|
||
|
|
||
|
send(ab, [ab]);
|
||
|
SUPPORT_TRANSFERABLE = ab.byteLength === 0;
|
||
|
}
|
||
|
|
||
|
var MESSAGE_TYPES = {
|
||
|
WORLDREPORT: 0,
|
||
|
COLLISIONREPORT: 1,
|
||
|
VEHICLEREPORT: 2,
|
||
|
CONSTRAINTREPORT: 3,
|
||
|
SOFTREPORT: 4
|
||
|
};
|
||
|
|
||
|
// temp variables
|
||
|
var _object = void 0,
|
||
|
_vector = void 0,
|
||
|
_transform = void 0,
|
||
|
_transform_pos = void 0,
|
||
|
_softbody_enabled = false,
|
||
|
_num_objects = 0,
|
||
|
_num_rigidbody_objects = 0,
|
||
|
_num_softbody_objects = 0,
|
||
|
_num_wheels = 0,
|
||
|
_num_constraints = 0,
|
||
|
_softbody_report_size = 0,
|
||
|
|
||
|
|
||
|
// world variables
|
||
|
fixedTimeStep = void 0,
|
||
|
world = void 0,
|
||
|
_vec3_1 = void 0,
|
||
|
_vec3_2 = void 0,
|
||
|
_vec3_3 = void 0,
|
||
|
_quat = void 0;
|
||
|
|
||
|
// private cache
|
||
|
var public_functions = {},
|
||
|
_objects = [],
|
||
|
_vehicles = [],
|
||
|
_constraints = [],
|
||
|
_objects_ammo = {},
|
||
|
_object_shapes = {},
|
||
|
|
||
|
|
||
|
// The following objects are to track objects that ammo.js doesn't clean
|
||
|
// up. All are cleaned up when they're corresponding body is destroyed.
|
||
|
// Unfortunately, it's very difficult to get at these objects from the
|
||
|
// body, so we have to track them ourselves.
|
||
|
_motion_states = {},
|
||
|
|
||
|
// Don't need to worry about it for cached shapes.
|
||
|
_noncached_shapes = {},
|
||
|
|
||
|
// A body with a compound shape always has a regular shape as well, so we
|
||
|
// have track them separately.
|
||
|
_compound_shapes = {};
|
||
|
|
||
|
// object reporting
|
||
|
var REPORT_CHUNKSIZE = void 0,
|
||
|
// report array is increased in increments of this chunk size
|
||
|
worldreport = void 0,
|
||
|
softreport = void 0,
|
||
|
collisionreport = void 0,
|
||
|
vehiclereport = void 0,
|
||
|
constraintreport = void 0;
|
||
|
|
||
|
var WORLDREPORT_ITEMSIZE = 14,
|
||
|
// how many float values each reported item needs
|
||
|
COLLISIONREPORT_ITEMSIZE = 5,
|
||
|
// one float for each object id, and a Vec3 contact normal
|
||
|
VEHICLEREPORT_ITEMSIZE = 9,
|
||
|
// vehicle id, wheel index, 3 for position, 4 for rotation
|
||
|
CONSTRAINTREPORT_ITEMSIZE = 6; // constraint id, offset object, offset, applied impulse
|
||
|
|
||
|
var getShapeFromCache = function getShapeFromCache(cache_key) {
|
||
|
if (_object_shapes[cache_key] !== undefined) return _object_shapes[cache_key];
|
||
|
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
var setShapeCache = function setShapeCache(cache_key, shape) {
|
||
|
_object_shapes[cache_key] = shape;
|
||
|
};
|
||
|
|
||
|
var createShape = function createShape(description) {
|
||
|
var shape = void 0;
|
||
|
|
||
|
_transform.setIdentity();
|
||
|
switch (description.type) {
|
||
|
case 'compound':
|
||
|
{
|
||
|
shape = new Ammo.btCompoundShape();
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'plane':
|
||
|
{
|
||
|
var cache_key = 'plane_' + description.normal.x + '_' + description.normal.y + '_' + description.normal.z;
|
||
|
|
||
|
if ((shape = getShapeFromCache(cache_key)) === null) {
|
||
|
_vec3_1.setX(description.normal.x);
|
||
|
_vec3_1.setY(description.normal.y);
|
||
|
_vec3_1.setZ(description.normal.z);
|
||
|
shape = new Ammo.btStaticPlaneShape(_vec3_1, 0);
|
||
|
setShapeCache(cache_key, shape);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'box':
|
||
|
{
|
||
|
var _cache_key = 'box_' + description.width + '_' + description.height + '_' + description.depth;
|
||
|
|
||
|
if ((shape = getShapeFromCache(_cache_key)) === null) {
|
||
|
_vec3_1.setX(description.width / 2);
|
||
|
_vec3_1.setY(description.height / 2);
|
||
|
_vec3_1.setZ(description.depth / 2);
|
||
|
shape = new Ammo.btBoxShape(_vec3_1);
|
||
|
setShapeCache(_cache_key, shape);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'sphere':
|
||
|
{
|
||
|
var _cache_key2 = 'sphere_' + description.radius;
|
||
|
|
||
|
if ((shape = getShapeFromCache(_cache_key2)) === null) {
|
||
|
shape = new Ammo.btSphereShape(description.radius);
|
||
|
setShapeCache(_cache_key2, shape);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'cylinder':
|
||
|
{
|
||
|
var _cache_key3 = 'cylinder_' + description.width + '_' + description.height + '_' + description.depth;
|
||
|
|
||
|
if ((shape = getShapeFromCache(_cache_key3)) === null) {
|
||
|
_vec3_1.setX(description.width / 2);
|
||
|
_vec3_1.setY(description.height / 2);
|
||
|
_vec3_1.setZ(description.depth / 2);
|
||
|
shape = new Ammo.btCylinderShape(_vec3_1);
|
||
|
setShapeCache(_cache_key3, shape);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'capsule':
|
||
|
{
|
||
|
var _cache_key4 = 'capsule_' + description.radius + '_' + description.height;
|
||
|
|
||
|
if ((shape = getShapeFromCache(_cache_key4)) === null) {
|
||
|
// In Bullet, capsule height excludes the end spheres
|
||
|
shape = new Ammo.btCapsuleShape(description.radius, description.height - 2 * description.radius);
|
||
|
setShapeCache(_cache_key4, shape);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'cone':
|
||
|
{
|
||
|
var _cache_key5 = 'cone_' + description.radius + '_' + description.height;
|
||
|
|
||
|
if ((shape = getShapeFromCache(_cache_key5)) === null) {
|
||
|
shape = new Ammo.btConeShape(description.radius, description.height);
|
||
|
setShapeCache(_cache_key5, shape);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'concave':
|
||
|
{
|
||
|
var triangle_mesh = new Ammo.btTriangleMesh();
|
||
|
if (!description.data.length) return false;
|
||
|
var data = description.data;
|
||
|
|
||
|
for (var i = 0; i < data.length / 9; i++) {
|
||
|
_vec3_1.setX(data[i * 9]);
|
||
|
_vec3_1.setY(data[i * 9 + 1]);
|
||
|
_vec3_1.setZ(data[i * 9 + 2]);
|
||
|
|
||
|
_vec3_2.setX(data[i * 9 + 3]);
|
||
|
_vec3_2.setY(data[i * 9 + 4]);
|
||
|
_vec3_2.setZ(data[i * 9 + 5]);
|
||
|
|
||
|
_vec3_3.setX(data[i * 9 + 6]);
|
||
|
_vec3_3.setY(data[i * 9 + 7]);
|
||
|
_vec3_3.setZ(data[i * 9 + 8]);
|
||
|
|
||
|
triangle_mesh.addTriangle(_vec3_1, _vec3_2, _vec3_3, false);
|
||
|
}
|
||
|
|
||
|
shape = new Ammo.btBvhTriangleMeshShape(triangle_mesh, true, true);
|
||
|
|
||
|
_noncached_shapes[description.id] = shape;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'convex':
|
||
|
{
|
||
|
shape = new Ammo.btConvexHullShape();
|
||
|
var _data = description.data;
|
||
|
|
||
|
for (var _i = 0; _i < _data.length / 3; _i++) {
|
||
|
_vec3_1.setX(_data[_i * 3]);
|
||
|
_vec3_1.setY(_data[_i * 3 + 1]);
|
||
|
_vec3_1.setZ(_data[_i * 3 + 2]);
|
||
|
|
||
|
shape.addPoint(_vec3_1);
|
||
|
}
|
||
|
|
||
|
_noncached_shapes[description.id] = shape;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'heightfield':
|
||
|
{
|
||
|
var xpts = description.xpts,
|
||
|
ypts = description.ypts,
|
||
|
points = description.points,
|
||
|
ptr = Ammo._malloc(4 * xpts * ypts);
|
||
|
|
||
|
for (var _i2 = 0, p = 0, p2 = 0; _i2 < xpts; _i2++) {
|
||
|
for (var j = 0; j < ypts; j++) {
|
||
|
Ammo.HEAPF32[ptr + p2 >> 2] = points[p];
|
||
|
|
||
|
p++;
|
||
|
p2 += 4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
shape = new Ammo.btHeightfieldTerrainShape(description.xpts, description.ypts, ptr, 1, -description.absMaxHeight, description.absMaxHeight, 1, 'PHY_FLOAT', false);
|
||
|
|
||
|
_noncached_shapes[description.id] = shape;
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
// Not recognized
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
return shape;
|
||
|
};
|
||
|
|
||
|
var createSoftBody = function createSoftBody(description) {
|
||
|
var body = void 0;
|
||
|
|
||
|
var softBodyHelpers = new Ammo.btSoftBodyHelpers();
|
||
|
|
||
|
switch (description.type) {
|
||
|
case 'softTrimesh':
|
||
|
{
|
||
|
if (!description.aVertices.length) return false;
|
||
|
|
||
|
body = softBodyHelpers.CreateFromTriMesh(world.getWorldInfo(), description.aVertices, description.aIndices, description.aIndices.length / 3, false);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'softClothMesh':
|
||
|
{
|
||
|
var cr = description.corners;
|
||
|
|
||
|
body = softBodyHelpers.CreatePatch(world.getWorldInfo(), new Ammo.btVector3(cr[0], cr[1], cr[2]), new Ammo.btVector3(cr[3], cr[4], cr[5]), new Ammo.btVector3(cr[6], cr[7], cr[8]), new Ammo.btVector3(cr[9], cr[10], cr[11]), description.segments[0], description.segments[1], 0, true);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'softRopeMesh':
|
||
|
{
|
||
|
var data = description.data;
|
||
|
|
||
|
body = softBodyHelpers.CreateRope(world.getWorldInfo(), new Ammo.btVector3(data[0], data[1], data[2]), new Ammo.btVector3(data[3], data[4], data[5]), data[6] - 1, 0);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
// Not recognized
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
return body;
|
||
|
};
|
||
|
|
||
|
public_functions.init = function () {
|
||
|
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||
|
|
||
|
if (params.noWorker) {
|
||
|
window.Ammo = new params.ammo();
|
||
|
public_functions.makeWorld(params);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (params.wasmBuffer) {
|
||
|
importScripts(params.ammo);
|
||
|
|
||
|
self.Ammo = new loadAmmoFromBinary(params.wasmBuffer)();
|
||
|
send({ cmd: 'ammoLoaded' });
|
||
|
public_functions.makeWorld(params);
|
||
|
} else {
|
||
|
importScripts(params.ammo);
|
||
|
send({ cmd: 'ammoLoaded' });
|
||
|
|
||
|
self.Ammo = new Ammo();
|
||
|
public_functions.makeWorld(params);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public_functions.makeWorld = function () {
|
||
|
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||
|
|
||
|
_transform = new Ammo.btTransform();
|
||
|
_transform_pos = new Ammo.btTransform();
|
||
|
_vec3_1 = new Ammo.btVector3(0, 0, 0);
|
||
|
_vec3_2 = new Ammo.btVector3(0, 0, 0);
|
||
|
_vec3_3 = new Ammo.btVector3(0, 0, 0);
|
||
|
_quat = new Ammo.btQuaternion(0, 0, 0, 0);
|
||
|
|
||
|
REPORT_CHUNKSIZE = params.reportsize || 50;
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE) {
|
||
|
// Transferable messages are supported, take advantage of them with TypedArrays
|
||
|
worldreport = new Float32Array(2 + REPORT_CHUNKSIZE * WORLDREPORT_ITEMSIZE); // message id + # of objects to report + chunk size * # of values per object
|
||
|
collisionreport = new Float32Array(2 + REPORT_CHUNKSIZE * COLLISIONREPORT_ITEMSIZE); // message id + # of collisions to report + chunk size * # of values per object
|
||
|
vehiclereport = new Float32Array(2 + REPORT_CHUNKSIZE * VEHICLEREPORT_ITEMSIZE); // message id + # of vehicles to report + chunk size * # of values per object
|
||
|
constraintreport = new Float32Array(2 + REPORT_CHUNKSIZE * CONSTRAINTREPORT_ITEMSIZE); // message id + # of constraints to report + chunk size * # of values per object
|
||
|
} else {
|
||
|
// Transferable messages are not supported, send data as normal arrays
|
||
|
worldreport = [];
|
||
|
collisionreport = [];
|
||
|
vehiclereport = [];
|
||
|
constraintreport = [];
|
||
|
}
|
||
|
|
||
|
worldreport[0] = MESSAGE_TYPES.WORLDREPORT;
|
||
|
collisionreport[0] = MESSAGE_TYPES.COLLISIONREPORT;
|
||
|
vehiclereport[0] = MESSAGE_TYPES.VEHICLEREPORT;
|
||
|
constraintreport[0] = MESSAGE_TYPES.CONSTRAINTREPORT;
|
||
|
|
||
|
var collisionConfiguration = params.softbody ? new Ammo.btSoftBodyRigidBodyCollisionConfiguration() : new Ammo.btDefaultCollisionConfiguration(),
|
||
|
dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration),
|
||
|
solver = new Ammo.btSequentialImpulseConstraintSolver();
|
||
|
|
||
|
var broadphase = void 0;
|
||
|
|
||
|
if (!params.broadphase) params.broadphase = { type: 'dynamic' };
|
||
|
// TODO!!!
|
||
|
/* if (params.broadphase.type === 'sweepprune') {
|
||
|
extend(params.broadphase, {
|
||
|
aabbmin: {
|
||
|
x: -50,
|
||
|
y: -50,
|
||
|
z: -50
|
||
|
},
|
||
|
aabbmax: {
|
||
|
x: 50,
|
||
|
y: 50,
|
||
|
z: 50
|
||
|
},
|
||
|
});
|
||
|
}*/
|
||
|
|
||
|
switch (params.broadphase.type) {
|
||
|
case 'sweepprune':
|
||
|
_vec3_1.setX(params.broadphase.aabbmin.x);
|
||
|
_vec3_1.setY(params.broadphase.aabbmin.y);
|
||
|
_vec3_1.setZ(params.broadphase.aabbmin.z);
|
||
|
|
||
|
_vec3_2.setX(params.broadphase.aabbmax.x);
|
||
|
_vec3_2.setY(params.broadphase.aabbmax.y);
|
||
|
_vec3_2.setZ(params.broadphase.aabbmax.z);
|
||
|
|
||
|
broadphase = new Ammo.btAxisSweep3(_vec3_1, _vec3_2);
|
||
|
|
||
|
break;
|
||
|
case 'dynamic':
|
||
|
default:
|
||
|
broadphase = new Ammo.btDbvtBroadphase();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
world = params.softbody ? new Ammo.btSoftRigidDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration, new Ammo.btDefaultSoftBodySolver()) : new Ammo.btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
|
||
|
fixedTimeStep = params.fixedTimeStep;
|
||
|
|
||
|
if (params.softbody) _softbody_enabled = true;
|
||
|
|
||
|
send({ cmd: 'worldReady' });
|
||
|
};
|
||
|
|
||
|
public_functions.setFixedTimeStep = function (description) {
|
||
|
fixedTimeStep = description;
|
||
|
};
|
||
|
|
||
|
public_functions.setGravity = function (description) {
|
||
|
_vec3_1.setX(description.x);
|
||
|
_vec3_1.setY(description.y);
|
||
|
_vec3_1.setZ(description.z);
|
||
|
world.setGravity(_vec3_1);
|
||
|
};
|
||
|
|
||
|
public_functions.appendAnchor = function (description) {
|
||
|
_objects[description.obj].appendAnchor(description.node, _objects[description.obj2], description.collisionBetweenLinkedBodies, description.influence);
|
||
|
};
|
||
|
|
||
|
public_functions.linkNodes = function (description) {
|
||
|
var self_body = _objects[description.self];
|
||
|
var other_body = _objects[description.body];
|
||
|
|
||
|
var self_node = self_body.get_m_nodes().at(description.n1);
|
||
|
var other_node = other_body.get_m_nodes().at(description.n2);
|
||
|
|
||
|
var self_vec = self_node.get_m_x();
|
||
|
var other_vec = other_node.get_m_x();
|
||
|
|
||
|
var force_x = other_vec.x() - self_vec.x();
|
||
|
var force_y = other_vec.y() - self_vec.y();
|
||
|
var force_z = other_vec.z() - self_vec.z();
|
||
|
|
||
|
// var modifier = 30;
|
||
|
|
||
|
var cached_distance = void 0,
|
||
|
linked = false;
|
||
|
|
||
|
var _loop = setInterval(function () {
|
||
|
force_x = other_vec.x() - self_vec.x();
|
||
|
force_y = other_vec.y() - self_vec.y();
|
||
|
force_z = other_vec.z() - self_vec.z();
|
||
|
|
||
|
var distance = Math.sqrt(force_x * force_x + force_y * force_y + force_z * force_z);
|
||
|
|
||
|
if (cached_distance && !linked && cached_distance < distance) {
|
||
|
// cached_distance && !linked && cached_distance < distance
|
||
|
|
||
|
linked = true;
|
||
|
|
||
|
// let self_vel = self_node.get_m_v();
|
||
|
//
|
||
|
// _vec3_1.setX(-self_vel.x());
|
||
|
// _vec3_1.setY(-self_vel.y());
|
||
|
// _vec3_1.setZ(-self_vel.z());
|
||
|
//
|
||
|
// let other_vel = other_node.get_m_v();
|
||
|
//
|
||
|
// _vec3_2.setX(-other_vel.x());
|
||
|
// _vec3_2.setY(-other_vel.y());
|
||
|
// _vec3_2.setZ(-other_vel.z());
|
||
|
|
||
|
console.log('link!');
|
||
|
|
||
|
_vec3_1.setX(0);
|
||
|
_vec3_1.setY(0);
|
||
|
_vec3_1.setZ(0);
|
||
|
|
||
|
self_body.setVelocity(_vec3_1);
|
||
|
|
||
|
other_body.setVelocity(_vec3_1);
|
||
|
|
||
|
// self_body.addVelocity(_vec3_1);
|
||
|
// other_body.addVelocity(_vec3_2);
|
||
|
|
||
|
// self_relative_x = self_node.x();
|
||
|
// self_relative_y = self_node.y();
|
||
|
// self_relative_z = self_node.z();
|
||
|
//
|
||
|
// other_relative_x = other_node.x();
|
||
|
// other_relative_y = other_node.y();
|
||
|
// other_relative_z = other_node.z();
|
||
|
|
||
|
// self_relative = new Ammo.btVector3();
|
||
|
// self_relative.setX();
|
||
|
|
||
|
// console.log('link!');
|
||
|
// self_body.appendAnchor(description.n1, connector, true, 0.5);
|
||
|
// other_body.appendAnchor(description.n2, connector, true, 0.5);
|
||
|
// clearInterval(_loop);
|
||
|
|
||
|
// _vec3_1.setX(0);
|
||
|
// _vec3_1.setY(0);
|
||
|
// _vec3_1.setZ(0);
|
||
|
|
||
|
// self_body.setVelocity(_vec3_1);
|
||
|
// other_body.setVelocity(_vec3_1);
|
||
|
|
||
|
// other_body.addForce(
|
||
|
// _vec3_2,
|
||
|
// description.n2
|
||
|
// );
|
||
|
|
||
|
// description.modifier *= 1.6;
|
||
|
}
|
||
|
|
||
|
var modifer2 = linked ? 40 : 1;
|
||
|
|
||
|
force_x *= Math.max(distance, 1) * description.modifier * modifer2;
|
||
|
force_y *= Math.max(distance, 1) * description.modifier * modifer2;
|
||
|
force_z *= Math.max(distance, 1) * description.modifier * modifer2;
|
||
|
|
||
|
_vec3_1.setX(force_x);
|
||
|
_vec3_1.setY(force_y);
|
||
|
_vec3_1.setZ(force_z);
|
||
|
|
||
|
_vec3_2.setX(-force_x);
|
||
|
_vec3_2.setY(-force_y);
|
||
|
_vec3_2.setZ(-force_z);
|
||
|
|
||
|
self_body.addVelocity(_vec3_1, description.n1);
|
||
|
|
||
|
other_body.addVelocity(_vec3_2, description.n2);
|
||
|
|
||
|
// } else {
|
||
|
// // self_relative_x = null;
|
||
|
// }
|
||
|
|
||
|
|
||
|
// if (self_relative_x) {
|
||
|
// _vec3_1.setX(self_relative_x - self_node.x());
|
||
|
// _vec3_1.setY(self_relative_y - self_node.y());
|
||
|
// _vec3_1.setZ(self_relative_z - self_node.z());
|
||
|
//
|
||
|
// _vec3_2.setX(other_relative_x - other_node.x());
|
||
|
// _vec3_2.setY(other_relative_y - other_node.y());
|
||
|
// _vec3_2.setZ(other_relative_z - other_node.z());
|
||
|
// } else {
|
||
|
|
||
|
// }
|
||
|
|
||
|
|
||
|
cached_distance = distance;
|
||
|
}, 10);
|
||
|
};
|
||
|
|
||
|
public_functions.appendLink = function (description) {
|
||
|
// console.log(Ammo);
|
||
|
// console.log(new Ammo.Material());
|
||
|
|
||
|
// var _mat = new Ammo.Material();
|
||
|
//
|
||
|
// _mat.set_m_kAST(0);
|
||
|
// _mat.set_m_kLST(0);
|
||
|
// _mat.set_m_kVST(0);
|
||
|
//
|
||
|
// _objects[description.self].appendLink(
|
||
|
// description.n1,
|
||
|
// description.n2,
|
||
|
// _mat,
|
||
|
// false
|
||
|
// );
|
||
|
|
||
|
_vec3_1.setX(1000);
|
||
|
_vec3_1.setY(0);
|
||
|
_vec3_1.setZ(0);
|
||
|
|
||
|
_objects[description.self].addForce(_vec3_1, description.n1);
|
||
|
};
|
||
|
|
||
|
public_functions.appendLinearJoint = function (description) {
|
||
|
// console.log('Ammo', Ammo);
|
||
|
var specs = new Ammo.Specs();
|
||
|
var _pos = description.specs.position;
|
||
|
|
||
|
specs.set_position(new Ammo.btVector3(_pos[0], _pos[1], _pos[2]));
|
||
|
if (description.specs.erp) specs.set_erp(description.specs.erp);
|
||
|
if (description.specs.cfm) specs.set_cfm(description.specs.cfm);
|
||
|
if (description.specs.split) specs.set_split(description.specs.split);
|
||
|
|
||
|
// console.log(specs);
|
||
|
//
|
||
|
// // ljoint.set_m_rpos(
|
||
|
// // new Ammo.btVector3(_pos1[0], _pos1[1], _pos1[2]),
|
||
|
// // new Ammo.btVector3(_pos2[0], _pos2[1], _pos2[2])
|
||
|
// // );
|
||
|
//
|
||
|
// // console.log('ljoint', ljoint);
|
||
|
//
|
||
|
|
||
|
// console.log('body', _objects[description.body]);
|
||
|
_objects[description.self].appendLinearJoint(specs, _objects[description.body]);
|
||
|
};
|
||
|
|
||
|
public_functions.addObject = function (description) {
|
||
|
var body = void 0,
|
||
|
motionState = void 0;
|
||
|
|
||
|
if (description.type.indexOf('soft') !== -1) {
|
||
|
body = createSoftBody(description);
|
||
|
|
||
|
var sbConfig = body.get_m_cfg();
|
||
|
|
||
|
if (description.viterations) sbConfig.set_viterations(description.viterations);
|
||
|
if (description.piterations) sbConfig.set_piterations(description.piterations);
|
||
|
if (description.diterations) sbConfig.set_diterations(description.diterations);
|
||
|
if (description.citerations) sbConfig.set_citerations(description.citerations);
|
||
|
sbConfig.set_collisions(0x11);
|
||
|
sbConfig.set_kDF(description.friction);
|
||
|
sbConfig.set_kDP(description.damping);
|
||
|
if (description.pressure) sbConfig.set_kPR(description.pressure);
|
||
|
if (description.drag) sbConfig.set_kDG(description.drag);
|
||
|
if (description.lift) sbConfig.set_kLF(description.lift);
|
||
|
if (description.anchorHardness) sbConfig.set_kAHR(description.anchorHardness);
|
||
|
if (description.rigidHardness) sbConfig.set_kCHR(description.rigidHardness);
|
||
|
|
||
|
if (description.klst) body.get_m_materials().at(0).set_m_kLST(description.klst);
|
||
|
if (description.kast) body.get_m_materials().at(0).set_m_kAST(description.kast);
|
||
|
if (description.kvst) body.get_m_materials().at(0).set_m_kVST(description.kvst);
|
||
|
|
||
|
Ammo.castObject(body, Ammo.btCollisionObject).getCollisionShape().setMargin(typeof description.margin !== 'undefined' ? description.margin : 0.1);
|
||
|
|
||
|
// Ammo.castObject(body, Ammo.btCollisionObject).getCollisionShape().setMargin(0);
|
||
|
|
||
|
// Ammo.castObject(body, Ammo.btCollisionObject).getCollisionShape().setLocalScaling(_vec3_1);
|
||
|
body.setActivationState(description.state || 4);
|
||
|
body.type = 0; // SoftBody.
|
||
|
if (description.type === 'softRopeMesh') body.rope = true;
|
||
|
if (description.type === 'softClothMesh') body.cloth = true;
|
||
|
|
||
|
_transform.setIdentity();
|
||
|
|
||
|
// @test
|
||
|
_quat.setX(description.rotation.x);
|
||
|
_quat.setY(description.rotation.y);
|
||
|
_quat.setZ(description.rotation.z);
|
||
|
_quat.setW(description.rotation.w);
|
||
|
body.rotate(_quat);
|
||
|
|
||
|
_vec3_1.setX(description.position.x);
|
||
|
_vec3_1.setY(description.position.y);
|
||
|
_vec3_1.setZ(description.position.z);
|
||
|
body.translate(_vec3_1);
|
||
|
|
||
|
_vec3_1.setX(description.scale.x);
|
||
|
_vec3_1.setY(description.scale.y);
|
||
|
_vec3_1.setZ(description.scale.z);
|
||
|
body.scale(_vec3_1);
|
||
|
|
||
|
body.setTotalMass(description.mass, false);
|
||
|
world.addSoftBody(body, 1, -1);
|
||
|
if (description.type === 'softTrimesh') _softbody_report_size += body.get_m_faces().size() * 3;else if (description.type === 'softRopeMesh') _softbody_report_size += body.get_m_nodes().size();else _softbody_report_size += body.get_m_nodes().size() * 3;
|
||
|
|
||
|
_num_softbody_objects++;
|
||
|
} else {
|
||
|
var shape = createShape(description);
|
||
|
|
||
|
if (!shape) return;
|
||
|
|
||
|
// If there are children then this is a compound shape
|
||
|
if (description.children) {
|
||
|
var compound_shape = new Ammo.btCompoundShape();
|
||
|
compound_shape.addChildShape(_transform, shape);
|
||
|
|
||
|
for (var i = 0; i < description.children.length; i++) {
|
||
|
var _child = description.children[i];
|
||
|
|
||
|
var trans = new Ammo.btTransform();
|
||
|
trans.setIdentity();
|
||
|
|
||
|
_vec3_1.setX(_child.position_offset.x);
|
||
|
_vec3_1.setY(_child.position_offset.y);
|
||
|
_vec3_1.setZ(_child.position_offset.z);
|
||
|
trans.setOrigin(_vec3_1);
|
||
|
|
||
|
_quat.setX(_child.rotation.x);
|
||
|
_quat.setY(_child.rotation.y);
|
||
|
_quat.setZ(_child.rotation.z);
|
||
|
_quat.setW(_child.rotation.w);
|
||
|
trans.setRotation(_quat);
|
||
|
|
||
|
shape = createShape(description.children[i]);
|
||
|
compound_shape.addChildShape(trans, shape);
|
||
|
Ammo.destroy(trans);
|
||
|
}
|
||
|
|
||
|
shape = compound_shape;
|
||
|
_compound_shapes[description.id] = shape;
|
||
|
}
|
||
|
|
||
|
_vec3_1.setX(description.scale.x);
|
||
|
_vec3_1.setY(description.scale.y);
|
||
|
_vec3_1.setZ(description.scale.z);
|
||
|
|
||
|
shape.setLocalScaling(_vec3_1);
|
||
|
shape.setMargin(typeof description.margin !== 'undefined' ? description.margin : 0);
|
||
|
|
||
|
_vec3_1.setX(0);
|
||
|
_vec3_1.setY(0);
|
||
|
_vec3_1.setZ(0);
|
||
|
shape.calculateLocalInertia(description.mass, _vec3_1);
|
||
|
|
||
|
_transform.setIdentity();
|
||
|
|
||
|
_vec3_2.setX(description.position.x);
|
||
|
_vec3_2.setY(description.position.y);
|
||
|
_vec3_2.setZ(description.position.z);
|
||
|
_transform.setOrigin(_vec3_2);
|
||
|
|
||
|
_quat.setX(description.rotation.x);
|
||
|
_quat.setY(description.rotation.y);
|
||
|
_quat.setZ(description.rotation.z);
|
||
|
_quat.setW(description.rotation.w);
|
||
|
_transform.setRotation(_quat);
|
||
|
|
||
|
motionState = new Ammo.btDefaultMotionState(_transform); // #TODO: btDefaultMotionState supports center of mass offset as second argument - implement
|
||
|
var rbInfo = new Ammo.btRigidBodyConstructionInfo(description.mass, motionState, shape, _vec3_1);
|
||
|
|
||
|
rbInfo.set_m_friction(description.friction);
|
||
|
rbInfo.set_m_restitution(description.restitution);
|
||
|
rbInfo.set_m_linearDamping(description.damping);
|
||
|
rbInfo.set_m_angularDamping(description.damping);
|
||
|
|
||
|
body = new Ammo.btRigidBody(rbInfo);
|
||
|
body.setActivationState(description.state || 4);
|
||
|
Ammo.destroy(rbInfo);
|
||
|
|
||
|
if (typeof description.collision_flags !== 'undefined') body.setCollisionFlags(description.collision_flags);
|
||
|
|
||
|
if (description.group && description.mask) world.addRigidBody(body, description.group, description.mask);else world.addRigidBody(body);
|
||
|
body.type = 1; // RigidBody.
|
||
|
_num_rigidbody_objects++;
|
||
|
}
|
||
|
|
||
|
body.activate();
|
||
|
|
||
|
body.id = description.id;
|
||
|
_objects[body.id] = body;
|
||
|
_motion_states[body.id] = motionState;
|
||
|
|
||
|
_objects_ammo[body.a === undefined ? body.ptr : body.a] = body.id;
|
||
|
_num_objects++;
|
||
|
|
||
|
send({ cmd: 'objectReady', params: body.id });
|
||
|
};
|
||
|
|
||
|
public_functions.addVehicle = function (description) {
|
||
|
var vehicle_tuning = new Ammo.btVehicleTuning();
|
||
|
|
||
|
vehicle_tuning.set_m_suspensionStiffness(description.suspension_stiffness);
|
||
|
vehicle_tuning.set_m_suspensionCompression(description.suspension_compression);
|
||
|
vehicle_tuning.set_m_suspensionDamping(description.suspension_damping);
|
||
|
vehicle_tuning.set_m_maxSuspensionTravelCm(description.max_suspension_travel);
|
||
|
vehicle_tuning.set_m_maxSuspensionForce(description.max_suspension_force);
|
||
|
|
||
|
var vehicle = new Ammo.btRaycastVehicle(vehicle_tuning, _objects[description.rigidBody], new Ammo.btDefaultVehicleRaycaster(world));
|
||
|
|
||
|
vehicle.tuning = vehicle_tuning;
|
||
|
_objects[description.rigidBody].setActivationState(4);
|
||
|
vehicle.setCoordinateSystem(0, 1, 2);
|
||
|
|
||
|
world.addVehicle(vehicle);
|
||
|
_vehicles[description.id] = vehicle;
|
||
|
};
|
||
|
public_functions.removeVehicle = function (description) {
|
||
|
_vehicles[description.id] = null;
|
||
|
};
|
||
|
|
||
|
public_functions.addWheel = function (description) {
|
||
|
if (_vehicles[description.id] !== undefined) {
|
||
|
var tuning = _vehicles[description.id].tuning;
|
||
|
if (description.tuning !== undefined) {
|
||
|
tuning = new Ammo.btVehicleTuning();
|
||
|
tuning.set_m_suspensionStiffness(description.tuning.suspension_stiffness);
|
||
|
tuning.set_m_suspensionCompression(description.tuning.suspension_compression);
|
||
|
tuning.set_m_suspensionDamping(description.tuning.suspension_damping);
|
||
|
tuning.set_m_maxSuspensionTravelCm(description.tuning.max_suspension_travel);
|
||
|
tuning.set_m_maxSuspensionForce(description.tuning.max_suspension_force);
|
||
|
}
|
||
|
|
||
|
_vec3_1.setX(description.connection_point.x);
|
||
|
_vec3_1.setY(description.connection_point.y);
|
||
|
_vec3_1.setZ(description.connection_point.z);
|
||
|
|
||
|
_vec3_2.setX(description.wheel_direction.x);
|
||
|
_vec3_2.setY(description.wheel_direction.y);
|
||
|
_vec3_2.setZ(description.wheel_direction.z);
|
||
|
|
||
|
_vec3_3.setX(description.wheel_axle.x);
|
||
|
_vec3_3.setY(description.wheel_axle.y);
|
||
|
_vec3_3.setZ(description.wheel_axle.z);
|
||
|
|
||
|
_vehicles[description.id].addWheel(_vec3_1, _vec3_2, _vec3_3, description.suspension_rest_length, description.wheel_radius, tuning, description.is_front_wheel);
|
||
|
}
|
||
|
|
||
|
_num_wheels++;
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE) {
|
||
|
vehiclereport = new Float32Array(1 + _num_wheels * VEHICLEREPORT_ITEMSIZE); // message id & ( # of objects to report * # of values per object )
|
||
|
vehiclereport[0] = MESSAGE_TYPES.VEHICLEREPORT;
|
||
|
} else vehiclereport = [MESSAGE_TYPES.VEHICLEREPORT];
|
||
|
};
|
||
|
|
||
|
public_functions.setSteering = function (details) {
|
||
|
if (_vehicles[details.id] !== undefined) _vehicles[details.id].setSteeringValue(details.steering, details.wheel);
|
||
|
};
|
||
|
|
||
|
public_functions.setBrake = function (details) {
|
||
|
if (_vehicles[details.id] !== undefined) _vehicles[details.id].setBrake(details.brake, details.wheel);
|
||
|
};
|
||
|
|
||
|
public_functions.applyEngineForce = function (details) {
|
||
|
if (_vehicles[details.id] !== undefined) _vehicles[details.id].applyEngineForce(details.force, details.wheel);
|
||
|
};
|
||
|
|
||
|
public_functions.removeObject = function (details) {
|
||
|
if (_objects[details.id].type === 0) {
|
||
|
_num_softbody_objects--;
|
||
|
_softbody_report_size -= _objects[details.id].get_m_nodes().size();
|
||
|
world.removeSoftBody(_objects[details.id]);
|
||
|
} else if (_objects[details.id].type === 1) {
|
||
|
_num_rigidbody_objects--;
|
||
|
world.removeRigidBody(_objects[details.id]);
|
||
|
Ammo.destroy(_motion_states[details.id]);
|
||
|
}
|
||
|
|
||
|
Ammo.destroy(_objects[details.id]);
|
||
|
if (_compound_shapes[details.id]) Ammo.destroy(_compound_shapes[details.id]);
|
||
|
if (_noncached_shapes[details.id]) Ammo.destroy(_noncached_shapes[details.id]);
|
||
|
|
||
|
_objects_ammo[_objects[details.id].a === undefined ? _objects[details.id].a : _objects[details.id].ptr] = null;
|
||
|
_objects[details.id] = null;
|
||
|
_motion_states[details.id] = null;
|
||
|
|
||
|
if (_compound_shapes[details.id]) _compound_shapes[details.id] = null;
|
||
|
if (_noncached_shapes[details.id]) _noncached_shapes[details.id] = null;
|
||
|
_num_objects--;
|
||
|
};
|
||
|
|
||
|
public_functions.updateTransform = function (details) {
|
||
|
_object = _objects[details.id];
|
||
|
|
||
|
if (_object.type === 1) {
|
||
|
_object.getMotionState().getWorldTransform(_transform);
|
||
|
|
||
|
if (details.pos) {
|
||
|
_vec3_1.setX(details.pos.x);
|
||
|
_vec3_1.setY(details.pos.y);
|
||
|
_vec3_1.setZ(details.pos.z);
|
||
|
_transform.setOrigin(_vec3_1);
|
||
|
}
|
||
|
|
||
|
if (details.quat) {
|
||
|
_quat.setX(details.quat.x);
|
||
|
_quat.setY(details.quat.y);
|
||
|
_quat.setZ(details.quat.z);
|
||
|
_quat.setW(details.quat.w);
|
||
|
_transform.setRotation(_quat);
|
||
|
}
|
||
|
|
||
|
_object.setWorldTransform(_transform);
|
||
|
_object.activate();
|
||
|
} else if (_object.type === 0) {
|
||
|
// _object.getWorldTransform(_transform);
|
||
|
|
||
|
if (details.pos) {
|
||
|
_vec3_1.setX(details.pos.x);
|
||
|
_vec3_1.setY(details.pos.y);
|
||
|
_vec3_1.setZ(details.pos.z);
|
||
|
_transform.setOrigin(_vec3_1);
|
||
|
}
|
||
|
|
||
|
if (details.quat) {
|
||
|
_quat.setX(details.quat.x);
|
||
|
_quat.setY(details.quat.y);
|
||
|
_quat.setZ(details.quat.z);
|
||
|
_quat.setW(details.quat.w);
|
||
|
_transform.setRotation(_quat);
|
||
|
}
|
||
|
|
||
|
_object.transform(_transform);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public_functions.updateMass = function (details) {
|
||
|
// #TODO: changing a static object into dynamic is buggy
|
||
|
_object = _objects[details.id];
|
||
|
|
||
|
// Per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=&f=9&t=3663#p13816
|
||
|
world.removeRigidBody(_object);
|
||
|
|
||
|
_vec3_1.setX(0);
|
||
|
_vec3_1.setY(0);
|
||
|
_vec3_1.setZ(0);
|
||
|
|
||
|
_object.setMassProps(details.mass, _vec3_1);
|
||
|
world.addRigidBody(_object);
|
||
|
_object.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.applyCentralImpulse = function (details) {
|
||
|
_vec3_1.setX(details.x);
|
||
|
_vec3_1.setY(details.y);
|
||
|
_vec3_1.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].applyCentralImpulse(_vec3_1);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.applyImpulse = function (details) {
|
||
|
_vec3_1.setX(details.impulse_x);
|
||
|
_vec3_1.setY(details.impulse_y);
|
||
|
_vec3_1.setZ(details.impulse_z);
|
||
|
|
||
|
_vec3_2.setX(details.x);
|
||
|
_vec3_2.setY(details.y);
|
||
|
_vec3_2.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].applyImpulse(_vec3_1, _vec3_2);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.applyTorque = function (details) {
|
||
|
_vec3_1.setX(details.torque_x);
|
||
|
_vec3_1.setY(details.torque_y);
|
||
|
_vec3_1.setZ(details.torque_z);
|
||
|
|
||
|
_objects[details.id].applyTorque(_vec3_1);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.applyCentralForce = function (details) {
|
||
|
_vec3_1.setX(details.x);
|
||
|
_vec3_1.setY(details.y);
|
||
|
_vec3_1.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].applyCentralForce(_vec3_1);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.applyForce = function (details) {
|
||
|
_vec3_1.setX(details.force_x);
|
||
|
_vec3_1.setY(details.force_y);
|
||
|
_vec3_1.setZ(details.force_z);
|
||
|
|
||
|
_vec3_2.setX(details.x);
|
||
|
_vec3_2.setY(details.y);
|
||
|
_vec3_2.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].applyForce(_vec3_1, _vec3_2);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.onSimulationResume = function () {
|
||
|
};
|
||
|
|
||
|
public_functions.setAngularVelocity = function (details) {
|
||
|
_vec3_1.setX(details.x);
|
||
|
_vec3_1.setY(details.y);
|
||
|
_vec3_1.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].setAngularVelocity(_vec3_1);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.setLinearVelocity = function (details) {
|
||
|
_vec3_1.setX(details.x);
|
||
|
_vec3_1.setY(details.y);
|
||
|
_vec3_1.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].setLinearVelocity(_vec3_1);
|
||
|
_objects[details.id].activate();
|
||
|
};
|
||
|
|
||
|
public_functions.setAngularFactor = function (details) {
|
||
|
_vec3_1.setX(details.x);
|
||
|
_vec3_1.setY(details.y);
|
||
|
_vec3_1.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].setAngularFactor(_vec3_1);
|
||
|
};
|
||
|
|
||
|
public_functions.setLinearFactor = function (details) {
|
||
|
_vec3_1.setX(details.x);
|
||
|
_vec3_1.setY(details.y);
|
||
|
_vec3_1.setZ(details.z);
|
||
|
|
||
|
_objects[details.id].setLinearFactor(_vec3_1);
|
||
|
};
|
||
|
|
||
|
public_functions.setDamping = function (details) {
|
||
|
_objects[details.id].setDamping(details.linear, details.angular);
|
||
|
};
|
||
|
|
||
|
public_functions.setCcdMotionThreshold = function (details) {
|
||
|
_objects[details.id].setCcdMotionThreshold(details.threshold);
|
||
|
};
|
||
|
|
||
|
public_functions.setCcdSweptSphereRadius = function (details) {
|
||
|
_objects[details.id].setCcdSweptSphereRadius(details.radius);
|
||
|
};
|
||
|
|
||
|
public_functions.addConstraint = function (details) {
|
||
|
var constraint = void 0;
|
||
|
|
||
|
switch (details.type) {
|
||
|
|
||
|
case 'point':
|
||
|
{
|
||
|
if (details.objectb === undefined) {
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
constraint = new Ammo.btPoint2PointConstraint(_objects[details.objecta], _vec3_1);
|
||
|
} else {
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
_vec3_2.setX(details.positionb.x);
|
||
|
_vec3_2.setY(details.positionb.y);
|
||
|
_vec3_2.setZ(details.positionb.z);
|
||
|
|
||
|
constraint = new Ammo.btPoint2PointConstraint(_objects[details.objecta], _objects[details.objectb], _vec3_1, _vec3_2);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case 'hinge':
|
||
|
{
|
||
|
if (details.objectb === undefined) {
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
_vec3_2.setX(details.axis.x);
|
||
|
_vec3_2.setY(details.axis.y);
|
||
|
_vec3_2.setZ(details.axis.z);
|
||
|
|
||
|
constraint = new Ammo.btHingeConstraint(_objects[details.objecta], _vec3_1, _vec3_2);
|
||
|
} else {
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
_vec3_2.setX(details.positionb.x);
|
||
|
_vec3_2.setY(details.positionb.y);
|
||
|
_vec3_2.setZ(details.positionb.z);
|
||
|
|
||
|
_vec3_3.setX(details.axis.x);
|
||
|
_vec3_3.setY(details.axis.y);
|
||
|
_vec3_3.setZ(details.axis.z);
|
||
|
|
||
|
constraint = new Ammo.btHingeConstraint(_objects[details.objecta], _objects[details.objectb], _vec3_1, _vec3_2, _vec3_3, _vec3_3);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case 'slider':
|
||
|
{
|
||
|
var transformb = void 0;
|
||
|
var transforma = new Ammo.btTransform();
|
||
|
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
transforma.setOrigin(_vec3_1);
|
||
|
|
||
|
var rotation = transforma.getRotation();
|
||
|
rotation.setEuler(details.axis.x, details.axis.y, details.axis.z);
|
||
|
transforma.setRotation(rotation);
|
||
|
|
||
|
if (details.objectb) {
|
||
|
transformb = new Ammo.btTransform();
|
||
|
|
||
|
_vec3_2.setX(details.positionb.x);
|
||
|
_vec3_2.setY(details.positionb.y);
|
||
|
_vec3_2.setZ(details.positionb.z);
|
||
|
|
||
|
transformb.setOrigin(_vec3_2);
|
||
|
|
||
|
rotation = transformb.getRotation();
|
||
|
rotation.setEuler(details.axis.x, details.axis.y, details.axis.z);
|
||
|
transformb.setRotation(rotation);
|
||
|
|
||
|
constraint = new Ammo.btSliderConstraint(_objects[details.objecta], _objects[details.objectb], transforma, transformb, true);
|
||
|
} else {
|
||
|
constraint = new Ammo.btSliderConstraint(_objects[details.objecta], transforma, true);
|
||
|
}
|
||
|
|
||
|
constraint.ta = transforma;
|
||
|
constraint.tb = transformb;
|
||
|
|
||
|
Ammo.destroy(transforma);
|
||
|
if (transformb !== undefined) Ammo.destroy(transformb);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'conetwist':
|
||
|
{
|
||
|
var _transforma = new Ammo.btTransform();
|
||
|
_transforma.setIdentity();
|
||
|
|
||
|
var _transformb = new Ammo.btTransform();
|
||
|
_transformb.setIdentity();
|
||
|
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
_vec3_2.setX(details.positionb.x);
|
||
|
_vec3_2.setY(details.positionb.y);
|
||
|
_vec3_2.setZ(details.positionb.z);
|
||
|
|
||
|
_transforma.setOrigin(_vec3_1);
|
||
|
_transformb.setOrigin(_vec3_2);
|
||
|
|
||
|
var _rotation = _transforma.getRotation();
|
||
|
_rotation.setEulerZYX(-details.axisa.z, -details.axisa.y, -details.axisa.x);
|
||
|
_transforma.setRotation(_rotation);
|
||
|
|
||
|
_rotation = _transformb.getRotation();
|
||
|
_rotation.setEulerZYX(-details.axisb.z, -details.axisb.y, -details.axisb.x);
|
||
|
_transformb.setRotation(_rotation);
|
||
|
|
||
|
constraint = new Ammo.btConeTwistConstraint(_objects[details.objecta], _objects[details.objectb], _transforma, _transformb);
|
||
|
|
||
|
constraint.setLimit(Math.PI, 0, Math.PI);
|
||
|
|
||
|
constraint.ta = _transforma;
|
||
|
constraint.tb = _transformb;
|
||
|
|
||
|
Ammo.destroy(_transforma);
|
||
|
Ammo.destroy(_transformb);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case 'dof':
|
||
|
{
|
||
|
var _transformb2 = void 0;
|
||
|
|
||
|
var _transforma2 = new Ammo.btTransform();
|
||
|
_transforma2.setIdentity();
|
||
|
|
||
|
_vec3_1.setX(details.positiona.x);
|
||
|
_vec3_1.setY(details.positiona.y);
|
||
|
_vec3_1.setZ(details.positiona.z);
|
||
|
|
||
|
_transforma2.setOrigin(_vec3_1);
|
||
|
|
||
|
var _rotation2 = _transforma2.getRotation();
|
||
|
_rotation2.setEulerZYX(-details.axisa.z, -details.axisa.y, -details.axisa.x);
|
||
|
_transforma2.setRotation(_rotation2);
|
||
|
|
||
|
if (details.objectb) {
|
||
|
_transformb2 = new Ammo.btTransform();
|
||
|
_transformb2.setIdentity();
|
||
|
|
||
|
_vec3_2.setX(details.positionb.x);
|
||
|
_vec3_2.setY(details.positionb.y);
|
||
|
_vec3_2.setZ(details.positionb.z);
|
||
|
|
||
|
_transformb2.setOrigin(_vec3_2);
|
||
|
|
||
|
_rotation2 = _transformb2.getRotation();
|
||
|
_rotation2.setEulerZYX(-details.axisb.z, -details.axisb.y, -details.axisb.x);
|
||
|
_transformb2.setRotation(_rotation2);
|
||
|
|
||
|
constraint = new Ammo.btGeneric6DofConstraint(_objects[details.objecta], _objects[details.objectb], _transforma2, _transformb2, true);
|
||
|
} else {
|
||
|
constraint = new Ammo.btGeneric6DofConstraint(_objects[details.objecta], _transforma2, true);
|
||
|
}
|
||
|
|
||
|
constraint.ta = _transforma2;
|
||
|
constraint.tb = _transformb2;
|
||
|
|
||
|
Ammo.destroy(_transforma2);
|
||
|
if (_transformb2 !== undefined) Ammo.destroy(_transformb2);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
world.addConstraint(constraint);
|
||
|
|
||
|
constraint.a = _objects[details.objecta];
|
||
|
constraint.b = _objects[details.objectb];
|
||
|
|
||
|
constraint.enableFeedback();
|
||
|
_constraints[details.id] = constraint;
|
||
|
_num_constraints++;
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE) {
|
||
|
constraintreport = new Float32Array(1 + _num_constraints * CONSTRAINTREPORT_ITEMSIZE); // message id & ( # of objects to report * # of values per object )
|
||
|
constraintreport[0] = MESSAGE_TYPES.CONSTRAINTREPORT;
|
||
|
} else constraintreport = [MESSAGE_TYPES.CONSTRAINTREPORT];
|
||
|
};
|
||
|
|
||
|
public_functions.removeConstraint = function (details) {
|
||
|
var constraint = _constraints[details.id];
|
||
|
|
||
|
if (constraint !== undefined) {
|
||
|
world.removeConstraint(constraint);
|
||
|
_constraints[details.id] = null;
|
||
|
_num_constraints--;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public_functions.constraint_setBreakingImpulseThreshold = function (details) {
|
||
|
var constraint = _constraints[details.id];
|
||
|
if (constraint !== undefined) constraint.setBreakingImpulseThreshold(details.threshold);
|
||
|
};
|
||
|
|
||
|
public_functions.simulate = function () {
|
||
|
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||
|
|
||
|
if (world) {
|
||
|
if (params.timeStep && params.timeStep < fixedTimeStep) params.timeStep = fixedTimeStep;
|
||
|
|
||
|
params.maxSubSteps = params.maxSubSteps || Math.ceil(params.timeStep / fixedTimeStep); // If maxSubSteps is not defined, keep the simulation fully up to date
|
||
|
|
||
|
world.stepSimulation(params.timeStep, params.maxSubSteps, fixedTimeStep);
|
||
|
|
||
|
if (_vehicles.length > 0) reportVehicles();
|
||
|
reportCollisions();
|
||
|
if (_constraints.length > 0) reportConstraints();
|
||
|
reportWorld();
|
||
|
if (_softbody_enabled) reportWorld_softbodies();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Constraint functions
|
||
|
public_functions.hinge_setLimits = function (params) {
|
||
|
_constraints[params.constraint].setLimit(params.low, params.high, 0, params.bias_factor, params.relaxation_factor);
|
||
|
};
|
||
|
|
||
|
public_functions.hinge_enableAngularMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.enableAngularMotor(true, params.velocity, params.acceleration);
|
||
|
constraint.a.activate();
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.hinge_disableMotor = function (params) {
|
||
|
_constraints[params.constraint].enableMotor(false);
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.slider_setLimits = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setLowerLinLimit(params.lin_lower || 0);
|
||
|
constraint.setUpperLinLimit(params.lin_upper || 0);
|
||
|
|
||
|
constraint.setLowerAngLimit(params.ang_lower || 0);
|
||
|
constraint.setUpperAngLimit(params.ang_upper || 0);
|
||
|
};
|
||
|
|
||
|
public_functions.slider_setRestitution = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setSoftnessLimLin(params.linear || 0);
|
||
|
constraint.setSoftnessLimAng(params.angular || 0);
|
||
|
};
|
||
|
|
||
|
public_functions.slider_enableLinearMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setTargetLinMotorVelocity(params.velocity);
|
||
|
constraint.setMaxLinMotorForce(params.acceleration);
|
||
|
constraint.setPoweredLinMotor(true);
|
||
|
constraint.a.activate();
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.slider_disableLinearMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setPoweredLinMotor(false);
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.slider_enableAngularMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setTargetAngMotorVelocity(params.velocity);
|
||
|
constraint.setMaxAngMotorForce(params.acceleration);
|
||
|
constraint.setPoweredAngMotor(true);
|
||
|
constraint.a.activate();
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.slider_disableAngularMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setPoweredAngMotor(false);
|
||
|
constraint.a.activate();
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.conetwist_setLimit = function (params) {
|
||
|
_constraints[params.constraint].setLimit(params.z, params.y, params.x); // ZYX order
|
||
|
};
|
||
|
|
||
|
public_functions.conetwist_enableMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.enableMotor(true);
|
||
|
constraint.a.activate();
|
||
|
constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.conetwist_setMaxMotorImpulse = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.setMaxMotorImpulse(params.max_impulse);
|
||
|
constraint.a.activate();
|
||
|
constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.conetwist_setMotorTarget = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
|
||
|
_quat.setX(params.x);
|
||
|
_quat.setY(params.y);
|
||
|
_quat.setZ(params.z);
|
||
|
_quat.setW(params.w);
|
||
|
|
||
|
constraint.setMotorTarget(_quat);
|
||
|
|
||
|
constraint.a.activate();
|
||
|
constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.conetwist_disableMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
constraint.enableMotor(false);
|
||
|
constraint.a.activate();
|
||
|
constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_setLinearLowerLimit = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
|
||
|
_vec3_1.setX(params.x);
|
||
|
_vec3_1.setY(params.y);
|
||
|
_vec3_1.setZ(params.z);
|
||
|
|
||
|
constraint.setLinearLowerLimit(_vec3_1);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_setLinearUpperLimit = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
|
||
|
_vec3_1.setX(params.x);
|
||
|
_vec3_1.setY(params.y);
|
||
|
_vec3_1.setZ(params.z);
|
||
|
|
||
|
constraint.setLinearUpperLimit(_vec3_1);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_setAngularLowerLimit = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
|
||
|
_vec3_1.setX(params.x);
|
||
|
_vec3_1.setY(params.y);
|
||
|
_vec3_1.setZ(params.z);
|
||
|
|
||
|
constraint.setAngularLowerLimit(_vec3_1);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_setAngularUpperLimit = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
|
||
|
_vec3_1.setX(params.x);
|
||
|
_vec3_1.setY(params.y);
|
||
|
_vec3_1.setZ(params.z);
|
||
|
|
||
|
constraint.setAngularUpperLimit(_vec3_1);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_enableAngularMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint];
|
||
|
|
||
|
var motor = constraint.getRotationalLimitMotor(params.which);
|
||
|
motor.set_m_enableMotor(true);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_configureAngularMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint],
|
||
|
motor = constraint.getRotationalLimitMotor(params.which);
|
||
|
|
||
|
motor.set_m_loLimit(params.low_angle);
|
||
|
motor.set_m_hiLimit(params.high_angle);
|
||
|
motor.set_m_targetVelocity(params.velocity);
|
||
|
motor.set_m_maxMotorForce(params.max_force);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
public_functions.dof_disableAngularMotor = function (params) {
|
||
|
var constraint = _constraints[params.constraint],
|
||
|
motor = constraint.getRotationalLimitMotor(params.which);
|
||
|
|
||
|
motor.set_m_enableMotor(false);
|
||
|
constraint.a.activate();
|
||
|
|
||
|
if (constraint.b) constraint.b.activate();
|
||
|
};
|
||
|
|
||
|
var reportWorld = function reportWorld() {
|
||
|
if (SUPPORT_TRANSFERABLE && worldreport.length < 2 + _num_rigidbody_objects * WORLDREPORT_ITEMSIZE) {
|
||
|
worldreport = new Float32Array(2 // message id & # objects in report
|
||
|
+ Math.ceil(_num_rigidbody_objects / REPORT_CHUNKSIZE) * REPORT_CHUNKSIZE * WORLDREPORT_ITEMSIZE // # of values needed * item size
|
||
|
);
|
||
|
|
||
|
worldreport[0] = MESSAGE_TYPES.WORLDREPORT;
|
||
|
}
|
||
|
|
||
|
worldreport[1] = _num_rigidbody_objects; // record how many objects we're reporting on
|
||
|
|
||
|
{
|
||
|
var i = 0,
|
||
|
index = _objects.length;
|
||
|
|
||
|
while (index--) {
|
||
|
var object = _objects[index];
|
||
|
|
||
|
if (object && object.type === 1) {
|
||
|
// RigidBodies.
|
||
|
// #TODO: we can't use center of mass transform when center of mass can change,
|
||
|
// but getMotionState().getWorldTransform() screws up on objects that have been moved
|
||
|
// object.getMotionState().getWorldTransform( transform );
|
||
|
// object.getMotionState().getWorldTransform(_transform);
|
||
|
|
||
|
var transform = object.getCenterOfMassTransform();
|
||
|
var origin = transform.getOrigin();
|
||
|
var rotation = transform.getRotation();
|
||
|
|
||
|
// add values to report
|
||
|
var offset = 2 + i++ * WORLDREPORT_ITEMSIZE;
|
||
|
|
||
|
worldreport[offset] = object.id;
|
||
|
|
||
|
worldreport[offset + 1] = origin.x();
|
||
|
worldreport[offset + 2] = origin.y();
|
||
|
worldreport[offset + 3] = origin.z();
|
||
|
|
||
|
worldreport[offset + 4] = rotation.x();
|
||
|
worldreport[offset + 5] = rotation.y();
|
||
|
worldreport[offset + 6] = rotation.z();
|
||
|
worldreport[offset + 7] = rotation.w();
|
||
|
|
||
|
_vector = object.getLinearVelocity();
|
||
|
worldreport[offset + 8] = _vector.x();
|
||
|
worldreport[offset + 9] = _vector.y();
|
||
|
worldreport[offset + 10] = _vector.z();
|
||
|
|
||
|
_vector = object.getAngularVelocity();
|
||
|
worldreport[offset + 11] = _vector.x();
|
||
|
worldreport[offset + 12] = _vector.y();
|
||
|
worldreport[offset + 13] = _vector.z();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE) send(worldreport.buffer, [worldreport.buffer]);else send(worldreport);
|
||
|
};
|
||
|
|
||
|
var reportWorld_softbodies = function reportWorld_softbodies() {
|
||
|
// TODO: Add SUPPORTTRANSFERABLE.
|
||
|
|
||
|
softreport = new Float32Array(2 // message id & # objects in report
|
||
|
+ _num_softbody_objects * 2 + _softbody_report_size * 6);
|
||
|
|
||
|
softreport[0] = MESSAGE_TYPES.SOFTREPORT;
|
||
|
softreport[1] = _num_softbody_objects; // record how many objects we're reporting on
|
||
|
|
||
|
{
|
||
|
var offset = 2,
|
||
|
index = _objects.length;
|
||
|
|
||
|
while (index--) {
|
||
|
var object = _objects[index];
|
||
|
|
||
|
if (object && object.type === 0) {
|
||
|
// SoftBodies.
|
||
|
|
||
|
softreport[offset] = object.id;
|
||
|
|
||
|
var offsetVert = offset + 2;
|
||
|
|
||
|
if (object.rope === true) {
|
||
|
var nodes = object.get_m_nodes();
|
||
|
var size = nodes.size();
|
||
|
softreport[offset + 1] = size;
|
||
|
|
||
|
for (var i = 0; i < size; i++) {
|
||
|
var node = nodes.at(i);
|
||
|
var vert = node.get_m_x();
|
||
|
var off = offsetVert + i * 3;
|
||
|
|
||
|
softreport[off] = vert.x();
|
||
|
softreport[off + 1] = vert.y();
|
||
|
softreport[off + 2] = vert.z();
|
||
|
}
|
||
|
|
||
|
offset += size * 3 + 2;
|
||
|
} else if (object.cloth) {
|
||
|
var _nodes = object.get_m_nodes();
|
||
|
var _size = _nodes.size();
|
||
|
softreport[offset + 1] = _size;
|
||
|
|
||
|
for (var _i3 = 0; _i3 < _size; _i3++) {
|
||
|
var _node = _nodes.at(_i3);
|
||
|
var _vert = _node.get_m_x();
|
||
|
var normal = _node.get_m_n();
|
||
|
var _off = offsetVert + _i3 * 6;
|
||
|
|
||
|
softreport[_off] = _vert.x();
|
||
|
softreport[_off + 1] = _vert.y();
|
||
|
softreport[_off + 2] = _vert.z();
|
||
|
|
||
|
softreport[_off + 3] = -normal.x();
|
||
|
softreport[_off + 4] = -normal.y();
|
||
|
softreport[_off + 5] = -normal.z();
|
||
|
}
|
||
|
|
||
|
offset += _size * 6 + 2;
|
||
|
} else {
|
||
|
var faces = object.get_m_faces();
|
||
|
var _size2 = faces.size();
|
||
|
softreport[offset + 1] = _size2;
|
||
|
|
||
|
for (var _i4 = 0; _i4 < _size2; _i4++) {
|
||
|
var face = faces.at(_i4);
|
||
|
|
||
|
var node1 = face.get_m_n(0);
|
||
|
var node2 = face.get_m_n(1);
|
||
|
var node3 = face.get_m_n(2);
|
||
|
|
||
|
var vert1 = node1.get_m_x();
|
||
|
var vert2 = node2.get_m_x();
|
||
|
var vert3 = node3.get_m_x();
|
||
|
|
||
|
var normal1 = node1.get_m_n();
|
||
|
var normal2 = node2.get_m_n();
|
||
|
var normal3 = node3.get_m_n();
|
||
|
|
||
|
var _off2 = offsetVert + _i4 * 18;
|
||
|
|
||
|
softreport[_off2] = vert1.x();
|
||
|
softreport[_off2 + 1] = vert1.y();
|
||
|
softreport[_off2 + 2] = vert1.z();
|
||
|
|
||
|
softreport[_off2 + 3] = normal1.x();
|
||
|
softreport[_off2 + 4] = normal1.y();
|
||
|
softreport[_off2 + 5] = normal1.z();
|
||
|
|
||
|
softreport[_off2 + 6] = vert2.x();
|
||
|
softreport[_off2 + 7] = vert2.y();
|
||
|
softreport[_off2 + 8] = vert2.z();
|
||
|
|
||
|
softreport[_off2 + 9] = normal2.x();
|
||
|
softreport[_off2 + 10] = normal2.y();
|
||
|
softreport[_off2 + 11] = normal2.z();
|
||
|
|
||
|
softreport[_off2 + 12] = vert3.x();
|
||
|
softreport[_off2 + 13] = vert3.y();
|
||
|
softreport[_off2 + 14] = vert3.z();
|
||
|
|
||
|
softreport[_off2 + 15] = normal3.x();
|
||
|
softreport[_off2 + 16] = normal3.y();
|
||
|
softreport[_off2 + 17] = normal3.z();
|
||
|
}
|
||
|
|
||
|
offset += _size2 * 18 + 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if (SUPPORT_TRANSFERABLE) send(softreport.buffer, [softreport.buffer]);
|
||
|
// else send(softreport);
|
||
|
send(softreport);
|
||
|
};
|
||
|
|
||
|
var reportCollisions = function reportCollisions() {
|
||
|
var dp = world.getDispatcher(),
|
||
|
num = dp.getNumManifolds();
|
||
|
// _collided = false;
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE) {
|
||
|
if (collisionreport.length < 2 + num * COLLISIONREPORT_ITEMSIZE) {
|
||
|
collisionreport = new Float32Array(2 // message id & # objects in report
|
||
|
+ Math.ceil(_num_objects / REPORT_CHUNKSIZE) * REPORT_CHUNKSIZE * COLLISIONREPORT_ITEMSIZE // # of values needed * item size
|
||
|
);
|
||
|
collisionreport[0] = MESSAGE_TYPES.COLLISIONREPORT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
collisionreport[1] = 0; // how many collisions we're reporting on
|
||
|
|
||
|
for (var i = 0; i < num; i++) {
|
||
|
var manifold = dp.getManifoldByIndexInternal(i),
|
||
|
num_contacts = manifold.getNumContacts();
|
||
|
|
||
|
if (num_contacts === 0) continue;
|
||
|
|
||
|
for (var j = 0; j < num_contacts; j++) {
|
||
|
var pt = manifold.getContactPoint(j);
|
||
|
|
||
|
// if ( pt.getDistance() < 0 ) {
|
||
|
var offset = 2 + collisionreport[1]++ * COLLISIONREPORT_ITEMSIZE;
|
||
|
collisionreport[offset] = _objects_ammo[manifold.getBody0().ptr];
|
||
|
collisionreport[offset + 1] = _objects_ammo[manifold.getBody1().ptr];
|
||
|
|
||
|
_vector = pt.get_m_normalWorldOnB();
|
||
|
collisionreport[offset + 2] = _vector.x();
|
||
|
collisionreport[offset + 3] = _vector.y();
|
||
|
collisionreport[offset + 4] = _vector.z();
|
||
|
break;
|
||
|
// }
|
||
|
// send(_objects_ammo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE) send(collisionreport.buffer, [collisionreport.buffer]);else send(collisionreport);
|
||
|
};
|
||
|
|
||
|
var reportVehicles = function reportVehicles() {
|
||
|
if (SUPPORT_TRANSFERABLE) {
|
||
|
if (vehiclereport.length < 2 + _num_wheels * VEHICLEREPORT_ITEMSIZE) {
|
||
|
vehiclereport = new Float32Array(2 // message id & # objects in report
|
||
|
+ Math.ceil(_num_wheels / REPORT_CHUNKSIZE) * REPORT_CHUNKSIZE * VEHICLEREPORT_ITEMSIZE // # of values needed * item size
|
||
|
);
|
||
|
vehiclereport[0] = MESSAGE_TYPES.VEHICLEREPORT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
var i = 0,
|
||
|
j = 0,
|
||
|
index = _vehicles.length;
|
||
|
|
||
|
while (index--) {
|
||
|
if (_vehicles[index]) {
|
||
|
var vehicle = _vehicles[index];
|
||
|
|
||
|
for (j = 0; j < vehicle.getNumWheels(); j++) {
|
||
|
// vehicle.updateWheelTransform( j, true );
|
||
|
// transform = vehicle.getWheelTransformWS( j );
|
||
|
var transform = vehicle.getWheelInfo(j).get_m_worldTransform();
|
||
|
|
||
|
var origin = transform.getOrigin();
|
||
|
var rotation = transform.getRotation();
|
||
|
|
||
|
// add values to report
|
||
|
var offset = 1 + i++ * VEHICLEREPORT_ITEMSIZE;
|
||
|
|
||
|
vehiclereport[offset] = index;
|
||
|
vehiclereport[offset + 1] = j;
|
||
|
|
||
|
vehiclereport[offset + 2] = origin.x();
|
||
|
vehiclereport[offset + 3] = origin.y();
|
||
|
vehiclereport[offset + 4] = origin.z();
|
||
|
|
||
|
vehiclereport[offset + 5] = rotation.x();
|
||
|
vehiclereport[offset + 6] = rotation.y();
|
||
|
vehiclereport[offset + 7] = rotation.z();
|
||
|
vehiclereport[offset + 8] = rotation.w();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE && j !== 0) send(vehiclereport.buffer, [vehiclereport.buffer]);else if (j !== 0) send(vehiclereport);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var reportConstraints = function reportConstraints() {
|
||
|
if (SUPPORT_TRANSFERABLE) {
|
||
|
if (constraintreport.length < 2 + _num_constraints * CONSTRAINTREPORT_ITEMSIZE) {
|
||
|
constraintreport = new Float32Array(2 // message id & # objects in report
|
||
|
+ Math.ceil(_num_constraints / REPORT_CHUNKSIZE) * REPORT_CHUNKSIZE * CONSTRAINTREPORT_ITEMSIZE // # of values needed * item size
|
||
|
);
|
||
|
constraintreport[0] = MESSAGE_TYPES.CONSTRAINTREPORT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
var offset = 0,
|
||
|
i = 0,
|
||
|
index = _constraints.lenght;
|
||
|
|
||
|
while (index--) {
|
||
|
if (_constraints[index]) {
|
||
|
var _constraint = _constraints[index];
|
||
|
var offset_body = _constraint.a;
|
||
|
var transform = _constraint.ta;
|
||
|
var origin = transform.getOrigin();
|
||
|
|
||
|
// add values to report
|
||
|
offset = 1 + i++ * CONSTRAINTREPORT_ITEMSIZE;
|
||
|
|
||
|
constraintreport[offset] = index;
|
||
|
constraintreport[offset + 1] = offset_body.id;
|
||
|
constraintreport[offset + 2] = origin.x;
|
||
|
constraintreport[offset + 3] = origin.y;
|
||
|
constraintreport[offset + 4] = origin.z;
|
||
|
constraintreport[offset + 5] = _constraint.getBreakingImpulseThreshold();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUPPORT_TRANSFERABLE && i !== 0) send(constraintreport.buffer, [constraintreport.buffer]);else if (i !== 0) send(constraintreport);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
self.onmessage = function (event) {
|
||
|
if (event.data instanceof Float32Array) {
|
||
|
// transferable object
|
||
|
switch (event.data[0]) {
|
||
|
case MESSAGE_TYPES.WORLDREPORT:
|
||
|
{
|
||
|
worldreport = new Float32Array(event.data);
|
||
|
break;
|
||
|
}
|
||
|
case MESSAGE_TYPES.COLLISIONREPORT:
|
||
|
{
|
||
|
collisionreport = new Float32Array(event.data);
|
||
|
break;
|
||
|
}
|
||
|
case MESSAGE_TYPES.VEHICLEREPORT:
|
||
|
{
|
||
|
vehiclereport = new Float32Array(event.data);
|
||
|
break;
|
||
|
}
|
||
|
case MESSAGE_TYPES.CONSTRAINTREPORT:
|
||
|
{
|
||
|
constraintreport = new Float32Array(event.data);
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
} else if (event.data.cmd && public_functions[event.data.cmd]) public_functions[event.data.cmd](event.data.params);
|
||
|
};
|
||
|
|
||
|
self.receive = self.onmessage;
|
||
|
});
|
||
|
|
||
|
var WorldModule = function (_WorldModuleBase) {
|
||
|
inherits(WorldModule, _WorldModuleBase);
|
||
|
|
||
|
function WorldModule() {
|
||
|
var _ref;
|
||
|
|
||
|
classCallCheck(this, WorldModule);
|
||
|
|
||
|
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
||
|
args[_key] = arguments[_key];
|
||
|
}
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (_ref = WorldModule.__proto__ || Object.getPrototypeOf(WorldModule)).call.apply(_ref, [this].concat(args)));
|
||
|
|
||
|
_this.worker = new PhysicsWorker();
|
||
|
_this.worker.transferableMessage = _this.worker.webkitPostMessage || _this.worker.postMessage;
|
||
|
|
||
|
_this.isLoaded = false;
|
||
|
|
||
|
var options = _this.options;
|
||
|
|
||
|
_this.loader = new Promise(function (resolve, reject) {
|
||
|
// if (options.wasm) {
|
||
|
// fetch(options.wasm)
|
||
|
// .then(response => response.arrayBuffer())
|
||
|
// .then(buffer => {
|
||
|
// options.wasmBuffer = buffer;
|
||
|
//
|
||
|
// this.execute('init', options);
|
||
|
// resolve();
|
||
|
// });
|
||
|
// } else {
|
||
|
_this.execute('init', options);
|
||
|
resolve();
|
||
|
// }
|
||
|
});
|
||
|
|
||
|
_this.loader.then(function () {
|
||
|
_this.isLoaded = true;
|
||
|
});
|
||
|
|
||
|
// Test SUPPORT_TRANSFERABLE
|
||
|
|
||
|
var ab = new ArrayBuffer(1);
|
||
|
_this.worker.transferableMessage(ab, [ab]);
|
||
|
_this.SUPPORT_TRANSFERABLE = ab.byteLength === 0;
|
||
|
|
||
|
_this.setup();
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
createClass(WorldModule, [{
|
||
|
key: 'send',
|
||
|
value: function send() {
|
||
|
var _worker;
|
||
|
|
||
|
(_worker = this.worker).transferableMessage.apply(_worker, arguments);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'receive',
|
||
|
value: function receive(callback) {
|
||
|
this.worker.addEventListener('message', callback);
|
||
|
}
|
||
|
}]);
|
||
|
return WorldModule;
|
||
|
}(WorldModuleBase);
|
||
|
|
||
|
var _class$1, _temp;
|
||
|
|
||
|
var properties = {
|
||
|
position: {
|
||
|
get: function get$$1() {
|
||
|
return this._native.position;
|
||
|
},
|
||
|
set: function set$$1(vector3) {
|
||
|
var pos = this._native.position;
|
||
|
var scope = this;
|
||
|
|
||
|
Object.defineProperties(pos, {
|
||
|
x: {
|
||
|
get: function get$$1() {
|
||
|
return this._x;
|
||
|
},
|
||
|
set: function set$$1(x) {
|
||
|
scope.__dirtyPosition = true;
|
||
|
this._x = x;
|
||
|
}
|
||
|
},
|
||
|
y: {
|
||
|
get: function get$$1() {
|
||
|
return this._y;
|
||
|
},
|
||
|
set: function set$$1(y) {
|
||
|
scope.__dirtyPosition = true;
|
||
|
this._y = y;
|
||
|
}
|
||
|
},
|
||
|
z: {
|
||
|
get: function get$$1() {
|
||
|
return this._z;
|
||
|
},
|
||
|
set: function set$$1(z) {
|
||
|
scope.__dirtyPosition = true;
|
||
|
this._z = z;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
scope.__dirtyPosition = true;
|
||
|
|
||
|
pos.copy(vector3);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
quaternion: {
|
||
|
get: function get$$1() {
|
||
|
this.__c_rot = true;
|
||
|
return this.native.quaternion;
|
||
|
},
|
||
|
set: function set$$1(quaternion) {
|
||
|
var _this = this;
|
||
|
|
||
|
var quat = this._native.quaternion,
|
||
|
native = this._native;
|
||
|
|
||
|
quat.copy(quaternion);
|
||
|
|
||
|
quat.onChange(function () {
|
||
|
if (_this.__c_rot) {
|
||
|
if (native.__dirtyRotation === true) {
|
||
|
_this.__c_rot = false;
|
||
|
native.__dirtyRotation = false;
|
||
|
}
|
||
|
native.__dirtyRotation = true;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
|
||
|
rotation: {
|
||
|
get: function get$$1() {
|
||
|
this.__c_rot = true;
|
||
|
return this._native.rotation;
|
||
|
},
|
||
|
set: function set$$1(euler) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
var rot = this._native.rotation,
|
||
|
native = this._native;
|
||
|
|
||
|
this.quaternion.copy(new three.Quaternion().setFromEuler(euler));
|
||
|
|
||
|
rot.onChange(function () {
|
||
|
if (_this2.__c_rot) {
|
||
|
_this2.quaternion.copy(new three.Quaternion().setFromEuler(rot));
|
||
|
native.__dirtyRotation = true;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function wrapPhysicsPrototype(scope) {
|
||
|
for (var key in properties) {
|
||
|
Object.defineProperty(scope, key, {
|
||
|
get: properties[key].get.bind(scope),
|
||
|
set: properties[key].set.bind(scope),
|
||
|
configurable: true,
|
||
|
enumerable: true
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function onCopy(source) {
|
||
|
wrapPhysicsPrototype(this);
|
||
|
|
||
|
var physics = this.use('physics');
|
||
|
var sourcePhysics = source.use('physics');
|
||
|
|
||
|
this.manager.modules.physics = physics.clone(this.manager);
|
||
|
|
||
|
physics.data = _extends({}, sourcePhysics.data);
|
||
|
physics.data.isSoftBodyReset = false;
|
||
|
if (physics.data.isSoftbody) physics.data.isSoftBodyReset = false;
|
||
|
|
||
|
this.position = this.position.clone();
|
||
|
this.rotation = this.rotation.clone();
|
||
|
this.quaternion = this.quaternion.clone();
|
||
|
|
||
|
return source;
|
||
|
}
|
||
|
|
||
|
function onWrap() {
|
||
|
this.position = this.position.clone();
|
||
|
this.rotation = this.rotation.clone();
|
||
|
this.quaternion = this.quaternion.clone();
|
||
|
}
|
||
|
|
||
|
var API = function () {
|
||
|
function API() {
|
||
|
classCallCheck(this, API);
|
||
|
}
|
||
|
|
||
|
createClass(API, [{
|
||
|
key: 'applyCentralImpulse',
|
||
|
value: function applyCentralImpulse(force) {
|
||
|
this.execute('applyCentralImpulse', { id: this.data.id, x: force.x, y: force.y, z: force.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'applyImpulse',
|
||
|
value: function applyImpulse(force, offset) {
|
||
|
this.execute('applyImpulse', {
|
||
|
id: this.data.id,
|
||
|
impulse_x: force.x,
|
||
|
impulse_y: force.y,
|
||
|
impulse_z: force.z,
|
||
|
x: offset.x,
|
||
|
y: offset.y,
|
||
|
z: offset.z
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'applyTorque',
|
||
|
value: function applyTorque(force) {
|
||
|
this.execute('applyTorque', {
|
||
|
id: this.data.id,
|
||
|
torque_x: force.x,
|
||
|
torque_y: force.y,
|
||
|
torque_z: force.z
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'applyCentralForce',
|
||
|
value: function applyCentralForce(force) {
|
||
|
this.execute('applyCentralForce', {
|
||
|
id: this.data.id,
|
||
|
x: force.x,
|
||
|
y: force.y,
|
||
|
z: force.z
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'applyForce',
|
||
|
value: function applyForce(force, offset) {
|
||
|
this.execute('applyForce', {
|
||
|
id: this.data.id,
|
||
|
force_x: force.x,
|
||
|
force_y: force.y,
|
||
|
force_z: force.z,
|
||
|
x: offset.x,
|
||
|
y: offset.y,
|
||
|
z: offset.z
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'getAngularVelocity',
|
||
|
value: function getAngularVelocity() {
|
||
|
return this.data.angularVelocity;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setAngularVelocity',
|
||
|
value: function setAngularVelocity(velocity) {
|
||
|
this.execute('setAngularVelocity', { id: this.data.id, x: velocity.x, y: velocity.y, z: velocity.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'getLinearVelocity',
|
||
|
value: function getLinearVelocity() {
|
||
|
return this.data.linearVelocity;
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLinearVelocity',
|
||
|
value: function setLinearVelocity(velocity) {
|
||
|
this.execute('setLinearVelocity', { id: this.data.id, x: velocity.x, y: velocity.y, z: velocity.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setAngularFactor',
|
||
|
value: function setAngularFactor(factor) {
|
||
|
this.execute('setAngularFactor', { id: this.data.id, x: factor.x, y: factor.y, z: factor.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setLinearFactor',
|
||
|
value: function setLinearFactor(factor) {
|
||
|
this.execute('setLinearFactor', { id: this.data.id, x: factor.x, y: factor.y, z: factor.z });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setDamping',
|
||
|
value: function setDamping(linear, angular) {
|
||
|
this.execute('setDamping', { id: this.data.id, linear: linear, angular: angular });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setCcdMotionThreshold',
|
||
|
value: function setCcdMotionThreshold(threshold) {
|
||
|
this.execute('setCcdMotionThreshold', { id: this.data.id, threshold: threshold });
|
||
|
}
|
||
|
}, {
|
||
|
key: 'setCcdSweptSphereRadius',
|
||
|
value: function setCcdSweptSphereRadius(radius) {
|
||
|
this.execute('setCcdSweptSphereRadius', { id: this.data.id, radius: radius });
|
||
|
}
|
||
|
}]);
|
||
|
return API;
|
||
|
}();
|
||
|
|
||
|
var _default = (_temp = _class$1 = function (_API) {
|
||
|
inherits(_default, _API);
|
||
|
|
||
|
function _default(defaults$$1, data) {
|
||
|
classCallCheck(this, _default);
|
||
|
|
||
|
var _this3 = possibleConstructorReturn(this, (_default.__proto__ || Object.getPrototypeOf(_default)).call(this));
|
||
|
|
||
|
_this3.bridge = {
|
||
|
onCopy: onCopy,
|
||
|
onWrap: onWrap
|
||
|
};
|
||
|
|
||
|
_this3.data = Object.assign(defaults$$1, data);
|
||
|
return _this3;
|
||
|
}
|
||
|
|
||
|
createClass(_default, [{
|
||
|
key: 'integrate',
|
||
|
value: function integrate(self) {
|
||
|
wrapPhysicsPrototype(this);
|
||
|
}
|
||
|
}, {
|
||
|
key: 'manager',
|
||
|
value: function manager(_manager) {
|
||
|
_manager.define('physics');
|
||
|
|
||
|
this.execute = function () {
|
||
|
var _manager$get;
|
||
|
|
||
|
return _manager.has('module:world') ? (_manager$get = _manager.get('module:world')).execute.apply(_manager$get, arguments) : function () {};
|
||
|
};
|
||
|
}
|
||
|
}, {
|
||
|
key: 'updateData',
|
||
|
value: function updateData(callback) {
|
||
|
this.bridge.geometry = function (geometry, module) {
|
||
|
if (!callback) return geometry;
|
||
|
|
||
|
var result = callback(geometry, module);
|
||
|
return result ? result : geometry;
|
||
|
};
|
||
|
}
|
||
|
}, {
|
||
|
key: 'clone',
|
||
|
value: function clone(manager) {
|
||
|
var clone = new this.constructor();
|
||
|
clone.data = _extends({}, this.data);
|
||
|
clone.bridge.geometry = this.bridge.geometry;
|
||
|
this.manager.apply(clone, [manager]);
|
||
|
|
||
|
return clone;
|
||
|
}
|
||
|
}]);
|
||
|
return _default;
|
||
|
}(API), _class$1.rigidbody = function () {
|
||
|
return {
|
||
|
touches: [],
|
||
|
linearVelocity: new three.Vector3(),
|
||
|
angularVelocity: new three.Vector3(),
|
||
|
mass: 10,
|
||
|
scale: new three.Vector3(1, 1, 1),
|
||
|
restitution: 0.3,
|
||
|
friction: 0.8,
|
||
|
damping: 0,
|
||
|
margin: 0
|
||
|
};
|
||
|
}, _class$1.softbody = function () {
|
||
|
return {
|
||
|
touches: [],
|
||
|
restitution: 0.3,
|
||
|
friction: 0.8,
|
||
|
damping: 0,
|
||
|
scale: new three.Vector3(1, 1, 1),
|
||
|
pressure: 100,
|
||
|
margin: 0,
|
||
|
klst: 0.9,
|
||
|
kvst: 0.9,
|
||
|
kast: 0.9,
|
||
|
piterations: 1,
|
||
|
viterations: 0,
|
||
|
diterations: 0,
|
||
|
citerations: 4,
|
||
|
anchorHardness: 0.7,
|
||
|
rigidHardness: 1,
|
||
|
isSoftbody: true,
|
||
|
isSoftBodyReset: false
|
||
|
};
|
||
|
}, _class$1.rope = function () {
|
||
|
return {
|
||
|
touches: [],
|
||
|
friction: 0.8,
|
||
|
scale: new three.Vector3(1, 1, 1),
|
||
|
damping: 0,
|
||
|
margin: 0,
|
||
|
klst: 0.9,
|
||
|
kvst: 0.9,
|
||
|
kast: 0.9,
|
||
|
piterations: 1,
|
||
|
viterations: 0,
|
||
|
diterations: 0,
|
||
|
citerations: 4,
|
||
|
anchorHardness: 0.7,
|
||
|
rigidHardness: 1,
|
||
|
isSoftbody: true
|
||
|
};
|
||
|
}, _class$1.cloth = function () {
|
||
|
return {
|
||
|
touches: [],
|
||
|
friction: 0.8,
|
||
|
damping: 0,
|
||
|
margin: 0,
|
||
|
scale: new three.Vector3(1, 1, 1),
|
||
|
klst: 0.9,
|
||
|
kvst: 0.9,
|
||
|
kast: 0.9,
|
||
|
piterations: 1,
|
||
|
viterations: 0,
|
||
|
diterations: 0,
|
||
|
citerations: 4,
|
||
|
anchorHardness: 0.7,
|
||
|
rigidHardness: 1
|
||
|
};
|
||
|
}, _temp);
|
||
|
|
||
|
var BoxModule = function (_PhysicsModule) {
|
||
|
inherits(BoxModule, _PhysicsModule);
|
||
|
|
||
|
function BoxModule(params) {
|
||
|
classCallCheck(this, BoxModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (BoxModule.__proto__ || Object.getPrototypeOf(BoxModule)).call(this, _extends({
|
||
|
type: 'box'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
data.width = data.width || geometry.boundingBox.max.x - geometry.boundingBox.min.x;
|
||
|
data.height = data.height || geometry.boundingBox.max.y - geometry.boundingBox.min.y;
|
||
|
data.depth = data.depth || geometry.boundingBox.max.z - geometry.boundingBox.min.z;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return BoxModule;
|
||
|
}(_default);
|
||
|
|
||
|
var CompoundModule = function (_PhysicsModule) {
|
||
|
inherits(CompoundModule, _PhysicsModule);
|
||
|
|
||
|
function CompoundModule(params) {
|
||
|
classCallCheck(this, CompoundModule);
|
||
|
return possibleConstructorReturn(this, (CompoundModule.__proto__ || Object.getPrototypeOf(CompoundModule)).call(this, _extends({
|
||
|
type: 'compound'
|
||
|
}, _default.rigidbody()), params));
|
||
|
}
|
||
|
|
||
|
return CompoundModule;
|
||
|
}(_default);
|
||
|
|
||
|
// TODO: Test CapsuleModule in action.
|
||
|
var CapsuleModule = function (_PhysicsModule) {
|
||
|
inherits(CapsuleModule, _PhysicsModule);
|
||
|
|
||
|
function CapsuleModule(params) {
|
||
|
classCallCheck(this, CapsuleModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (CapsuleModule.__proto__ || Object.getPrototypeOf(CapsuleModule)).call(this, _extends({
|
||
|
type: 'capsule'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
data.width = data.width || geometry.boundingBox.max.x - geometry.boundingBox.min.x;
|
||
|
data.height = data.height || geometry.boundingBox.max.y - geometry.boundingBox.min.y;
|
||
|
data.depth = data.depth || geometry.boundingBox.max.z - geometry.boundingBox.min.z;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return CapsuleModule;
|
||
|
}(_default);
|
||
|
|
||
|
var ConcaveModule = function (_PhysicsModule) {
|
||
|
inherits(ConcaveModule, _PhysicsModule);
|
||
|
|
||
|
function ConcaveModule(params) {
|
||
|
classCallCheck(this, ConcaveModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (ConcaveModule.__proto__ || Object.getPrototypeOf(ConcaveModule)).call(this, _extends({
|
||
|
type: 'concave'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
data.data = _this.geometryProcessor(geometry);
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
createClass(ConcaveModule, [{
|
||
|
key: 'geometryProcessor',
|
||
|
value: function geometryProcessor(geometry) {
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
var data = geometry.isBufferGeometry ? geometry.attributes.position.array : new Float32Array(geometry.faces.length * 9);
|
||
|
|
||
|
if (!geometry.isBufferGeometry) {
|
||
|
var vertices = geometry.vertices;
|
||
|
|
||
|
for (var i = 0; i < geometry.faces.length; i++) {
|
||
|
var face = geometry.faces[i];
|
||
|
|
||
|
var vA = vertices[face.a];
|
||
|
var vB = vertices[face.b];
|
||
|
var vC = vertices[face.c];
|
||
|
|
||
|
var i9 = i * 9;
|
||
|
|
||
|
data[i9] = vA.x;
|
||
|
data[i9 + 1] = vA.y;
|
||
|
data[i9 + 2] = vA.z;
|
||
|
|
||
|
data[i9 + 3] = vB.x;
|
||
|
data[i9 + 4] = vB.y;
|
||
|
data[i9 + 5] = vB.z;
|
||
|
|
||
|
data[i9 + 6] = vC.x;
|
||
|
data[i9 + 7] = vC.y;
|
||
|
data[i9 + 8] = vC.z;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return data;
|
||
|
}
|
||
|
}]);
|
||
|
return ConcaveModule;
|
||
|
}(_default);
|
||
|
|
||
|
var ConeModule = function (_PhysicsModule) {
|
||
|
inherits(ConeModule, _PhysicsModule);
|
||
|
|
||
|
function ConeModule(params) {
|
||
|
classCallCheck(this, ConeModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (ConeModule.__proto__ || Object.getPrototypeOf(ConeModule)).call(this, _extends({
|
||
|
type: 'cone'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
data.radius = data.radius || (geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2;
|
||
|
data.height = data.height || geometry.boundingBox.max.y - geometry.boundingBox.min.y;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return ConeModule;
|
||
|
}(_default);
|
||
|
|
||
|
var ConvexModule = function (_PhysicsModule) {
|
||
|
inherits(ConvexModule, _PhysicsModule);
|
||
|
|
||
|
function ConvexModule(params) {
|
||
|
classCallCheck(this, ConvexModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (ConvexModule.__proto__ || Object.getPrototypeOf(ConvexModule)).call(this, _extends({
|
||
|
type: 'convex'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
if (!geometry.isBufferGeometry) geometry._bufferGeometry = new three.BufferGeometry().fromGeometry(geometry);
|
||
|
|
||
|
data.data = geometry.isBufferGeometry ? geometry.attributes.position.array : geometry._bufferGeometry.attributes.position.array;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return ConvexModule;
|
||
|
}(_default);
|
||
|
|
||
|
var CylinderModule = function (_PhysicsModule) {
|
||
|
inherits(CylinderModule, _PhysicsModule);
|
||
|
|
||
|
function CylinderModule(params) {
|
||
|
classCallCheck(this, CylinderModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (CylinderModule.__proto__ || Object.getPrototypeOf(CylinderModule)).call(this, _extends({
|
||
|
type: 'cylinder'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
data.width = data.width || geometry.boundingBox.max.x - geometry.boundingBox.min.x;
|
||
|
data.height = data.height || geometry.boundingBox.max.y - geometry.boundingBox.min.y;
|
||
|
data.depth = data.depth || geometry.boundingBox.max.z - geometry.boundingBox.min.z;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return CylinderModule;
|
||
|
}(_default);
|
||
|
|
||
|
var HeightfieldModule = function (_PhysicsModule) {
|
||
|
inherits(HeightfieldModule, _PhysicsModule);
|
||
|
|
||
|
function HeightfieldModule(params) {
|
||
|
classCallCheck(this, HeightfieldModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (HeightfieldModule.__proto__ || Object.getPrototypeOf(HeightfieldModule)).call(this, _extends({
|
||
|
type: 'heightfield',
|
||
|
size: new three.Vector2(1, 1),
|
||
|
autoAlign: false
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
var _data$size = data.size,
|
||
|
xdiv = _data$size.x,
|
||
|
ydiv = _data$size.y;
|
||
|
|
||
|
var verts = geometry.isBufferGeometry ? geometry.attributes.position.array : geometry.vertices;
|
||
|
var size = geometry.isBufferGeometry ? verts.length / 3 : verts.length;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
var xsize = geometry.boundingBox.max.x - geometry.boundingBox.min.x;
|
||
|
var ysize = geometry.boundingBox.max.z - geometry.boundingBox.min.z;
|
||
|
|
||
|
data.xpts = typeof xdiv === 'undefined' ? Math.sqrt(size) : xdiv + 1;
|
||
|
data.ypts = typeof ydiv === 'undefined' ? Math.sqrt(size) : ydiv + 1;
|
||
|
|
||
|
// note - this assumes our plane geometry is square, unless we pass in specific xdiv and ydiv
|
||
|
data.absMaxHeight = Math.max(geometry.boundingBox.max.y, Math.abs(geometry.boundingBox.min.y));
|
||
|
|
||
|
var points = new Float32Array(size),
|
||
|
xpts = data.xpts,
|
||
|
ypts = data.ypts;
|
||
|
|
||
|
while (size--) {
|
||
|
var vNum = size % xpts + (ypts - Math.round(size / xpts - size % xpts / xpts) - 1) * ypts;
|
||
|
|
||
|
if (geometry.isBufferGeometry) points[size] = verts[vNum * 3 + 1];else points[size] = verts[vNum].y;
|
||
|
}
|
||
|
|
||
|
data.points = points;
|
||
|
|
||
|
data.scale.multiply(new three.Vector3(xsize / (xpts - 1), 1, ysize / (ypts - 1)));
|
||
|
|
||
|
if (data.autoAlign) geometry.translate(xsize / -2, 0, ysize / -2);
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return HeightfieldModule;
|
||
|
}(_default);
|
||
|
|
||
|
var PlaneModule = function (_PhysicsModule) {
|
||
|
inherits(PlaneModule, _PhysicsModule);
|
||
|
|
||
|
function PlaneModule(params) {
|
||
|
classCallCheck(this, PlaneModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (PlaneModule.__proto__ || Object.getPrototypeOf(PlaneModule)).call(this, _extends({
|
||
|
type: 'plane'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingBox) geometry.computeBoundingBox();
|
||
|
|
||
|
data.width = data.width || geometry.boundingBox.max.x - geometry.boundingBox.min.x;
|
||
|
data.height = data.height || geometry.boundingBox.max.y - geometry.boundingBox.min.y;
|
||
|
data.normal = data.normal || geometry.faces[0].normal.clone();
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return PlaneModule;
|
||
|
}(_default);
|
||
|
|
||
|
var SphereModule = function (_PhysicsModule) {
|
||
|
inherits(SphereModule, _PhysicsModule);
|
||
|
|
||
|
function SphereModule(params) {
|
||
|
classCallCheck(this, SphereModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (SphereModule.__proto__ || Object.getPrototypeOf(SphereModule)).call(this, _extends({
|
||
|
type: 'sphere'
|
||
|
}, _default.rigidbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.boundingSphere) geometry.computeBoundingSphere();
|
||
|
data.radius = data.radius || geometry.boundingSphere.radius;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
return SphereModule;
|
||
|
}(_default);
|
||
|
|
||
|
var SoftbodyModule = function (_PhysicsModule) {
|
||
|
inherits(SoftbodyModule, _PhysicsModule);
|
||
|
|
||
|
function SoftbodyModule(params) {
|
||
|
classCallCheck(this, SoftbodyModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (SoftbodyModule.__proto__ || Object.getPrototypeOf(SoftbodyModule)).call(this, _extends({
|
||
|
type: 'softTrimesh'
|
||
|
}, _default.softbody()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
var idxGeometry = geometry.isBufferGeometry ? geometry : function () {
|
||
|
geometry.mergeVertices();
|
||
|
|
||
|
var bufferGeometry = new three.BufferGeometry();
|
||
|
|
||
|
bufferGeometry.addAttribute('position', new three.BufferAttribute(new Float32Array(geometry.vertices.length * 3), 3).copyVector3sArray(geometry.vertices));
|
||
|
|
||
|
bufferGeometry.setIndex(new three.BufferAttribute(new (geometry.faces.length * 3 > 65535 ? Uint32Array : Uint16Array)(geometry.faces.length * 3), 1).copyIndicesArray(geometry.faces));
|
||
|
|
||
|
return bufferGeometry;
|
||
|
}();
|
||
|
|
||
|
data.aVertices = idxGeometry.attributes.position.array;
|
||
|
data.aIndices = idxGeometry.index.array;
|
||
|
|
||
|
return new three.BufferGeometry().fromGeometry(geometry);
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
createClass(SoftbodyModule, [{
|
||
|
key: 'appendAnchor',
|
||
|
value: function appendAnchor(object, node) {
|
||
|
var influence = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
||
|
var collisionBetweenLinkedBodies = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
||
|
|
||
|
var o1 = this.data.id;
|
||
|
var o2 = object.use('physics').data.id;
|
||
|
|
||
|
this.execute('appendAnchor', {
|
||
|
obj: o1,
|
||
|
obj2: o2,
|
||
|
node: node,
|
||
|
influence: influence,
|
||
|
collisionBetweenLinkedBodies: collisionBetweenLinkedBodies
|
||
|
});
|
||
|
}
|
||
|
}]);
|
||
|
return SoftbodyModule;
|
||
|
}(_default);
|
||
|
|
||
|
function arrayMax(array) {
|
||
|
if (array.length === 0) return -Infinity;
|
||
|
|
||
|
var max = array[0];
|
||
|
|
||
|
for (var i = 1, l = array.length; i < l; ++i) {
|
||
|
if (array[i] > max) max = array[i];
|
||
|
}
|
||
|
|
||
|
return max;
|
||
|
}
|
||
|
|
||
|
var ClothModule = function (_PhysicsModule) {
|
||
|
inherits(ClothModule, _PhysicsModule);
|
||
|
|
||
|
function ClothModule(params) {
|
||
|
classCallCheck(this, ClothModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (ClothModule.__proto__ || Object.getPrototypeOf(ClothModule)).call(this, _extends({
|
||
|
type: 'softClothMesh'
|
||
|
}, _default.cloth()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
var geomParams = geometry.parameters;
|
||
|
|
||
|
var geom = geometry.isBufferGeometry ? geometry : function () {
|
||
|
geometry.mergeVertices();
|
||
|
|
||
|
var bufferGeometry = new three.BufferGeometry();
|
||
|
|
||
|
bufferGeometry.addAttribute('position', new three.BufferAttribute(new Float32Array(geometry.vertices.length * 3), 3).copyVector3sArray(geometry.vertices));
|
||
|
|
||
|
var faces = geometry.faces,
|
||
|
facesLength = faces.length,
|
||
|
uvs = geometry.faceVertexUvs[0];
|
||
|
|
||
|
var normalsArray = new Float32Array(facesLength * 3);
|
||
|
// const uvsArray = new Array(geometry.vertices.length * 2);
|
||
|
var uvsArray = new Float32Array(facesLength * 2);
|
||
|
var faceArray = new Uint32Array(facesLength * 3);
|
||
|
|
||
|
for (var i = 0; i < facesLength; i++) {
|
||
|
var i3 = i * 3;
|
||
|
var normal = faces[i].normal || new Vector3();
|
||
|
|
||
|
faceArray[i3] = faces[i].a;
|
||
|
faceArray[i3 + 1] = faces[i].b;
|
||
|
faceArray[i3 + 2] = faces[i].c;
|
||
|
|
||
|
normalsArray[i3] = normal.x;
|
||
|
normalsArray[i3 + 1] = normal.y;
|
||
|
normalsArray[i3 + 2] = normal.z;
|
||
|
|
||
|
uvsArray[faces[i].a * 2 + 0] = uvs[i][0].x; // a
|
||
|
uvsArray[faces[i].a * 2 + 1] = uvs[i][0].y;
|
||
|
|
||
|
uvsArray[faces[i].b * 2 + 0] = uvs[i][1].x; // b
|
||
|
uvsArray[faces[i].b * 2 + 1] = uvs[i][1].y;
|
||
|
|
||
|
uvsArray[faces[i].c * 2 + 0] = uvs[i][2].x; // c
|
||
|
uvsArray[faces[i].c * 2 + 1] = uvs[i][2].y;
|
||
|
}
|
||
|
|
||
|
bufferGeometry.addAttribute('normal', new three.BufferAttribute(normalsArray, 3));
|
||
|
|
||
|
bufferGeometry.addAttribute('uv', new three.BufferAttribute(uvsArray, 2));
|
||
|
|
||
|
bufferGeometry.setIndex(new three.BufferAttribute(new (arrayMax(faces) * 3 > 65535 ? Uint32Array : Uint16Array)(facesLength * 3), 1).copyIndicesArray(faces));
|
||
|
|
||
|
return bufferGeometry;
|
||
|
}();
|
||
|
|
||
|
var verts = geom.attributes.position.array;
|
||
|
|
||
|
if (!geomParams.widthSegments) geomParams.widthSegments = 1;
|
||
|
if (!geomParams.heightSegments) geomParams.heightSegments = 1;
|
||
|
|
||
|
var idx00 = 0;
|
||
|
var idx01 = geomParams.widthSegments;
|
||
|
var idx10 = (geomParams.heightSegments + 1) * (geomParams.widthSegments + 1) - (geomParams.widthSegments + 1);
|
||
|
var idx11 = verts.length / 3 - 1;
|
||
|
|
||
|
data.corners = [verts[idx01 * 3], verts[idx01 * 3 + 1], verts[idx01 * 3 + 2], // ╗
|
||
|
verts[idx00 * 3], verts[idx00 * 3 + 1], verts[idx00 * 3 + 2], // ╔
|
||
|
verts[idx11 * 3], verts[idx11 * 3 + 1], verts[idx11 * 3 + 2], // ╝
|
||
|
verts[idx10 * 3], verts[idx10 * 3 + 1], verts[idx10 * 3 + 2]];
|
||
|
|
||
|
data.segments = [geomParams.widthSegments + 1, geomParams.heightSegments + 1];
|
||
|
|
||
|
return geom;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
createClass(ClothModule, [{
|
||
|
key: 'appendAnchor',
|
||
|
value: function appendAnchor(object, node, influence) {
|
||
|
var collisionBetweenLinkedBodies = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
||
|
|
||
|
var o1 = this.data.id;
|
||
|
var o2 = object.use('physics').data.id;
|
||
|
|
||
|
this.execute('appendAnchor', {
|
||
|
obj: o1,
|
||
|
obj2: o2,
|
||
|
node: node,
|
||
|
influence: influence,
|
||
|
collisionBetweenLinkedBodies: collisionBetweenLinkedBodies
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'linkNodes',
|
||
|
value: function linkNodes(object, n1, n2, modifier) {
|
||
|
var self = this.data.id;
|
||
|
var body = object.use('physics').data.id;
|
||
|
|
||
|
this.execute('linkNodes', {
|
||
|
self: self,
|
||
|
body: body,
|
||
|
n1: n1, // self node
|
||
|
n2: n2, // body node
|
||
|
modifier: modifier
|
||
|
});
|
||
|
}
|
||
|
}, {
|
||
|
key: 'appendLinearJoint',
|
||
|
value: function appendLinearJoint(object, specs) {
|
||
|
var self = this.data.id;
|
||
|
var body = object.use('physics').data.id;
|
||
|
|
||
|
this.execute('appendLinearJoint', {
|
||
|
self: self,
|
||
|
body: body,
|
||
|
specs: specs
|
||
|
});
|
||
|
}
|
||
|
}]);
|
||
|
return ClothModule;
|
||
|
}(_default);
|
||
|
|
||
|
var RopeModule = function (_PhysicsModule) {
|
||
|
inherits(RopeModule, _PhysicsModule);
|
||
|
|
||
|
function RopeModule(params) {
|
||
|
classCallCheck(this, RopeModule);
|
||
|
|
||
|
var _this = possibleConstructorReturn(this, (RopeModule.__proto__ || Object.getPrototypeOf(RopeModule)).call(this, _extends({
|
||
|
type: 'softRopeMesh'
|
||
|
}, _default.rope()), params));
|
||
|
|
||
|
_this.updateData(function (geometry, _ref) {
|
||
|
var data = _ref.data;
|
||
|
|
||
|
if (!geometry.isBufferGeometry) {
|
||
|
geometry = function () {
|
||
|
var buff = new three.BufferGeometry();
|
||
|
|
||
|
buff.addAttribute('position', new three.BufferAttribute(new Float32Array(geometry.vertices.length * 3), 3).copyVector3sArray(geometry.vertices));
|
||
|
|
||
|
return buff;
|
||
|
}();
|
||
|
}
|
||
|
|
||
|
var length = geometry.attributes.position.array.length / 3;
|
||
|
var vert = function vert(n) {
|
||
|
return new three.Vector3().fromArray(geometry.attributes.position.array, n * 3);
|
||
|
};
|
||
|
|
||
|
var v1 = vert(0);
|
||
|
var v2 = vert(length - 1);
|
||
|
|
||
|
data.data = [v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, length];
|
||
|
|
||
|
return geometry;
|
||
|
});
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
createClass(RopeModule, [{
|
||
|
key: 'appendAnchor',
|
||
|
value: function appendAnchor(object, node, influence) {
|
||
|
var collisionBetweenLinkedBodies = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
||
|
|
||
|
var o1 = this.data.id;
|
||
|
var o2 = object.use('physics').data.id;
|
||
|
|
||
|
this.execute('appendAnchor', {
|
||
|
obj: o1,
|
||
|
obj2: o2,
|
||
|
node: node,
|
||
|
influence: influence,
|
||
|
collisionBetweenLinkedBodies: collisionBetweenLinkedBodies
|
||
|
});
|
||
|
}
|
||
|
}]);
|
||
|
return RopeModule;
|
||
|
}(_default);
|
||
|
|
||
|
var _class$2, _temp$1;
|
||
|
|
||
|
var PI_2 = Math.PI / 2;
|
||
|
|
||
|
// TODO: Fix DOM
|
||
|
function FirstPersonControlsSolver(camera, mesh, params) {
|
||
|
var _this = this;
|
||
|
|
||
|
var velocityFactor = 1;
|
||
|
var runVelocity = 0.25;
|
||
|
|
||
|
mesh.use('physics').setAngularFactor({ x: 0, y: 0, z: 0 });
|
||
|
camera.position.set(0, 0, 0);
|
||
|
|
||
|
/* Init */
|
||
|
var player = mesh,
|
||
|
pitchObject = new three.Object3D();
|
||
|
|
||
|
pitchObject.add(camera.native);
|
||
|
|
||
|
var yawObject = new three.Object3D();
|
||
|
|
||
|
yawObject.position.y = params.ypos; // eyes are 2 meters above the ground
|
||
|
yawObject.add(pitchObject);
|
||
|
|
||
|
var quat = new three.Quaternion();
|
||
|
|
||
|
var canJump = false,
|
||
|
|
||
|
// Moves.
|
||
|
moveForward = false,
|
||
|
moveBackward = false,
|
||
|
moveLeft = false,
|
||
|
moveRight = false;
|
||
|
|
||
|
player.on('collision', function (otherObject, v, r, contactNormal) {
|
||
|
console.log(contactNormal.y);
|
||
|
if (contactNormal.y < 0.5) // Use a "good" threshold value between 0 and 1 here!
|
||
|
canJump = true;
|
||
|
});
|
||
|
|
||
|
var onMouseMove = function onMouseMove(event) {
|
||
|
if (_this.enabled === false) return;
|
||
|
|
||
|
var movementX = typeof event.movementX === 'number' ? event.movementX : typeof event.mozMovementX === 'number' ? event.mozMovementX : typeof event.getMovementX === 'function' ? event.getMovementX() : 0;
|
||
|
var movementY = typeof event.movementY === 'number' ? event.movementY : typeof event.mozMovementY === 'number' ? event.mozMovementY : typeof event.getMovementY === 'function' ? event.getMovementY() : 0;
|
||
|
|
||
|
yawObject.rotation.y -= movementX * 0.002;
|
||
|
pitchObject.rotation.x -= movementY * 0.002;
|
||
|
|
||
|
pitchObject.rotation.x = Math.max(-PI_2, Math.min(PI_2, pitchObject.rotation.x));
|
||
|
};
|
||
|
|
||
|
var physics = player.use('physics');
|
||
|
|
||
|
var onKeyDown = function onKeyDown(event) {
|
||
|
switch (event.keyCode) {
|
||
|
case 38: // up
|
||
|
case 87:
|
||
|
// w
|
||
|
moveForward = true;
|
||
|
break;
|
||
|
|
||
|
case 37: // left
|
||
|
case 65:
|
||
|
// a
|
||
|
moveLeft = true;
|
||
|
break;
|
||
|
|
||
|
case 40: // down
|
||
|
case 83:
|
||
|
// s
|
||
|
moveBackward = true;
|
||
|
break;
|
||
|
|
||
|
case 39: // right
|
||
|
case 68:
|
||
|
// d
|
||
|
moveRight = true;
|
||
|
break;
|
||
|
|
||
|
case 32:
|
||
|
// space
|
||
|
console.log(canJump);
|
||
|
if (canJump === true) physics.applyCentralImpulse({ x: 0, y: 300, z: 0 });
|
||
|
canJump = false;
|
||
|
break;
|
||
|
|
||
|
case 16:
|
||
|
// shift
|
||
|
runVelocity = 0.5;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var onKeyUp = function onKeyUp(event) {
|
||
|
switch (event.keyCode) {
|
||
|
case 38: // up
|
||
|
case 87:
|
||
|
// w
|
||
|
moveForward = false;
|
||
|
break;
|
||
|
|
||
|
case 37: // left
|
||
|
case 65:
|
||
|
// a
|
||
|
moveLeft = false;
|
||
|
break;
|
||
|
|
||
|
case 40: // down
|
||
|
case 83:
|
||
|
// a
|
||
|
moveBackward = false;
|
||
|
break;
|
||
|
|
||
|
case 39: // right
|
||
|
case 68:
|
||
|
// d
|
||
|
moveRight = false;
|
||
|
break;
|
||
|
|
||
|
case 16:
|
||
|
// shift
|
||
|
runVelocity = 0.25;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
}
|
||
|
};
|
||
|
|
||
|
document.body.addEventListener('mousemove', onMouseMove, false);
|
||
|
document.body.addEventListener('keydown', onKeyDown, false);
|
||
|
document.body.addEventListener('keyup', onKeyUp, false);
|
||
|
|
||
|
this.enabled = false;
|
||
|
this.getObject = function () {
|
||
|
return yawObject;
|
||
|
};
|
||
|
|
||
|
this.getDirection = function (targetVec) {
|
||
|
targetVec.set(0, 0, -1);
|
||
|
quat.multiplyVector3(targetVec);
|
||
|
};
|
||
|
|
||
|
// Moves the camera to the Physi.js object position
|
||
|
// and adds velocity to the object if the run key is down.
|
||
|
var inputVelocity = new three.Vector3(),
|
||
|
euler = new three.Euler();
|
||
|
|
||
|
this.update = function (delta) {
|
||
|
if (_this.enabled === false) return;
|
||
|
|
||
|
delta = delta || 0.5;
|
||
|
delta = Math.min(delta, 0.5, delta);
|
||
|
|
||
|
inputVelocity.set(0, 0, 0);
|
||
|
|
||
|
var speed = velocityFactor * delta * params.speed * runVelocity;
|
||
|
|
||
|
if (moveForward) inputVelocity.z = -speed;
|
||
|
if (moveBackward) inputVelocity.z = speed;
|
||
|
if (moveLeft) inputVelocity.x = -speed;
|
||
|
if (moveRight) inputVelocity.x = speed;
|
||
|
|
||
|
// Convert velocity to world coordinates
|
||
|
euler.x = pitchObject.rotation.x;
|
||
|
euler.y = yawObject.rotation.y;
|
||
|
euler.order = 'XYZ';
|
||
|
|
||
|
quat.setFromEuler(euler);
|
||
|
|
||
|
inputVelocity.applyQuaternion(quat);
|
||
|
|
||
|
physics.applyCentralImpulse({ x: inputVelocity.x, y: 0, z: inputVelocity.z });
|
||
|
physics.setAngularVelocity({ x: inputVelocity.z, y: 0, z: -inputVelocity.x });
|
||
|
physics.setAngularFactor({ x: 0, y: 0, z: 0 });
|
||
|
};
|
||
|
|
||
|
player.on('physics:added', function () {
|
||
|
player.manager.get('module:world').addEventListener('update', function () {
|
||
|
if (_this.enabled === false) return;
|
||
|
yawObject.position.copy(player.position);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var FirstPersonModule = (_temp$1 = _class$2 = function () {
|
||
|
function FirstPersonModule(object) {
|
||
|
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||
|
classCallCheck(this, FirstPersonModule);
|
||
|
|
||
|
this.object = object;
|
||
|
this.params = params;
|
||
|
|
||
|
if (!this.params.block) {
|
||
|
this.params.block = document.getElementById('blocker');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createClass(FirstPersonModule, [{
|
||
|
key: 'manager',
|
||
|
value: function manager(_manager) {
|
||
|
var _this2 = this;
|
||
|
|
||
|
this.controls = new FirstPersonControlsSolver(_manager.get('camera'), this.object, this.params);
|
||
|
|
||
|
if ('pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document) {
|
||
|
var element = document.body;
|
||
|
|
||
|
var pointerlockchange = function pointerlockchange() {
|
||
|
if (document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element) {
|
||
|
_this2.controls.enabled = true;
|
||
|
_this2.params.block.style.display = 'none';
|
||
|
} else {
|
||
|
_this2.controls.enabled = false;
|
||
|
_this2.params.block.style.display = 'block';
|
||
|
}
|
||
|
};
|
||
|
|
||
|
document.addEventListener('pointerlockchange', pointerlockchange, false);
|
||
|
document.addEventListener('mozpointerlockchange', pointerlockchange, false);
|
||
|
document.addEventListener('webkitpointerlockchange', pointerlockchange, false);
|
||
|
|
||
|
var pointerlockerror = function pointerlockerror() {
|
||
|
console.warn('Pointer lock error.');
|
||
|
};
|
||
|
|
||
|
document.addEventListener('pointerlockerror', pointerlockerror, false);
|
||
|
document.addEventListener('mozpointerlockerror', pointerlockerror, false);
|
||
|
document.addEventListener('webkitpointerlockerror', pointerlockerror, false);
|
||
|
|
||
|
document.querySelector('body').addEventListener('click', function () {
|
||
|
element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;
|
||
|
|
||
|
element.requestFullscreen = element.requestFullscreen || element.mozRequestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen;
|
||
|
|
||
|
if (/Firefox/i.test(navigator.userAgent)) {
|
||
|
var fullscreenchange = function fullscreenchange() {
|
||
|
if (document.fullscreenElement === element || document.mozFullscreenElement === element || document.mozFullScreenElement === element) {
|
||
|
document.removeEventListener('fullscreenchange', fullscreenchange);
|
||
|
document.removeEventListener('mozfullscreenchange', fullscreenchange);
|
||
|
|
||
|
element.requestPointerLock();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
document.addEventListener('fullscreenchange', fullscreenchange, false);
|
||
|
document.addEventListener('mozfullscreenchange', fullscreenchange, false);
|
||
|
|
||
|
element.requestFullscreen();
|
||
|
} else element.requestPointerLock();
|
||
|
});
|
||
|
} else console.warn('Your browser does not support the PointerLock');
|
||
|
|
||
|
_manager.get('scene').add(this.controls.getObject());
|
||
|
}
|
||
|
}, {
|
||
|
key: 'integrate',
|
||
|
value: function integrate(self) {
|
||
|
var updateProcessor = function updateProcessor(c) {
|
||
|
self.controls.update(c.getDelta());
|
||
|
};
|
||
|
|
||
|
self.updateLoop = new whs.Loop(updateProcessor).start(this);
|
||
|
}
|
||
|
}]);
|
||
|
return FirstPersonModule;
|
||
|
}(), _class$2.defaults = {
|
||
|
block: null,
|
||
|
speed: 1,
|
||
|
ypos: 1
|
||
|
}, _temp$1);
|
||
|
|
||
|
exports.getEulerXYZFromQuaternion = getEulerXYZFromQuaternion;
|
||
|
exports.getQuatertionFromEuler = getQuatertionFromEuler;
|
||
|
exports.convertWorldPositionToObject = convertWorldPositionToObject;
|
||
|
exports.addObjectChildren = addObjectChildren;
|
||
|
exports.MESSAGE_TYPES = MESSAGE_TYPES;
|
||
|
exports.REPORT_ITEMSIZE = REPORT_ITEMSIZE;
|
||
|
exports.COLLISIONREPORT_ITEMSIZE = COLLISIONREPORT_ITEMSIZE;
|
||
|
exports.VEHICLEREPORT_ITEMSIZE = VEHICLEREPORT_ITEMSIZE;
|
||
|
exports.CONSTRAINTREPORT_ITEMSIZE = CONSTRAINTREPORT_ITEMSIZE;
|
||
|
exports.temp1Vector3 = temp1Vector3;
|
||
|
exports.temp2Vector3 = temp2Vector3;
|
||
|
exports.temp1Matrix4 = temp1Matrix4;
|
||
|
exports.temp1Quat = temp1Quat;
|
||
|
exports.Eventable = Eventable;
|
||
|
exports.ConeTwistConstraint = ConeTwistConstraint;
|
||
|
exports.HingeConstraint = HingeConstraint;
|
||
|
exports.PointConstraint = PointConstraint;
|
||
|
exports.SliderConstraint = SliderConstraint;
|
||
|
exports.DOFConstraint = DOFConstraint;
|
||
|
exports.WorldModule = WorldModule;
|
||
|
exports.BoxModule = BoxModule;
|
||
|
exports.CompoundModule = CompoundModule;
|
||
|
exports.CapsuleModule = CapsuleModule;
|
||
|
exports.ConcaveModule = ConcaveModule;
|
||
|
exports.ConeModule = ConeModule;
|
||
|
exports.ConvexModule = ConvexModule;
|
||
|
exports.CylinderModule = CylinderModule;
|
||
|
exports.HeightfieldModule = HeightfieldModule;
|
||
|
exports.PlaneModule = PlaneModule;
|
||
|
exports.SphereModule = SphereModule;
|
||
|
exports.SoftbodyModule = SoftbodyModule;
|
||
|
exports.ClothModule = ClothModule;
|
||
|
exports.RopeModule = RopeModule;
|
||
|
exports.FirstPersonModule = FirstPersonModule;
|
||
|
|
||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||
|
|
||
|
})));
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGh5c2ljcy1tb2R1bGUuanMubWFwIiwic291cmNlcyI6WyIuLi9zcmMvYXBpLmpzIiwiLi4vc3JjL2V2ZW50YWJsZS5qcyIsIi4uL3NyYy9jb25zdHJhaW50cy9Db25lVHdpc3RDb25zdHJhaW50LmpzIiwiLi4vc3JjL2NvbnN0cmFpbnRzL0hpbmdlQ29uc3RyYWludC5qcyIsIi4uL3NyYy9jb25zdHJhaW50cy9Qb2ludENvbnN0cmFpbnQuanMiLCIuLi9zcmMvY29uc3RyYWludHMvU2xpZGVyQ29uc3RyYWludC5qcyIsIi4uL3NyYy9jb25zdHJhaW50cy9ET0ZDb25zdHJhaW50LmpzIiwiLi4vc3JjL3ZlaGljbGUvdmVoaWNsZS5qcyIsIi4uL3NyYy9tb2R1bGVzL2NvcmUvV29ybGRNb2R1bGVCYXNlLmpzIiwiLi4vYnVuZGxlLXdvcmtlci93b3JrZXJoZWxwZXIuanMiLCIuLi9zcmMvd29ya2VyLmpzIiwiLi4vc3JjL21vZHVsZXMvV29ybGRNb2R1bGUuanMiLCIuLi9zcmMvbW9kdWxlcy9jb3JlL1BoeXNpY3NNb2R1bGUuanMiLCIuLi9zcmMvbW9kdWxlcy9Cb3hNb2R1bGUuanMiLCIuLi9zcmMvbW9kdWxlcy9Db21wb3VuZE1vZHVsZS5qcyIsIi4uL3NyYy9tb2R1bGVzL0NhcHN1bGVNb2R1bGUuanMiLCIuLi9zcmMvbW9kdWxlcy9Db25jYXZlTW9kdWxlLmpzIiwiLi4vc3JjL21vZHVsZXMvQ29uZU1vZHVsZS5qcyIsIi4uL3NyYy9tb2R1bGVzL0NvbnZleE1vZHVsZS5qcyIsIi4uL3NyYy9tb2R1bGVzL0N5bGluZGVyTW9kdWxlLmpzIiwiLi4vc3JjL21vZHVsZXMvSGVpZ2h0ZmllbGRNb2R1bGUuanMiLCIuLi9zcmMvbW9kdWxlcy9QbGFuZU1vZHVsZS5qcyIsIi4uL3NyYy9tb2R1bGVzL1NwaGVyZU1vZHVsZS5qcyIsIi4uL3NyYy9tb2R1bGVzL1NvZnRib2R5TW9kdWxlLmpzIiwiLi4vc3JjL21vZHVsZXMvQ2xvdGhNb2R1bGUuanMiLCIuLi9zcmMvbW9kdWxlcy9Sb3BlTW9kdWxlLmpzIiwiLi4vc3JjL21vZHVsZXMvY29udHJvbHMvRmlyc3RQZXJzb25Nb2R1bGUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgVmVjdG9yMyxcbiAgTWF0cml4NCxcbiAgUXVhdGVybmlvblxufSBmcm9tICd0aHJlZSc7XG5cbmNvbnN0IE1FU1NBR0VfVFlQRVMgPSB7XG4gIFdPUkxEUkVQT1JUOiAwLFxuICBDT0xMSVNJT05SRVBPUlQ6IDEsXG4gIFZFSElDTEVSRVBPUlQ6IDIsXG4gIENPTlNUUkFJTlRSRVBPUlQ6IDMsXG4gIFNPRlRSRVBPUlQ6IDRcbn07XG5cbmNvbnN0IFJFUE9SVF9JVEVNU0laRSA9IDE0LFxuICBDT0xMSVNJT05SRVBPUlRfSVRFTVNJWkUgPSA1LFxuICBWRUhJQ0xFUkVQT1JUX0lURU1TSVpFID0gOSxcbiAgQ09OU1RSQUlOVFJFUE9SVF9JVEVNU0laRSA9IDY7XG5cbmNvbnN0IHRlbXAxVmVjdG9yMyA9IG5ldyBWZWN0b3IzKCksXG4gIHRlbXAyVmVjdG9yMyA9IG5ldyBWZWN0b3IzKCksXG4gIHRlbXAxTWF0cml4NCA9IG5ldyBNYXRyaXg0KCksXG4gIHRlbXAxUXVhdCA9IG5ldyBRdWF0ZXJuaW9uKCk7XG5cbmNvbnN0IGdldEV1bGVyWFlaRnJvbVF1YXRlcm5pb24gPSAoeCwgeSwgeiwgdykgPT4ge1xuICByZXR1cm4gbmV3IFZlY3RvcjMoXG4gICAgTWF0aC5hdGFuMigyICogKHggKiB3IC0geSAqIHopLCAodyAqIHcgLSB4ICogeCAtIHkgKiB5ICsgeiAqIHopKSxcbiAgICBNYXRoLmFzaW4oMiAqICh4ICogeiArIHkgKiB3KSksXG4gICAgTWF0aC5hdGFuMigyICogKHogKiB3IC0geCAqIHkpLCAodyAqIHcgKyB4ICogeCAtIHkgKiB5IC0geiAqIHopKVxuICApO1xufTtcblxuY29uc3QgZ2V0UXVhdGVydGlvbkZyb21FdWxlciA9ICh4LCB5LCB6KSA9PiB7XG4gIGNvbnN0IGMxID0gTWF0aC5jb3MoeSk7XG4gIGNvbnN0IHMxID0gTWF0aC5zaW4oeSk7XG4gIGNvbnN0IGMyID0gTWF0aC5jb3MoLXopO1xuICBjb25zdCBzMiA9IE1hdGguc2luKC16KTtcbiAgY29uc3QgYzMgPSBNYXRoLmNvcyh4KTtcbiAgY29uc3QgczMgPSBNYXRoLnNpbih4KTtcbiAgY29uc3QgYzFjMiA9IGMxICogYzI7XG4gIGNvbnN0IHMxczIgPSBzMSAqIHMyO1xuXG4gIHJldHVybiB7XG4gICAgdzogYzFjMiAqIGMzIC0gczFzMiAqIHMzLFxuICAgIHg6IGMxYzIgKiBzMyArIHMxczIgKiBjMyxcbiAgICB5OiBzMSAqIGMyICogYzMgKyBjMSAqIHMyICogczMsXG4gICAgejogYzEgKiBzMiAqIGMzIC0gczEgKiBjMiAqIHMzXG4gIH07XG59O1xuXG5jb25zdCBjb252ZXJ0V29ybGRQb3NpdGlvblRvT2JqZWN0ID0gKHBvc2l0aW9uLCBvYmplY3QpID0+IHtcbiAgdGVtcDFNYXRyaXg0LmlkZW50aXR5KCk7IC8vIHJlc2V0IHRlbXAgbWF0cml4XG5cbiAgLy8gU2V0IHRoZSB0ZW1wIG1hdHJpeCdzIHJvdGF0aW9uIHRvIHRoZSBvYmplY3QncyByb3RhdGlvblxuICB0ZW1wMU1hdHJpeDQuaWRlbnRpdHkoKS5tYWtlUm90YXRpb25Gcm9tUXVhdGVybmlvbihvYmplY3QucXVhdGVybmlvbik7XG5cbiAgLy8gSW52ZXJ0IHJvdGF0aW9uIG1hdHJpeCBpbiBvcmRlciB0byBcInVucm90YXRlXCIgYSBwb2ludCBiYWNrIHRvIG9iamVjdCBzcGFjZVxuICB0ZW1wMU1hdHJpeDQuZ2V0SW52ZXJzZSh0ZW1wMU1hdHJpeDQpO1xuXG4gIC8vIFlheSEgVGVtcCB2YXJzIVxuICB0ZW1wMVZlY3RvcjMuY29weShwb3NpdGlvbik7XG4gIHRlbXAyVmVjdG9yMy5jb3B5KG9iamVjdC5wb3NpdGlvbik7XG5cbiAgLy8gQXBwbHkgdGhlIHJvdGF0aW9uXG4gIHJldHVybiB0ZW1wMVZlY3RvcjMuc3ViKHRlbXAyVmVjdG9yMykuYXBwbHlNYXRyaXg0KHRlbXAxTWF0cml4NCk7XG59O1xuXG5jb25zdCBhZGRPYmplY3RDaGlsZHJlbiA9IGZ1bmN0aW9uIChwYXJlbnQsIG9iamVjdCkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG9iamVjdC5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGNoaWxkID0gb2JqZWN0LmNoaWxkcmVuW2ldO1xuICAgIGNvbnN0IHBoeXNpY3MgPSBjaGlsZC5jb21wb25lbnQgPyBjaGlsZC5jb21wb25lbnQudXNlKCdwaHlzaWNzJykgOiBmYWxzZTtcblxuICAgIGlmIChwaHlzaWNzKSB7XG4gICAgICBjb25zdCBkYXRhID0gcGh5c2ljcy5kYXRhO1xuXG4gICAgICBjaGlsZC51cGRhdGV
|