9886 lines
452 KiB
JavaScript
9886 lines
452 KiB
JavaScript
(function() {
|
|
function r(e, n, t) {
|
|
function o(i, f) {
|
|
if (!n[i]) {
|
|
if (!e[i]) {
|
|
var c = "function" == typeof require && require;
|
|
if (!f && c) return c(i, !0);
|
|
if (u) return u(i, !0);
|
|
var a = new Error("Cannot find module '" + i + "'");
|
|
throw a.code = "MODULE_NOT_FOUND", a;
|
|
}
|
|
var p = n[i] = {
|
|
exports: {}
|
|
};
|
|
e[i][0].call(p.exports, function(r) {
|
|
var n = e[i][1][r];
|
|
return o(n || r);
|
|
}, p, p.exports, r, e, n, t);
|
|
}
|
|
return n[i].exports;
|
|
}
|
|
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
|
|
return o;
|
|
}
|
|
return r;
|
|
})()({
|
|
1: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.CannonRigidBody = void 0;
|
|
var _cannon = _interopRequireDefault(require("../../../../../external/cannon/cannon"));
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
var v3_cannon0 = new _cannon["default"].Vec3();
|
|
var v3_cannon1 = new _cannon["default"].Vec3();
|
|
var Vec3 = cc.Vec3;
|
|
var CannonRigidBody = function() {
|
|
function CannonRigidBody() {
|
|
this._rigidBody = void 0;
|
|
this._sharedBody = void 0;
|
|
this._isEnabled = false;
|
|
}
|
|
var _proto = CannonRigidBody.prototype;
|
|
_proto.__preload = function __preload(com) {
|
|
this._rigidBody = com;
|
|
this._sharedBody = cc.director.getPhysics3DManager().physicsWorld.getSharedBody(this._rigidBody.node);
|
|
this._sharedBody.reference = true;
|
|
this._sharedBody.wrappedBody = this;
|
|
};
|
|
_proto.onLoad = function onLoad() {};
|
|
_proto.onEnable = function onEnable() {
|
|
this._isEnabled = true;
|
|
this.mass = this._rigidBody.mass;
|
|
this.allowSleep = this._rigidBody.allowSleep;
|
|
this.linearDamping = this._rigidBody.linearDamping;
|
|
this.angularDamping = this._rigidBody.angularDamping;
|
|
this.useGravity = this._rigidBody.useGravity;
|
|
this.isKinematic = this._rigidBody.isKinematic;
|
|
this.fixedRotation = this._rigidBody.fixedRotation;
|
|
this.linearFactor = this._rigidBody.linearFactor;
|
|
this.angularFactor = this._rigidBody.angularFactor;
|
|
this._sharedBody.enabled = true;
|
|
};
|
|
_proto.onDisable = function onDisable() {
|
|
this._isEnabled = false;
|
|
this._sharedBody.enabled = false;
|
|
};
|
|
_proto.onDestroy = function onDestroy() {
|
|
this._sharedBody.reference = false;
|
|
this._rigidBody = null;
|
|
this._sharedBody = null;
|
|
};
|
|
_proto.wakeUp = function wakeUp() {
|
|
return this._sharedBody.body.wakeUp();
|
|
};
|
|
_proto.sleep = function sleep() {
|
|
return this._sharedBody.body.sleep();
|
|
};
|
|
_proto.getLinearVelocity = function getLinearVelocity(out) {
|
|
Vec3.copy(out, this._sharedBody.body.velocity);
|
|
return out;
|
|
};
|
|
_proto.setLinearVelocity = function setLinearVelocity(value) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
Vec3.copy(body.velocity, value);
|
|
};
|
|
_proto.getAngularVelocity = function getAngularVelocity(out) {
|
|
Vec3.copy(out, this._sharedBody.body.angularVelocity);
|
|
return out;
|
|
};
|
|
_proto.setAngularVelocity = function setAngularVelocity(value) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
Vec3.copy(body.angularVelocity, value);
|
|
};
|
|
_proto.applyForce = function applyForce(force, worldPoint) {
|
|
null == worldPoint && (worldPoint = Vec3.ZERO);
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.applyForce(Vec3.copy(v3_cannon0, force), Vec3.copy(v3_cannon1, worldPoint));
|
|
};
|
|
_proto.applyImpulse = function applyImpulse(impulse, worldPoint) {
|
|
null == worldPoint && (worldPoint = Vec3.ZERO);
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.applyImpulse(Vec3.copy(v3_cannon0, impulse), Vec3.copy(v3_cannon1, worldPoint));
|
|
};
|
|
_proto.applyLocalForce = function applyLocalForce(force, localPoint) {
|
|
null == localPoint && (localPoint = Vec3.ZERO);
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.applyLocalForce(Vec3.copy(v3_cannon0, force), Vec3.copy(v3_cannon1, localPoint));
|
|
};
|
|
_proto.applyLocalImpulse = function applyLocalImpulse(impulse, localPoint) {
|
|
null == localPoint && (localPoint = Vec3.ZERO);
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.applyLocalImpulse(Vec3.copy(v3_cannon0, impulse), Vec3.copy(v3_cannon1, localPoint));
|
|
};
|
|
_proto.applyTorque = function applyTorque(torque) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.torque.x += torque.x;
|
|
body.torque.y += torque.y;
|
|
body.torque.z += torque.z;
|
|
};
|
|
_proto.applyLocalTorque = function applyLocalTorque(torque) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
Vec3.copy(v3_cannon0, torque);
|
|
body.vectorToWorldFrame(v3_cannon0, v3_cannon0);
|
|
body.torque.x += v3_cannon0.x;
|
|
body.torque.y += v3_cannon0.y;
|
|
body.torque.z += v3_cannon0.z;
|
|
};
|
|
_createClass(CannonRigidBody, [ {
|
|
key: "isAwake",
|
|
get: function get() {
|
|
return this._sharedBody.body.isAwake();
|
|
}
|
|
}, {
|
|
key: "isSleepy",
|
|
get: function get() {
|
|
return this._sharedBody.body.isSleepy();
|
|
}
|
|
}, {
|
|
key: "isSleeping",
|
|
get: function get() {
|
|
return this._sharedBody.body.isSleeping();
|
|
}
|
|
}, {
|
|
key: "allowSleep",
|
|
set: function set(v) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.allowSleep = v;
|
|
}
|
|
}, {
|
|
key: "mass",
|
|
set: function set(value) {
|
|
var body = this._sharedBody.body;
|
|
body.mass = value;
|
|
0 == body.mass ? body.type = _cannon["default"].Body.STATIC : body.type = this._rigidBody.isKinematic ? _cannon["default"].Body.KINEMATIC : _cannon["default"].Body.DYNAMIC;
|
|
body.updateMassProperties();
|
|
body.isSleeping() && body.wakeUp();
|
|
}
|
|
}, {
|
|
key: "isKinematic",
|
|
set: function set(value) {
|
|
var body = this._sharedBody.body;
|
|
0 == body.mass ? body.type = _cannon["default"].Body.STATIC : body.type = value ? _cannon["default"].Body.KINEMATIC : _cannon["default"].Body.DYNAMIC;
|
|
}
|
|
}, {
|
|
key: "fixedRotation",
|
|
set: function set(value) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.fixedRotation = value;
|
|
body.updateMassProperties();
|
|
}
|
|
}, {
|
|
key: "linearDamping",
|
|
set: function set(value) {
|
|
this._sharedBody.body.linearDamping = value;
|
|
}
|
|
}, {
|
|
key: "angularDamping",
|
|
set: function set(value) {
|
|
this._sharedBody.body.angularDamping = value;
|
|
}
|
|
}, {
|
|
key: "useGravity",
|
|
set: function set(value) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
body.useGravity = value;
|
|
}
|
|
}, {
|
|
key: "linearFactor",
|
|
set: function set(value) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
Vec3.copy(body.linearFactor, value);
|
|
}
|
|
}, {
|
|
key: "angularFactor",
|
|
set: function set(value) {
|
|
var body = this._sharedBody.body;
|
|
body.isSleeping() && body.wakeUp();
|
|
Vec3.copy(body.angularFactor, value);
|
|
}
|
|
}, {
|
|
key: "rigidBody",
|
|
get: function get() {
|
|
return this._rigidBody;
|
|
}
|
|
}, {
|
|
key: "sharedBody",
|
|
get: function get() {
|
|
return this._sharedBody;
|
|
}
|
|
}, {
|
|
key: "isEnabled",
|
|
get: function get() {
|
|
return this._isEnabled;
|
|
}
|
|
} ]);
|
|
return CannonRigidBody;
|
|
}();
|
|
exports.CannonRigidBody = CannonRigidBody;
|
|
}, {
|
|
"../../../../../external/cannon/cannon": 24
|
|
} ],
|
|
2: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.CannonSharedBody = void 0;
|
|
var _cannon = _interopRequireDefault(require("../../../../../external/cannon/cannon"));
|
|
var _physicsEnum = require("../framework/physics-enum");
|
|
var _util = require("../framework/util");
|
|
var _cannonUtil = require("./cannon-util");
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
var LocalDirtyFlag = cc.Node._LocalDirtyFlag;
|
|
var PHYSICS_SCALE = LocalDirtyFlag.PHYSICS_SCALE;
|
|
var Quat = cc.Quat;
|
|
var Vec3 = cc.Vec3;
|
|
var fastRemoveAt = cc.js.array.fastRemoveAt;
|
|
var v3_0 = new Vec3();
|
|
var quat_0 = new Quat();
|
|
var contactsPool = [];
|
|
var CollisionEventObject = {
|
|
type: "collision-enter",
|
|
selfCollider: null,
|
|
otherCollider: null,
|
|
contacts: []
|
|
};
|
|
var CannonSharedBody = function() {
|
|
CannonSharedBody.getSharedBody = function getSharedBody(node, wrappedWorld) {
|
|
var key = node._id;
|
|
if (CannonSharedBody.sharedBodiesMap.has(key)) return CannonSharedBody.sharedBodiesMap.get(key);
|
|
var newSB = new CannonSharedBody(node, wrappedWorld);
|
|
CannonSharedBody.sharedBodiesMap.set(node._id, newSB);
|
|
return newSB;
|
|
};
|
|
_createClass(CannonSharedBody, [ {
|
|
key: "enabled",
|
|
set: function set(v) {
|
|
if (v) {
|
|
if (this.index < 0) {
|
|
this.index = this.wrappedWorld.bodies.length;
|
|
this.wrappedWorld.addSharedBody(this);
|
|
var node = this.node;
|
|
this.body.aabbNeedsUpdate = true;
|
|
node.getWorldPosition(v3_0);
|
|
node.getWorldRotation(quat_0);
|
|
var pos = this.body.position;
|
|
pos.x = parseFloat(v3_0.x.toFixed(3));
|
|
pos.y = parseFloat(v3_0.y.toFixed(3));
|
|
pos.z = parseFloat(v3_0.z.toFixed(3));
|
|
var rot = this.body.quaternion;
|
|
rot.x = parseFloat(quat_0.x.toFixed(12));
|
|
rot.y = parseFloat(quat_0.y.toFixed(12));
|
|
rot.z = parseFloat(quat_0.z.toFixed(12));
|
|
rot.w = parseFloat(quat_0.w.toFixed(12));
|
|
if (node._localMatDirty & PHYSICS_SCALE) {
|
|
var wscale = node.__wscale;
|
|
for (var i = 0; i < this.shapes.length; i++) this.shapes[i].setScale(wscale);
|
|
(0, _cannonUtil.commitShapeUpdates)(this.body);
|
|
}
|
|
this.body.isSleeping() && this.body.wakeUp();
|
|
}
|
|
} else if (this.index >= 0) {
|
|
var isRemove = 0 == this.shapes.length && null == this.wrappedBody || 0 == this.shapes.length && null != this.wrappedBody && !this.wrappedBody.rigidBody.enabledInHierarchy || 0 == this.shapes.length && null != this.wrappedBody && !this.wrappedBody.isEnabled;
|
|
if (isRemove) {
|
|
this.body.sleep();
|
|
this.index = -1;
|
|
this.wrappedWorld.removeSharedBody(this);
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: "reference",
|
|
set: function set(v) {
|
|
v ? this.ref++ : this.ref--;
|
|
0 == this.ref && this.destroy();
|
|
}
|
|
} ]);
|
|
function CannonSharedBody(node, wrappedWorld) {
|
|
this.node = void 0;
|
|
this.wrappedWorld = void 0;
|
|
this.body = new _cannon["default"].Body();
|
|
this.shapes = [];
|
|
this.wrappedBody = null;
|
|
this.index = -1;
|
|
this.ref = 0;
|
|
this.onCollidedListener = this.onCollided.bind(this);
|
|
this.wrappedWorld = wrappedWorld;
|
|
this.node = node;
|
|
this.body.material = this.wrappedWorld.world.defaultMaterial;
|
|
this.body.addEventListener("cc-collide", this.onCollidedListener);
|
|
this._updateGroup();
|
|
this.node.on(cc.Node.EventType.GROUP_CHANGED, this._updateGroup, this);
|
|
}
|
|
var _proto = CannonSharedBody.prototype;
|
|
_proto._updateGroup = function _updateGroup() {
|
|
(0, _cannonUtil.groupIndexToBitMask)(this.node.groupIndex, this.body);
|
|
};
|
|
_proto.addShape = function addShape(v) {
|
|
var index = this.shapes.indexOf(v);
|
|
if (index < 0) {
|
|
var _index = this.body.shapes.length;
|
|
this.body.addShape(v.shape);
|
|
this.shapes.push(v);
|
|
v.setIndex(_index);
|
|
var offset = this.body.shapeOffsets[_index];
|
|
var orient = this.body.shapeOrientations[_index];
|
|
v.setOffsetAndOrient(offset, orient);
|
|
}
|
|
};
|
|
_proto.removeShape = function removeShape(v) {
|
|
var index = this.shapes.indexOf(v);
|
|
if (index >= 0) {
|
|
fastRemoveAt(this.shapes, index);
|
|
this.body.removeShape(v.shape);
|
|
v.setIndex(-1);
|
|
}
|
|
};
|
|
_proto.syncSceneToPhysics = function syncSceneToPhysics(force) {
|
|
void 0 === force && (force = false);
|
|
var node = this.node;
|
|
var needUpdateTransform = (0, _util.worldDirty)(node);
|
|
if (!force && !needUpdateTransform) return;
|
|
this.body.aabbNeedsUpdate = true;
|
|
node.getWorldPosition(v3_0);
|
|
node.getWorldRotation(quat_0);
|
|
Vec3.copy(this.body.position, v3_0);
|
|
Quat.copy(this.body.quaternion, quat_0);
|
|
if (node._localMatDirty & PHYSICS_SCALE) {
|
|
var wscale = node.__wscale;
|
|
for (var i = 0; i < this.shapes.length; i++) this.shapes[i].setScale(wscale);
|
|
(0, _cannonUtil.commitShapeUpdates)(this.body);
|
|
}
|
|
this.body.isSleeping() && this.body.wakeUp();
|
|
};
|
|
_proto.syncPhysicsToScene = function syncPhysicsToScene() {
|
|
if (this.body.type != _physicsEnum.ERigidBodyType.STATIC && !this.body.isSleeping()) {
|
|
Vec3.copy(v3_0, this.body.position);
|
|
Quat.copy(quat_0, this.body.quaternion);
|
|
this.node.setWorldPosition(v3_0);
|
|
this.node.setWorldRotation(quat_0);
|
|
}
|
|
};
|
|
_proto.destroy = function destroy() {
|
|
this.body.removeEventListener("cc-collide", this.onCollidedListener);
|
|
this.node.off(cc.Node.EventType.GROUP_CHANGED, this._updateGroup, this);
|
|
CannonSharedBody.sharedBodiesMap["delete"](this.node._id);
|
|
delete _cannon["default"].World["idToBodyMap"][this.body.id];
|
|
this.node = null;
|
|
this.wrappedWorld = null;
|
|
this.body = null;
|
|
this.shapes = null;
|
|
this.onCollidedListener = null;
|
|
};
|
|
_proto.onCollided = function onCollided(event) {
|
|
CollisionEventObject.type = event.event;
|
|
var self = (0, _util.getWrap)(event.selfShape);
|
|
var other = (0, _util.getWrap)(event.otherShape);
|
|
if (self) {
|
|
CollisionEventObject.selfCollider = self.collider;
|
|
CollisionEventObject.otherCollider = other ? other.collider : null;
|
|
var i = 0;
|
|
for (i = CollisionEventObject.contacts.length; i--; ) contactsPool.push(CollisionEventObject.contacts.pop());
|
|
for (i = 0; i < event.contacts.length; i++) {
|
|
var cq = event.contacts[i];
|
|
if (contactsPool.length > 0) {
|
|
var c = contactsPool.pop();
|
|
Vec3.copy(c.contactA, cq.ri);
|
|
Vec3.copy(c.contactB, cq.rj);
|
|
Vec3.copy(c.normal, cq.ni);
|
|
CollisionEventObject.contacts.push(c);
|
|
} else {
|
|
var _c = {
|
|
contactA: Vec3.copy(new Vec3(), cq.ri),
|
|
contactB: Vec3.copy(new Vec3(), cq.rj),
|
|
normal: Vec3.copy(new Vec3(), cq.ni)
|
|
};
|
|
CollisionEventObject.contacts.push(_c);
|
|
}
|
|
}
|
|
for (i = 0; i < this.shapes.length; i++) {
|
|
var shape = this.shapes[i];
|
|
CollisionEventObject.type = _cannonUtil.deprecatedEventMap[CollisionEventObject.type];
|
|
shape.collider.emit(CollisionEventObject.type, CollisionEventObject);
|
|
CollisionEventObject.type = event.event;
|
|
shape.collider.emit(CollisionEventObject.type, CollisionEventObject);
|
|
}
|
|
}
|
|
};
|
|
return CannonSharedBody;
|
|
}();
|
|
exports.CannonSharedBody = CannonSharedBody;
|
|
CannonSharedBody.sharedBodiesMap = new Map();
|
|
}, {
|
|
"../../../../../external/cannon/cannon": 24,
|
|
"../framework/physics-enum": 19,
|
|
"../framework/util": 23,
|
|
"./cannon-util": 3
|
|
} ],
|
|
3: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.groupIndexToBitMask = groupIndexToBitMask;
|
|
exports.toCannonRaycastOptions = toCannonRaycastOptions;
|
|
exports.fillRaycastResult = fillRaycastResult;
|
|
exports.commitShapeUpdates = commitShapeUpdates;
|
|
exports.deprecatedEventMap = void 0;
|
|
var _util = require("../framework/util");
|
|
var Vec3 = cc.Vec3;
|
|
function groupIndexToBitMask(groupIndex, out) {
|
|
var categoryBits = 1 << groupIndex;
|
|
var maskBits = 0;
|
|
var bits = cc.game.collisionMatrix[groupIndex];
|
|
if (!bits) {
|
|
cc.error("cannon-utils: group is not exist", groupIndex);
|
|
return;
|
|
}
|
|
for (var i = 0; i < bits.length; i++) {
|
|
if (!bits[i]) continue;
|
|
maskBits |= 1 << i;
|
|
}
|
|
out.collisionFilterGroup = categoryBits;
|
|
out.collisionFilterMask = maskBits;
|
|
}
|
|
function toCannonRaycastOptions(out, options) {
|
|
out.checkCollisionResponse = !options.queryTrigger;
|
|
groupIndexToBitMask(options.groupIndex, out);
|
|
out.skipBackFaces = false;
|
|
}
|
|
function fillRaycastResult(result, cannonResult) {
|
|
result._assign(Vec3.copy(new Vec3(), cannonResult.hitPointWorld), cannonResult.distance, (0,
|
|
_util.getWrap)(cannonResult.shape).collider);
|
|
}
|
|
function commitShapeUpdates(body) {
|
|
body.aabbNeedsUpdate = true;
|
|
body.updateMassProperties();
|
|
body.updateBoundingRadius();
|
|
}
|
|
var deprecatedEventMap = {
|
|
onCollisionEnter: "collision-enter",
|
|
onCollisionStay: "collision-stay",
|
|
onCollisionExit: "collision-exit",
|
|
onTriggerEnter: "trigger-enter",
|
|
onTriggerStay: "trigger-stay",
|
|
onTriggerExit: "trigger-exit"
|
|
};
|
|
exports.deprecatedEventMap = deprecatedEventMap;
|
|
}, {
|
|
"../framework/util": 23
|
|
} ],
|
|
4: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.CannonWorld = void 0;
|
|
var _cannon = _interopRequireDefault(require("../../../../../external/cannon/cannon"));
|
|
var _cannonUtil = require("./cannon-util");
|
|
var _cannonShape = require("./shapes/cannon-shape");
|
|
var _cannonSharedBody = require("./cannon-shared-body");
|
|
var _util = require("../framework/util");
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
var Vec3 = cc.Vec3;
|
|
var fastRemoveAt = cc.js.array.fastRemoveAt;
|
|
var CannonWorld = function() {
|
|
_createClass(CannonWorld, [ {
|
|
key: "world",
|
|
get: function get() {
|
|
return this._world;
|
|
}
|
|
}, {
|
|
key: "defaultMaterial",
|
|
set: function set(mat) {
|
|
this._world.defaultMaterial.friction = mat.friction;
|
|
this._world.defaultMaterial.restitution = mat.restitution;
|
|
null != _cannonShape.CannonShape.idToMaterial[mat._uuid] && (_cannonShape.CannonShape.idToMaterial[mat._uuid] = this._world.defaultMaterial);
|
|
}
|
|
}, {
|
|
key: "allowSleep",
|
|
set: function set(v) {
|
|
this._world.allowSleep = v;
|
|
}
|
|
}, {
|
|
key: "gravity",
|
|
set: function set(gravity) {
|
|
Vec3.copy(this._world.gravity, gravity);
|
|
}
|
|
} ]);
|
|
function CannonWorld() {
|
|
this.bodies = [];
|
|
this._world = void 0;
|
|
this._raycastResult = new _cannon["default"].RaycastResult();
|
|
this._world = new _cannon["default"].World();
|
|
this._world.broadphase = new _cannon["default"].NaiveBroadphase();
|
|
this._world.addEventListener("postStep", this.onPostStep.bind(this));
|
|
}
|
|
var _proto = CannonWorld.prototype;
|
|
_proto.onPostStep = function onPostStep() {
|
|
var p3dm = cc.director.getPhysics3DManager();
|
|
if (p3dm.useFixedDigit) {
|
|
var pd = p3dm.fixDigits.position;
|
|
var rd = p3dm.fixDigits.rotation;
|
|
var bodies = this._world.bodies;
|
|
for (var i = 0; i < bodies.length; i++) {
|
|
var bi = bodies[i];
|
|
if (bi.type != _cannon["default"].Body.STATIC && !bi.isSleeping()) {
|
|
var pos = bi.position;
|
|
pos.x = parseFloat(pos.x.toFixed(pd));
|
|
pos.y = parseFloat(pos.y.toFixed(pd));
|
|
pos.z = parseFloat(pos.z.toFixed(pd));
|
|
var rot = bi.quaternion;
|
|
rot.x = parseFloat(rot.x.toFixed(rd));
|
|
rot.y = parseFloat(rot.y.toFixed(rd));
|
|
rot.z = parseFloat(rot.z.toFixed(rd));
|
|
rot.w = parseFloat(rot.w.toFixed(rd));
|
|
var vel = bi.velocity;
|
|
vel.x = parseFloat(vel.x.toFixed(pd));
|
|
vel.y = parseFloat(vel.y.toFixed(pd));
|
|
vel.z = parseFloat(vel.z.toFixed(pd));
|
|
var avel = bi.angularVelocity;
|
|
avel.x = parseFloat(avel.x.toFixed(pd));
|
|
avel.y = parseFloat(avel.y.toFixed(pd));
|
|
avel.z = parseFloat(avel.z.toFixed(pd));
|
|
}
|
|
}
|
|
}
|
|
};
|
|
_proto.step = function step(deltaTime, timeSinceLastCalled, maxSubStep) {
|
|
this.syncSceneToPhysics();
|
|
this._world.step(deltaTime, timeSinceLastCalled, maxSubStep);
|
|
this.syncPhysicsToScene();
|
|
this.emitEvents();
|
|
};
|
|
_proto.syncSceneToPhysics = function syncSceneToPhysics() {
|
|
(0, _util.clearNodeTransformRecord)();
|
|
for (var i = 0; i < this.bodies.length; i++) this.bodies[i].syncSceneToPhysics();
|
|
(0, _util.clearNodeTransformDirtyFlag)();
|
|
};
|
|
_proto.syncPhysicsToScene = function syncPhysicsToScene() {
|
|
for (var i = 0; i < this.bodies.length; i++) this.bodies[i].syncPhysicsToScene();
|
|
};
|
|
_proto.emitEvents = function emitEvents() {
|
|
this._world.emitTriggeredEvents();
|
|
this._world.emitCollisionEvents();
|
|
};
|
|
_proto.raycastClosest = function raycastClosest(worldRay, options, result) {
|
|
setupFromAndTo(worldRay, options.maxDistance);
|
|
(0, _cannonUtil.toCannonRaycastOptions)(raycastOpt, options);
|
|
var hit = this._world.raycastClosest(from, to, raycastOpt, this._raycastResult);
|
|
hit && (0, _cannonUtil.fillRaycastResult)(result, this._raycastResult);
|
|
return hit;
|
|
};
|
|
_proto.raycast = function raycast(worldRay, options, pool, results) {
|
|
setupFromAndTo(worldRay, options.maxDistance);
|
|
(0, _cannonUtil.toCannonRaycastOptions)(raycastOpt, options);
|
|
var hit = this._world.raycastAll(from, to, raycastOpt, function(result) {
|
|
var r = pool.add();
|
|
(0, _cannonUtil.fillRaycastResult)(r, result);
|
|
results.push(r);
|
|
});
|
|
return hit;
|
|
};
|
|
_proto.getSharedBody = function getSharedBody(node) {
|
|
return _cannonSharedBody.CannonSharedBody.getSharedBody(node, this);
|
|
};
|
|
_proto.addSharedBody = function addSharedBody(sharedBody) {
|
|
var i = this.bodies.indexOf(sharedBody);
|
|
if (i < 0) {
|
|
this.bodies.push(sharedBody);
|
|
this._world.addBody(sharedBody.body);
|
|
}
|
|
};
|
|
_proto.removeSharedBody = function removeSharedBody(sharedBody) {
|
|
var i = this.bodies.indexOf(sharedBody);
|
|
if (i >= 0) {
|
|
fastRemoveAt(this.bodies, i);
|
|
this._world.remove(sharedBody.body);
|
|
}
|
|
};
|
|
return CannonWorld;
|
|
}();
|
|
exports.CannonWorld = CannonWorld;
|
|
var from = new _cannon["default"].Vec3();
|
|
var to = new _cannon["default"].Vec3();
|
|
function setupFromAndTo(worldRay, distance) {
|
|
Vec3.copy(from, worldRay.o);
|
|
worldRay.computeHit(to, distance);
|
|
}
|
|
var raycastOpt = {
|
|
checkCollisionResponse: false,
|
|
collisionFilterGroup: -1,
|
|
collisionFilterMask: -1,
|
|
skipBackFaces: false
|
|
};
|
|
}, {
|
|
"../../../../../external/cannon/cannon": 24,
|
|
"../framework/util": 23,
|
|
"./cannon-shared-body": 2,
|
|
"./cannon-util": 3,
|
|
"./shapes/cannon-shape": 7
|
|
} ],
|
|
5: [ function(require, module, exports) {
|
|
"use strict";
|
|
var _physicsSelector = require("../framework/physics-selector");
|
|
var _cannonRigidBody = require("./cannon-rigid-body");
|
|
var _cannonWorld = require("./cannon-world");
|
|
var _cannonBoxShape = require("./shapes/cannon-box-shape");
|
|
var _cannonSphereShape = require("./shapes/cannon-sphere-shape");
|
|
true;
|
|
(0, _physicsSelector.instantiate)(_cannonBoxShape.CannonBoxShape, _cannonSphereShape.CannonSphereShape, _cannonRigidBody.CannonRigidBody, _cannonWorld.CannonWorld);
|
|
}, {
|
|
"../framework/physics-selector": 22,
|
|
"./cannon-rigid-body": 1,
|
|
"./cannon-world": 4,
|
|
"./shapes/cannon-box-shape": 6,
|
|
"./shapes/cannon-sphere-shape": 8
|
|
} ],
|
|
6: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.CannonBoxShape = void 0;
|
|
var _cannon = _interopRequireDefault(require("../../../../../../external/cannon/cannon"));
|
|
var _cannonUtil = require("../cannon-util");
|
|
var _cannonShape = require("./cannon-shape");
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
var Vec3 = cc.Vec3;
|
|
var v3_0 = new Vec3();
|
|
var CannonBoxShape = function(_CannonShape) {
|
|
_inheritsLoose(CannonBoxShape, _CannonShape);
|
|
_createClass(CannonBoxShape, [ {
|
|
key: "boxCollider",
|
|
get: function get() {
|
|
return this.collider;
|
|
}
|
|
}, {
|
|
key: "box",
|
|
get: function get() {
|
|
return this._shape;
|
|
}
|
|
} ]);
|
|
function CannonBoxShape(size) {
|
|
var _this;
|
|
_this = _CannonShape.call(this) || this;
|
|
_this.halfExtent = new _cannon["default"].Vec3();
|
|
Vec3.multiplyScalar(_this.halfExtent, size, .5);
|
|
_this._shape = new _cannon["default"].Box(_this.halfExtent.clone());
|
|
return _this;
|
|
}
|
|
var _proto = CannonBoxShape.prototype;
|
|
_proto.onLoad = function onLoad() {
|
|
_CannonShape.prototype.onLoad.call(this);
|
|
this.size = this.boxCollider.size;
|
|
};
|
|
_proto.setScale = function setScale(scale) {
|
|
_CannonShape.prototype.setScale.call(this, scale);
|
|
this.size = this.boxCollider.size;
|
|
};
|
|
_createClass(CannonBoxShape, [ {
|
|
key: "size",
|
|
set: function set(v) {
|
|
this.collider.node.getWorldScale(v3_0);
|
|
v3_0.x = Math.abs(v3_0.x);
|
|
v3_0.y = Math.abs(v3_0.y);
|
|
v3_0.z = Math.abs(v3_0.z);
|
|
Vec3.multiplyScalar(this.halfExtent, v, .5);
|
|
Vec3.multiply(this.box.halfExtents, this.halfExtent, v3_0);
|
|
this.box.updateConvexPolyhedronRepresentation();
|
|
-1 != this._index && (0, _cannonUtil.commitShapeUpdates)(this._body);
|
|
}
|
|
} ]);
|
|
return CannonBoxShape;
|
|
}(_cannonShape.CannonShape);
|
|
exports.CannonBoxShape = CannonBoxShape;
|
|
}, {
|
|
"../../../../../../external/cannon/cannon": 24,
|
|
"../cannon-util": 3,
|
|
"./cannon-shape": 7
|
|
} ],
|
|
7: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.CannonShape = void 0;
|
|
var _cannon = _interopRequireDefault(require("../../../../../../external/cannon/cannon"));
|
|
var _util = require("../../framework/util");
|
|
var _cannonUtil = require("../cannon-util");
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
var TriggerEventObject = {
|
|
type: "trigger-enter",
|
|
selfCollider: null,
|
|
otherCollider: null
|
|
};
|
|
var Vec3 = cc.Vec3;
|
|
var v3_0 = new Vec3();
|
|
var CannonShape = function() {
|
|
function CannonShape() {
|
|
this._collider = void 0;
|
|
this._shape = void 0;
|
|
this._offset = new _cannon["default"].Vec3();
|
|
this._orient = new _cannon["default"].Quaternion();
|
|
this._index = -1;
|
|
this._sharedBody = void 0;
|
|
this.onTriggerListener = this.onTrigger.bind(this);
|
|
}
|
|
var _proto = CannonShape.prototype;
|
|
_proto.__preload = function __preload(comp) {
|
|
this._collider = comp;
|
|
(0, _util.setWrap)(this._shape, this);
|
|
this._shape.addEventListener("cc-trigger", this.onTriggerListener);
|
|
this._sharedBody = cc.director.getPhysics3DManager().physicsWorld.getSharedBody(this._collider.node);
|
|
this._sharedBody.reference = true;
|
|
};
|
|
_proto.onLoad = function onLoad() {
|
|
this.center = this._collider.center;
|
|
this.isTrigger = this._collider.isTrigger;
|
|
};
|
|
_proto.onEnable = function onEnable() {
|
|
this._sharedBody.addShape(this);
|
|
this._sharedBody.enabled = true;
|
|
};
|
|
_proto.onDisable = function onDisable() {
|
|
this._sharedBody.removeShape(this);
|
|
this._sharedBody.enabled = false;
|
|
};
|
|
_proto.onDestroy = function onDestroy() {
|
|
this._sharedBody.reference = false;
|
|
this._shape.removeEventListener("cc-trigger", this.onTriggerListener);
|
|
delete _cannon["default"].World["idToShapeMap"][this._shape.id];
|
|
this._sharedBody = null;
|
|
(0, _util.setWrap)(this._shape, null);
|
|
this._offset = null;
|
|
this._orient = null;
|
|
this._shape = null;
|
|
this._collider = null;
|
|
this.onTriggerListener = null;
|
|
};
|
|
_proto.setScale = function setScale(scale) {
|
|
this._setCenter(this._collider.center);
|
|
};
|
|
_proto.setIndex = function setIndex(index) {
|
|
this._index = index;
|
|
};
|
|
_proto.setOffsetAndOrient = function setOffsetAndOrient(offset, orient) {
|
|
cc.Vec3.copy(offset, this._offset);
|
|
cc.Vec3.copy(orient, this._orient);
|
|
this._offset = offset;
|
|
this._orient = orient;
|
|
};
|
|
_proto._setCenter = function _setCenter(v) {
|
|
var lpos = this._offset;
|
|
Vec3.copy(lpos, v);
|
|
this._collider.node.getWorldScale(v3_0);
|
|
Vec3.multiply(lpos, lpos, v3_0);
|
|
};
|
|
_proto.onTrigger = function onTrigger(event) {
|
|
TriggerEventObject.type = event.event;
|
|
var self = (0, _util.getWrap)(event.selfShape);
|
|
var other = (0, _util.getWrap)(event.otherShape);
|
|
if (self) {
|
|
TriggerEventObject.selfCollider = self.collider;
|
|
TriggerEventObject.otherCollider = other ? other.collider : null;
|
|
TriggerEventObject.type = _cannonUtil.deprecatedEventMap[TriggerEventObject.type];
|
|
this._collider.emit(TriggerEventObject.type, TriggerEventObject);
|
|
TriggerEventObject.type = event.event;
|
|
this._collider.emit(TriggerEventObject.type, TriggerEventObject);
|
|
}
|
|
};
|
|
_createClass(CannonShape, [ {
|
|
key: "shape",
|
|
get: function get() {
|
|
return this._shape;
|
|
}
|
|
}, {
|
|
key: "collider",
|
|
get: function get() {
|
|
return this._collider;
|
|
}
|
|
}, {
|
|
key: "attachedRigidBody",
|
|
get: function get() {
|
|
if (this._sharedBody.wrappedBody) return this._sharedBody.wrappedBody.rigidBody;
|
|
return null;
|
|
}
|
|
}, {
|
|
key: "sharedBody",
|
|
get: function get() {
|
|
return this._sharedBody;
|
|
}
|
|
}, {
|
|
key: "material",
|
|
set: function set(mat) {
|
|
if (null == mat) this._shape.material = null; else {
|
|
null == CannonShape.idToMaterial[mat._uuid] && (CannonShape.idToMaterial[mat._uuid] = new _cannon["default"].Material(mat._uuid));
|
|
this._shape.material = CannonShape.idToMaterial[mat._uuid];
|
|
this._shape.material.friction = mat.friction;
|
|
this._shape.material.restitution = mat.restitution;
|
|
}
|
|
}
|
|
}, {
|
|
key: "isTrigger",
|
|
set: function set(v) {
|
|
this._shape.collisionResponse = !v;
|
|
this._index >= 0 && this._body.updateHasTrigger();
|
|
}
|
|
}, {
|
|
key: "center",
|
|
set: function set(v) {
|
|
this._setCenter(v);
|
|
this._index >= 0 && (0, _cannonUtil.commitShapeUpdates)(this._body);
|
|
}
|
|
}, {
|
|
key: "_body",
|
|
get: function get() {
|
|
return this._sharedBody.body;
|
|
}
|
|
} ]);
|
|
return CannonShape;
|
|
}();
|
|
exports.CannonShape = CannonShape;
|
|
CannonShape.idToMaterial = {};
|
|
}, {
|
|
"../../../../../../external/cannon/cannon": 24,
|
|
"../../framework/util": 23,
|
|
"../cannon-util": 3
|
|
} ],
|
|
8: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.CannonSphereShape = void 0;
|
|
var _cannon = _interopRequireDefault(require("../../../../../../external/cannon/cannon"));
|
|
var _cannonUtil = require("../cannon-util");
|
|
var _cannonShape = require("./cannon-shape");
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
var v3_0 = new cc.Vec3();
|
|
var CannonSphereShape = function(_CannonShape) {
|
|
_inheritsLoose(CannonSphereShape, _CannonShape);
|
|
_createClass(CannonSphereShape, [ {
|
|
key: "sphereCollider",
|
|
get: function get() {
|
|
return this.collider;
|
|
}
|
|
}, {
|
|
key: "sphere",
|
|
get: function get() {
|
|
return this._shape;
|
|
}
|
|
}, {
|
|
key: "radius",
|
|
get: function get() {
|
|
return this._radius;
|
|
},
|
|
set: function set(v) {
|
|
this.collider.node.getWorldScale(v3_0);
|
|
var max = v3_0.maxAxis();
|
|
this.sphere.radius = v * Math.abs(max);
|
|
this.sphere.updateBoundingSphereRadius();
|
|
-1 != this._index && (0, _cannonUtil.commitShapeUpdates)(this._body);
|
|
}
|
|
} ]);
|
|
function CannonSphereShape(radius) {
|
|
var _this;
|
|
_this = _CannonShape.call(this) || this;
|
|
_this._radius = void 0;
|
|
_this._radius = radius;
|
|
_this._shape = new _cannon["default"].Sphere(_this._radius);
|
|
return _this;
|
|
}
|
|
var _proto = CannonSphereShape.prototype;
|
|
_proto.onLoad = function onLoad() {
|
|
_CannonShape.prototype.onLoad.call(this);
|
|
this.radius = this.sphereCollider.radius;
|
|
};
|
|
_proto.setScale = function setScale(scale) {
|
|
_CannonShape.prototype.setScale.call(this, scale);
|
|
this.radius = this.sphereCollider.radius;
|
|
};
|
|
return CannonSphereShape;
|
|
}(_cannonShape.CannonShape);
|
|
exports.CannonSphereShape = CannonSphereShape;
|
|
}, {
|
|
"../../../../../../external/cannon/cannon": 24,
|
|
"../cannon-util": 3,
|
|
"./cannon-shape": 7
|
|
} ],
|
|
9: [ function(require, module, exports) {
|
|
"use strict";
|
|
require("../cannon/instantiate");
|
|
var _cannon = _interopRequireDefault(require("../../../../../external/cannon/cannon"));
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
window && (window.CANNON = _cannon["default"]);
|
|
}, {
|
|
"../../../../../external/cannon/cannon": 24,
|
|
"../cannon/instantiate": 5
|
|
} ],
|
|
10: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
var _framework = require("../framework");
|
|
Object.keys(_framework).forEach(function(key) {
|
|
if ("default" === key || "__esModule" === key) return;
|
|
if (key in exports && exports[key] === _framework[key]) return;
|
|
exports[key] = _framework[key];
|
|
});
|
|
}, {
|
|
"../framework": 17
|
|
} ],
|
|
11: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.PhysicsMaterial = void 0;
|
|
var _dec, _class, _class2, _descriptor, _descriptor2, _class3, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _assertThisInitialized(self) {
|
|
if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
return self;
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
var _cc$_decorator = cc._decorator, ccclass = _cc$_decorator.ccclass, property = _cc$_decorator.property;
|
|
var fastRemove = cc.js.array.fastRemove;
|
|
var equals = cc.math.equals;
|
|
var PhysicsMaterial = (_dec = ccclass("cc.PhysicsMaterial"), _dec(_class = (_class2 = (_temp = _class3 = function(_cc$Asset) {
|
|
_inheritsLoose(PhysicsMaterial, _cc$Asset);
|
|
_createClass(PhysicsMaterial, [ {
|
|
key: "friction",
|
|
get: function get() {
|
|
return this._friction;
|
|
},
|
|
set: function set(value) {
|
|
if (!equals(this._friction, value)) {
|
|
this._friction = value;
|
|
this.emit("physics_material_update");
|
|
}
|
|
}
|
|
}, {
|
|
key: "restitution",
|
|
get: function get() {
|
|
return this._restitution;
|
|
},
|
|
set: function set(value) {
|
|
if (!equals(this._restitution, value)) {
|
|
this._restitution = value;
|
|
this.emit("physics_material_update");
|
|
}
|
|
}
|
|
} ]);
|
|
function PhysicsMaterial() {
|
|
var _this;
|
|
_this = _cc$Asset.call(this) || this;
|
|
_initializerDefineProperty(_this, "_friction", _descriptor, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_restitution", _descriptor2, _assertThisInitialized(_this));
|
|
cc.EventTarget.call(_assertThisInitialized(_this));
|
|
PhysicsMaterial.allMaterials.push(_assertThisInitialized(_this));
|
|
"" == _this._uuid && (_this._uuid = "pm_" + PhysicsMaterial._idCounter++);
|
|
return _this;
|
|
}
|
|
var _proto = PhysicsMaterial.prototype;
|
|
_proto.clone = function clone() {
|
|
var c = new PhysicsMaterial();
|
|
c._friction = this._friction;
|
|
c._restitution = this._restitution;
|
|
return c;
|
|
};
|
|
_proto.destroy = function destroy() {
|
|
if (_cc$Asset.prototype.destroy.call(this)) {
|
|
fastRemove(PhysicsMaterial.allMaterials, this);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
return PhysicsMaterial;
|
|
}(cc.Asset), _class3.allMaterials = [], _class3._idCounter = 0, _temp), _descriptor = _applyDecoratedDescriptor(_class2.prototype, "_friction", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return .1;
|
|
}
|
|
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "_restitution", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return .1;
|
|
}
|
|
}), _applyDecoratedDescriptor(_class2.prototype, "friction", [ property ], Object.getOwnPropertyDescriptor(_class2.prototype, "friction"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "restitution", [ property ], Object.getOwnPropertyDescriptor(_class2.prototype, "restitution"), _class2.prototype),
|
|
_class2)) || _class);
|
|
exports.PhysicsMaterial = PhysicsMaterial;
|
|
cc.js.mixin(PhysicsMaterial.prototype, cc.EventTarget.prototype);
|
|
cc.PhysicsMaterial = PhysicsMaterial;
|
|
}, {} ],
|
|
12: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.BoxCollider3D = void 0;
|
|
var _instance = require("../../instance");
|
|
var _colliderComponent = require("./collider-component");
|
|
var _dec, _dec2, _dec3, _dec4, _class, _class2, _descriptor, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _assertThisInitialized(self) {
|
|
if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
return self;
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
var _cc$_decorator = cc._decorator, ccclass = _cc$_decorator.ccclass, executeInEditMode = _cc$_decorator.executeInEditMode, executionOrder = _cc$_decorator.executionOrder, menu = _cc$_decorator.menu, property = _cc$_decorator.property;
|
|
var Vec3 = cc.Vec3;
|
|
var BoxCollider3D = (_dec = ccclass("cc.BoxCollider3D"), _dec2 = executionOrder(98),
|
|
_dec3 = menu("i18n:MAIN_MENU.component.physics/Collider/Box 3D"), _dec4 = property({
|
|
type: cc.Vec3
|
|
}), _dec(_class = _dec2(_class = _dec3(_class = executeInEditMode(_class = (_class2 = (_temp = function(_Collider3D) {
|
|
_inheritsLoose(BoxCollider3D, _Collider3D);
|
|
_createClass(BoxCollider3D, [ {
|
|
key: "size",
|
|
get: function get() {
|
|
return this._size;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._size, value);
|
|
true;
|
|
this.boxShape.size = this._size;
|
|
}
|
|
}, {
|
|
key: "boxShape",
|
|
get: function get() {
|
|
return this._shape;
|
|
}
|
|
} ]);
|
|
function BoxCollider3D() {
|
|
var _this;
|
|
_this = _Collider3D.call(this) || this;
|
|
_initializerDefineProperty(_this, "_size", _descriptor, _assertThisInitialized(_this));
|
|
true;
|
|
_this._shape = (0, _instance.createBoxShape)(_this._size);
|
|
return _this;
|
|
}
|
|
return BoxCollider3D;
|
|
}(_colliderComponent.Collider3D), _temp), _applyDecoratedDescriptor(_class2.prototype, "size", [ _dec4 ], Object.getOwnPropertyDescriptor(_class2.prototype, "size"), _class2.prototype),
|
|
_descriptor = _applyDecoratedDescriptor(_class2.prototype, "_size", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3(1, 1, 1);
|
|
}
|
|
}), _class2)) || _class) || _class) || _class) || _class);
|
|
exports.BoxCollider3D = BoxCollider3D;
|
|
}, {
|
|
"../../instance": 18,
|
|
"./collider-component": 13
|
|
} ],
|
|
13: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.Collider3D = void 0;
|
|
var _physicsMaterial = require("../../assets/physics-material");
|
|
var _dec, _dec2, _dec3, _dec4, _dec5, _class, _class2, _descriptor, _descriptor2, _descriptor3, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _assertThisInitialized(self) {
|
|
if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
return self;
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
var _cc$_decorator = cc._decorator, ccclass = _cc$_decorator.ccclass, property = _cc$_decorator.property;
|
|
var Vec3 = cc.Vec3;
|
|
var Collider3D = (_dec = ccclass("cc.Collider3D"), _dec2 = property({
|
|
type: _physicsMaterial.PhysicsMaterial,
|
|
displayName: "Material",
|
|
displayOrder: -1
|
|
}), _dec3 = property({
|
|
displayOrder: 0
|
|
}), _dec4 = property({
|
|
type: cc.Vec3,
|
|
displayOrder: 1
|
|
}), _dec5 = property({
|
|
type: _physicsMaterial.PhysicsMaterial
|
|
}), _dec(_class = (_class2 = (_temp = function(_cc$Component) {
|
|
_inheritsLoose(Collider3D, _cc$Component);
|
|
_createClass(Collider3D, [ {
|
|
key: "sharedMaterial",
|
|
get: function get() {
|
|
return this._material;
|
|
},
|
|
set: function set(value) {
|
|
this.material = value;
|
|
}
|
|
}, {
|
|
key: "material",
|
|
get: function get() {
|
|
true;
|
|
if (this._isSharedMaterial && null != this._material) {
|
|
this._material.off("physics_material_update", this._updateMaterial, this);
|
|
this._material = this._material.clone();
|
|
this._material.on("physics_material_update", this._updateMaterial, this);
|
|
this._isSharedMaterial = false;
|
|
}
|
|
return this._material;
|
|
},
|
|
set: function set(value) {
|
|
false, false;
|
|
if (null != value && null != this._material) {
|
|
if (this._material._uuid != value._uuid) {
|
|
this._material.off("physics_material_update", this._updateMaterial, this);
|
|
value.on("physics_material_update", this._updateMaterial, this);
|
|
this._isSharedMaterial = false;
|
|
this._material = value;
|
|
}
|
|
} else if (null != value && null == this._material) {
|
|
value.on("physics_material_update", this._updateMaterial, this);
|
|
this._material = value;
|
|
} else if (null == value && null != this._material) {
|
|
this._material.off("physics_material_update", this._updateMaterial, this);
|
|
this._material = value;
|
|
}
|
|
this._updateMaterial();
|
|
}
|
|
}, {
|
|
key: "isTrigger",
|
|
get: function get() {
|
|
return this._isTrigger;
|
|
},
|
|
set: function set(value) {
|
|
this._isTrigger = value;
|
|
true;
|
|
this._shape.isTrigger = this._isTrigger;
|
|
}
|
|
}, {
|
|
key: "center",
|
|
get: function get() {
|
|
return this._center;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._center, value);
|
|
true;
|
|
this._shape.center = this._center;
|
|
}
|
|
}, {
|
|
key: "attachedRigidbody",
|
|
get: function get() {
|
|
return this.shape.attachedRigidBody;
|
|
}
|
|
}, {
|
|
key: "shape",
|
|
get: function get() {
|
|
return this._shape;
|
|
}
|
|
}, {
|
|
key: "_assertOnload",
|
|
get: function get() {
|
|
var r = 0 == this._isOnLoadCalled;
|
|
r && cc.error("Physics Error: Please make sure that the node has been added to the scene");
|
|
return !r;
|
|
}
|
|
} ]);
|
|
function Collider3D() {
|
|
var _this;
|
|
_this = _cc$Component.call(this) || this;
|
|
_this._shape = void 0;
|
|
_this._isSharedMaterial = true;
|
|
_initializerDefineProperty(_this, "_material", _descriptor, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_isTrigger", _descriptor2, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_center", _descriptor3, _assertThisInitialized(_this));
|
|
cc.EventTarget.call(_assertThisInitialized(_this));
|
|
return _this;
|
|
}
|
|
var _proto = Collider3D.prototype;
|
|
_proto.on = function on(type, callback, target, useCapture) {};
|
|
_proto.off = function off(type, callback, target) {};
|
|
_proto.once = function once(type, callback, target) {};
|
|
_proto.emit = function emit(key) {};
|
|
_proto.__preload = function __preload() {
|
|
true;
|
|
this._shape.__preload(this);
|
|
};
|
|
_proto.onLoad = function onLoad() {
|
|
true;
|
|
true;
|
|
this.sharedMaterial = null == this._material ? cc.director.getPhysics3DManager().defaultMaterial : this._material;
|
|
this._shape.onLoad();
|
|
};
|
|
_proto.onEnable = function onEnable() {
|
|
true;
|
|
this._shape.onEnable();
|
|
};
|
|
_proto.onDisable = function onDisable() {
|
|
true;
|
|
this._shape.onDisable();
|
|
};
|
|
_proto.onDestroy = function onDestroy() {
|
|
true;
|
|
this._material && this._material.off("physics_material_update", this._updateMaterial, this);
|
|
this._shape.onDestroy();
|
|
};
|
|
_proto._updateMaterial = function _updateMaterial() {
|
|
true;
|
|
this._shape.material = this._material;
|
|
};
|
|
return Collider3D;
|
|
}(cc.Component), _temp), _applyDecoratedDescriptor(_class2.prototype, "sharedMaterial", [ _dec2 ], Object.getOwnPropertyDescriptor(_class2.prototype, "sharedMaterial"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "isTrigger", [ _dec3 ], Object.getOwnPropertyDescriptor(_class2.prototype, "isTrigger"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "center", [ _dec4 ], Object.getOwnPropertyDescriptor(_class2.prototype, "center"), _class2.prototype),
|
|
_descriptor = _applyDecoratedDescriptor(_class2.prototype, "_material", [ _dec5 ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return null;
|
|
}
|
|
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "_isTrigger", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return false;
|
|
}
|
|
}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "_center", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3();
|
|
}
|
|
}), _class2)) || _class);
|
|
exports.Collider3D = Collider3D;
|
|
cc.js.mixin(Collider3D.prototype, cc.EventTarget.prototype);
|
|
}, {
|
|
"../../assets/physics-material": 11
|
|
} ],
|
|
14: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.SphereCollider3D = void 0;
|
|
var _instance = require("../../instance");
|
|
var _colliderComponent = require("./collider-component");
|
|
var _dec, _dec2, _dec3, _class, _class2, _descriptor, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _assertThisInitialized(self) {
|
|
if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
return self;
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
var _cc$_decorator = cc._decorator, ccclass = _cc$_decorator.ccclass, executeInEditMode = _cc$_decorator.executeInEditMode, executionOrder = _cc$_decorator.executionOrder, menu = _cc$_decorator.menu, property = _cc$_decorator.property;
|
|
var SphereCollider3D = (_dec = ccclass("cc.SphereCollider3D"), _dec2 = executionOrder(98),
|
|
_dec3 = menu("i18n:MAIN_MENU.component.physics/Collider/Sphere 3D"), _dec(_class = _dec2(_class = _dec3(_class = executeInEditMode(_class = (_class2 = (_temp = function(_Collider3D) {
|
|
_inheritsLoose(SphereCollider3D, _Collider3D);
|
|
_createClass(SphereCollider3D, [ {
|
|
key: "radius",
|
|
get: function get() {
|
|
return this._radius;
|
|
},
|
|
set: function set(value) {
|
|
this._radius = value;
|
|
true;
|
|
this.sphereShape.radius = this._radius;
|
|
}
|
|
}, {
|
|
key: "sphereShape",
|
|
get: function get() {
|
|
return this._shape;
|
|
}
|
|
} ]);
|
|
function SphereCollider3D() {
|
|
var _this;
|
|
_this = _Collider3D.call(this) || this;
|
|
_initializerDefineProperty(_this, "_radius", _descriptor, _assertThisInitialized(_this));
|
|
true;
|
|
_this._shape = (0, _instance.createSphereShape)(_this._radius);
|
|
return _this;
|
|
}
|
|
return SphereCollider3D;
|
|
}(_colliderComponent.Collider3D), _temp), _applyDecoratedDescriptor(_class2.prototype, "radius", [ property ], Object.getOwnPropertyDescriptor(_class2.prototype, "radius"), _class2.prototype),
|
|
_descriptor = _applyDecoratedDescriptor(_class2.prototype, "_radius", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return .5;
|
|
}
|
|
}), _class2)) || _class) || _class) || _class) || _class);
|
|
exports.SphereCollider3D = SphereCollider3D;
|
|
}, {
|
|
"../../instance": 18,
|
|
"./collider-component": 13
|
|
} ],
|
|
15: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.ConstantForce = void 0;
|
|
var _rigidBodyComponent = require("./rigid-body-component");
|
|
var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _assertThisInitialized(self) {
|
|
if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
return self;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
var _cc$_decorator = cc._decorator, ccclass = _cc$_decorator.ccclass, executeInEditMode = _cc$_decorator.executeInEditMode, executionOrder = _cc$_decorator.executionOrder, menu = _cc$_decorator.menu, property = _cc$_decorator.property, requireComponent = _cc$_decorator.requireComponent, disallowMultiple = _cc$_decorator.disallowMultiple;
|
|
var Vec3 = cc.Vec3;
|
|
var ConstantForce = (_dec = ccclass("cc.ConstantForce"), _dec2 = executionOrder(98),
|
|
_dec3 = requireComponent(_rigidBodyComponent.RigidBody3D), _dec4 = menu("i18n:MAIN_MENU.component.physics/Constant Force 3D"),
|
|
_dec5 = property({
|
|
displayOrder: 0
|
|
}), _dec6 = property({
|
|
displayOrder: 1
|
|
}), _dec7 = property({
|
|
displayOrder: 2
|
|
}), _dec8 = property({
|
|
displayOrder: 3
|
|
}), _dec(_class = _dec2(_class = _dec3(_class = _dec4(_class = disallowMultiple(_class = executeInEditMode(_class = (_class2 = (_temp = function(_cc$Component) {
|
|
_inheritsLoose(ConstantForce, _cc$Component);
|
|
function ConstantForce() {
|
|
var _this;
|
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
|
|
_this = _cc$Component.call.apply(_cc$Component, [ this ].concat(args)) || this;
|
|
_this._rigidbody = null;
|
|
_initializerDefineProperty(_this, "_force", _descriptor, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_localForce", _descriptor2, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_torque", _descriptor3, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_localTorque", _descriptor4, _assertThisInitialized(_this));
|
|
_this._mask = 0;
|
|
return _this;
|
|
}
|
|
var _proto = ConstantForce.prototype;
|
|
_proto.onLoad = function onLoad() {
|
|
true;
|
|
this._rigidbody = this.node.getComponent(_rigidBodyComponent.RigidBody3D);
|
|
this._maskUpdate(this._force, 1);
|
|
this._maskUpdate(this._localForce, 2);
|
|
this._maskUpdate(this._torque, 4);
|
|
this._maskUpdate(this._localTorque, 8);
|
|
};
|
|
_proto.lateUpdate = function lateUpdate(dt) {
|
|
true;
|
|
if (null != this._rigidbody && 0 != this._mask) {
|
|
1 & this._mask && this._rigidbody.applyForce(this._force);
|
|
2 & this._mask && this._rigidbody.applyLocalForce(this.localForce);
|
|
4 & this._mask && this._rigidbody.applyTorque(this._torque);
|
|
8 & this._mask && this._rigidbody.applyLocalTorque(this._localTorque);
|
|
}
|
|
};
|
|
_proto._maskUpdate = function _maskUpdate(t, m) {
|
|
Vec3.strictEquals(t, Vec3.ZERO) ? this._mask &= ~m : this._mask |= m;
|
|
};
|
|
_createClass(ConstantForce, [ {
|
|
key: "force",
|
|
get: function get() {
|
|
return this._force;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._force, value);
|
|
this._maskUpdate(this._force, 1);
|
|
}
|
|
}, {
|
|
key: "localForce",
|
|
get: function get() {
|
|
return this._localForce;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._localForce, value);
|
|
this._maskUpdate(this.localForce, 2);
|
|
}
|
|
}, {
|
|
key: "torque",
|
|
get: function get() {
|
|
return this._torque;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._torque, value);
|
|
this._maskUpdate(this._torque, 4);
|
|
}
|
|
}, {
|
|
key: "localTorque",
|
|
get: function get() {
|
|
return this._localTorque;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._localTorque, value);
|
|
this._maskUpdate(this._localTorque, 8);
|
|
}
|
|
} ]);
|
|
return ConstantForce;
|
|
}(cc.Component), _temp), _descriptor = _applyDecoratedDescriptor(_class2.prototype, "_force", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3();
|
|
}
|
|
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "_localForce", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3();
|
|
}
|
|
}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "_torque", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3();
|
|
}
|
|
}), _descriptor4 = _applyDecoratedDescriptor(_class2.prototype, "_localTorque", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3();
|
|
}
|
|
}), _applyDecoratedDescriptor(_class2.prototype, "force", [ _dec5 ], Object.getOwnPropertyDescriptor(_class2.prototype, "force"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "localForce", [ _dec6 ], Object.getOwnPropertyDescriptor(_class2.prototype, "localForce"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "torque", [ _dec7 ], Object.getOwnPropertyDescriptor(_class2.prototype, "torque"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "localTorque", [ _dec8 ], Object.getOwnPropertyDescriptor(_class2.prototype, "localTorque"), _class2.prototype),
|
|
_class2)) || _class) || _class) || _class) || _class) || _class) || _class);
|
|
exports.ConstantForce = ConstantForce;
|
|
}, {
|
|
"./rigid-body-component": 16
|
|
} ],
|
|
16: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.RigidBody3D = void 0;
|
|
var _instance = require("../instance");
|
|
var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _dec11, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _descriptor8, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _assertThisInitialized(self) {
|
|
if (void 0 === self) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
return self;
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
var _cc$_decorator = cc._decorator, ccclass = _cc$_decorator.ccclass, disallowMultiple = _cc$_decorator.disallowMultiple, executeInEditMode = _cc$_decorator.executeInEditMode, executionOrder = _cc$_decorator.executionOrder, menu = _cc$_decorator.menu, property = _cc$_decorator.property;
|
|
var Vec3 = cc.Vec3;
|
|
var RigidBody3D = (_dec = ccclass("cc.RigidBody3D"), _dec2 = executionOrder(99),
|
|
_dec3 = menu("i18n:MAIN_MENU.component.physics/Rigid Body 3D"), _dec4 = property({
|
|
displayOrder: 0
|
|
}), _dec5 = property({
|
|
displayOrder: 1
|
|
}), _dec6 = property({
|
|
displayOrder: 2
|
|
}), _dec7 = property({
|
|
displayOrder: 3
|
|
}), _dec8 = property({
|
|
displayOrder: 4
|
|
}), _dec9 = property({
|
|
displayOrder: 5
|
|
}), _dec10 = property({
|
|
displayOrder: 6
|
|
}), _dec11 = property({
|
|
displayOrder: 7
|
|
}), _dec(_class = _dec2(_class = _dec3(_class = executeInEditMode(_class = disallowMultiple(_class = (_class2 = (_temp = function(_cc$Component) {
|
|
_inheritsLoose(RigidBody3D, _cc$Component);
|
|
_createClass(RigidBody3D, [ {
|
|
key: "allowSleep",
|
|
get: function get() {
|
|
return this._allowSleep;
|
|
},
|
|
set: function set(v) {
|
|
this._allowSleep = v;
|
|
true, true;
|
|
this._body.allowSleep = v;
|
|
}
|
|
}, {
|
|
key: "mass",
|
|
get: function get() {
|
|
return this._mass;
|
|
},
|
|
set: function set(value) {
|
|
this._mass = value;
|
|
true, true;
|
|
this._body.mass = value;
|
|
}
|
|
}, {
|
|
key: "linearDamping",
|
|
get: function get() {
|
|
return this._linearDamping;
|
|
},
|
|
set: function set(value) {
|
|
this._linearDamping = value;
|
|
true, true;
|
|
this._body.linearDamping = value;
|
|
}
|
|
}, {
|
|
key: "angularDamping",
|
|
get: function get() {
|
|
return this._angularDamping;
|
|
},
|
|
set: function set(value) {
|
|
this._angularDamping = value;
|
|
true, true;
|
|
this._body.angularDamping = value;
|
|
}
|
|
}, {
|
|
key: "isKinematic",
|
|
get: function get() {
|
|
return this._isKinematic;
|
|
},
|
|
set: function set(value) {
|
|
this._isKinematic = value;
|
|
true, true;
|
|
this._body.isKinematic = value;
|
|
}
|
|
}, {
|
|
key: "useGravity",
|
|
get: function get() {
|
|
return this._useGravity;
|
|
},
|
|
set: function set(value) {
|
|
this._useGravity = value;
|
|
true, true;
|
|
this._body.useGravity = value;
|
|
}
|
|
}, {
|
|
key: "fixedRotation",
|
|
get: function get() {
|
|
return this._fixedRotation;
|
|
},
|
|
set: function set(value) {
|
|
this._fixedRotation = value;
|
|
true, true;
|
|
this._body.fixedRotation = value;
|
|
}
|
|
}, {
|
|
key: "linearFactor",
|
|
get: function get() {
|
|
return this._linearFactor;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._linearFactor, value);
|
|
true, true;
|
|
this._body.linearFactor = this._linearFactor;
|
|
}
|
|
}, {
|
|
key: "angularFactor",
|
|
get: function get() {
|
|
return this._angularFactor;
|
|
},
|
|
set: function set(value) {
|
|
Vec3.copy(this._angularFactor, value);
|
|
true, true;
|
|
this._body.angularFactor = this._angularFactor;
|
|
}
|
|
}, {
|
|
key: "isAwake",
|
|
get: function get() {
|
|
if (this._assertOnload && true) return this._body.isAwake;
|
|
return false;
|
|
}
|
|
}, {
|
|
key: "isSleepy",
|
|
get: function get() {
|
|
if (this._assertOnload && true) return this._body.isSleepy;
|
|
return false;
|
|
}
|
|
}, {
|
|
key: "isSleeping",
|
|
get: function get() {
|
|
if (this._assertOnload && true) return this._body.isSleeping;
|
|
return false;
|
|
}
|
|
}, {
|
|
key: "rigidBody",
|
|
get: function get() {
|
|
return this._body;
|
|
}
|
|
}, {
|
|
key: "_assertOnload",
|
|
get: function get() {
|
|
var r = 0 == this._isOnLoadCalled;
|
|
r && cc.error("Physics Error: Please make sure that the node has been added to the scene");
|
|
return !r;
|
|
}
|
|
} ]);
|
|
function RigidBody3D() {
|
|
var _this;
|
|
_this = _cc$Component.call(this) || this;
|
|
_this._body = void 0;
|
|
_this._allowSleep = true;
|
|
_initializerDefineProperty(_this, "_mass", _descriptor, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_linearDamping", _descriptor2, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_angularDamping", _descriptor3, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_fixedRotation", _descriptor4, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_isKinematic", _descriptor5, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_useGravity", _descriptor6, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_linearFactor", _descriptor7, _assertThisInitialized(_this));
|
|
_initializerDefineProperty(_this, "_angularFactor", _descriptor8, _assertThisInitialized(_this));
|
|
true, true;
|
|
_this._body = (0, _instance.createRigidBody)();
|
|
return _this;
|
|
}
|
|
var _proto = RigidBody3D.prototype;
|
|
_proto.__preload = function __preload() {
|
|
true, true;
|
|
this._body.__preload(this);
|
|
};
|
|
_proto.onEnable = function onEnable() {
|
|
true, true;
|
|
this._body.onEnable();
|
|
};
|
|
_proto.onDisable = function onDisable() {
|
|
true, true;
|
|
this._body.onDisable();
|
|
};
|
|
_proto.onDestroy = function onDestroy() {
|
|
true, true;
|
|
this._body.onDestroy();
|
|
};
|
|
_proto.applyForce = function applyForce(force, relativePoint) {
|
|
this._assertOnload && true && this._body.applyForce(force, relativePoint);
|
|
};
|
|
_proto.applyLocalForce = function applyLocalForce(force, localPoint) {
|
|
this._assertOnload && true && this._body.applyLocalForce(force, localPoint);
|
|
};
|
|
_proto.applyImpulse = function applyImpulse(impulse, relativePoint) {
|
|
this._assertOnload && true && this._body.applyImpulse(impulse, relativePoint);
|
|
};
|
|
_proto.applyLocalImpulse = function applyLocalImpulse(impulse, localPoint) {
|
|
this._assertOnload && true && this._body.applyLocalImpulse(impulse, localPoint);
|
|
};
|
|
_proto.applyTorque = function applyTorque(torque) {
|
|
this._assertOnload && true && this._body.applyTorque(torque);
|
|
};
|
|
_proto.applyLocalTorque = function applyLocalTorque(torque) {
|
|
this._assertOnload && true && this._body.applyLocalTorque(torque);
|
|
};
|
|
_proto.wakeUp = function wakeUp() {
|
|
this._assertOnload && true && this._body.wakeUp();
|
|
};
|
|
_proto.sleep = function sleep() {
|
|
this._assertOnload && true && this._body.sleep();
|
|
};
|
|
_proto.getLinearVelocity = function getLinearVelocity(out) {
|
|
this._assertOnload && true && this._body.getLinearVelocity(out);
|
|
};
|
|
_proto.setLinearVelocity = function setLinearVelocity(value) {
|
|
this._assertOnload && true && this._body.setLinearVelocity(value);
|
|
};
|
|
_proto.getAngularVelocity = function getAngularVelocity(out) {
|
|
this._assertOnload && true && this._body.getAngularVelocity(out);
|
|
};
|
|
_proto.setAngularVelocity = function setAngularVelocity(value) {
|
|
this._assertOnload && true && this._body.setAngularVelocity(value);
|
|
};
|
|
return RigidBody3D;
|
|
}(cc.Component), _temp), _applyDecoratedDescriptor(_class2.prototype, "mass", [ _dec4 ], Object.getOwnPropertyDescriptor(_class2.prototype, "mass"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "linearDamping", [ _dec5 ], Object.getOwnPropertyDescriptor(_class2.prototype, "linearDamping"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "angularDamping", [ _dec6 ], Object.getOwnPropertyDescriptor(_class2.prototype, "angularDamping"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "isKinematic", [ _dec7 ], Object.getOwnPropertyDescriptor(_class2.prototype, "isKinematic"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "useGravity", [ _dec8 ], Object.getOwnPropertyDescriptor(_class2.prototype, "useGravity"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "fixedRotation", [ _dec9 ], Object.getOwnPropertyDescriptor(_class2.prototype, "fixedRotation"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "linearFactor", [ _dec10 ], Object.getOwnPropertyDescriptor(_class2.prototype, "linearFactor"), _class2.prototype),
|
|
_applyDecoratedDescriptor(_class2.prototype, "angularFactor", [ _dec11 ], Object.getOwnPropertyDescriptor(_class2.prototype, "angularFactor"), _class2.prototype),
|
|
_descriptor = _applyDecoratedDescriptor(_class2.prototype, "_mass", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return 10;
|
|
}
|
|
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "_linearDamping", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return .1;
|
|
}
|
|
}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "_angularDamping", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return .1;
|
|
}
|
|
}), _descriptor4 = _applyDecoratedDescriptor(_class2.prototype, "_fixedRotation", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return false;
|
|
}
|
|
}), _descriptor5 = _applyDecoratedDescriptor(_class2.prototype, "_isKinematic", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return false;
|
|
}
|
|
}), _descriptor6 = _applyDecoratedDescriptor(_class2.prototype, "_useGravity", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return true;
|
|
}
|
|
}), _descriptor7 = _applyDecoratedDescriptor(_class2.prototype, "_linearFactor", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3(1, 1, 1);
|
|
}
|
|
}), _descriptor8 = _applyDecoratedDescriptor(_class2.prototype, "_angularFactor", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new Vec3(1, 1, 1);
|
|
}
|
|
}), _class2)) || _class) || _class) || _class) || _class) || _class);
|
|
exports.RigidBody3D = RigidBody3D;
|
|
}, {
|
|
"../instance": 18
|
|
} ],
|
|
17: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
var _physicsManager = require("./physics-manager");
|
|
exports.Physics3DManager = _physicsManager.Physics3DManager;
|
|
var _physicsRayResult = require("./physics-ray-result");
|
|
exports.PhysicsRayResult = _physicsRayResult.PhysicsRayResult;
|
|
var _boxColliderComponent = require("./components/collider/box-collider-component");
|
|
exports.BoxCollider3D = _boxColliderComponent.BoxCollider3D;
|
|
var _colliderComponent = require("./components/collider/collider-component");
|
|
exports.Collider3D = _colliderComponent.Collider3D;
|
|
var _sphereColliderComponent = require("./components/collider/sphere-collider-component");
|
|
exports.SphereCollider3D = _sphereColliderComponent.SphereCollider3D;
|
|
var _rigidBodyComponent = require("./components/rigid-body-component");
|
|
exports.RigidBody3D = _rigidBodyComponent.RigidBody3D;
|
|
var _constantForce = require("./components/constant-force");
|
|
var _physicsMaterial = require("./assets/physics-material");
|
|
exports.PhysicsMaterial = _physicsMaterial.PhysicsMaterial;
|
|
cc.Physics3DManager = _physicsManager.Physics3DManager;
|
|
cc.Collider3D = _colliderComponent.Collider3D;
|
|
cc.BoxCollider3D = _boxColliderComponent.BoxCollider3D;
|
|
cc.SphereCollider3D = _sphereColliderComponent.SphereCollider3D;
|
|
cc.RigidBody3D = _rigidBodyComponent.RigidBody3D;
|
|
cc.PhysicsRayResult = _physicsRayResult.PhysicsRayResult;
|
|
cc.ConstantForce = _constantForce.ConstantForce;
|
|
}, {
|
|
"./assets/physics-material": 11,
|
|
"./components/collider/box-collider-component": 12,
|
|
"./components/collider/collider-component": 13,
|
|
"./components/collider/sphere-collider-component": 14,
|
|
"./components/constant-force": 15,
|
|
"./components/rigid-body-component": 16,
|
|
"./physics-manager": 20,
|
|
"./physics-ray-result": 21
|
|
} ],
|
|
18: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.createPhysicsWorld = createPhysicsWorld;
|
|
exports.createRigidBody = createRigidBody;
|
|
exports.createBoxShape = createBoxShape;
|
|
exports.createSphereShape = createSphereShape;
|
|
var _physicsSelector = require("./physics-selector");
|
|
function createPhysicsWorld() {
|
|
return new _physicsSelector.PhysicsWorld();
|
|
}
|
|
function createRigidBody() {
|
|
return new _physicsSelector.RigidBody();
|
|
}
|
|
function createBoxShape(size) {
|
|
return new _physicsSelector.BoxShape(size);
|
|
}
|
|
function createSphereShape(radius) {
|
|
return new _physicsSelector.SphereShape(radius);
|
|
}
|
|
}, {
|
|
"./physics-selector": 22
|
|
} ],
|
|
19: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.ERigidBodyType = void 0;
|
|
var ERigidBodyType;
|
|
exports.ERigidBodyType = ERigidBodyType;
|
|
(function(ERigidBodyType) {
|
|
ERigidBodyType[ERigidBodyType["DYNAMIC"] = 1] = "DYNAMIC";
|
|
ERigidBodyType[ERigidBodyType["STATIC"] = 2] = "STATIC";
|
|
ERigidBodyType[ERigidBodyType["KINEMATIC"] = 4] = "KINEMATIC";
|
|
})(ERigidBodyType || (exports.ERigidBodyType = ERigidBodyType = {}));
|
|
}, {} ],
|
|
20: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.Physics3DManager = void 0;
|
|
var _instance = require("./instance");
|
|
var _physicsMaterial = require("./assets/physics-material");
|
|
var _physicsRayResult = require("./physics-ray-result");
|
|
var _dec, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _temp;
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer ? descriptor.initializer.call(context) : void 0
|
|
});
|
|
}
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
("value" in desc || desc.initializer) && (desc.writable = true);
|
|
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
if (context && void 0 !== desc.initializer) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = void 0;
|
|
}
|
|
if (void 0 === desc.initializer) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
return desc;
|
|
}
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error("Decorating class property failed. Please ensure that proposal-class-properties is enabled and runs after the decorators transform.");
|
|
}
|
|
var _cc$_decorator = cc._decorator, property = _cc$_decorator.property, ccclass = _cc$_decorator.ccclass;
|
|
var Physics3DManager = (_dec = ccclass("cc.Physics3DManager"), _dec(_class = (_class2 = (_temp = function() {
|
|
_createClass(Physics3DManager, [ {
|
|
key: "enabled",
|
|
get: function get() {
|
|
return this._enabled;
|
|
},
|
|
set: function set(value) {
|
|
this._enabled = value;
|
|
}
|
|
}, {
|
|
key: "allowSleep",
|
|
get: function get() {
|
|
return this._allowSleep;
|
|
},
|
|
set: function set(v) {
|
|
this._allowSleep = v;
|
|
true, true;
|
|
this.physicsWorld.allowSleep = this._allowSleep;
|
|
}
|
|
}, {
|
|
key: "maxSubStep",
|
|
get: function get() {
|
|
return this._maxSubStep;
|
|
},
|
|
set: function set(value) {
|
|
this._maxSubStep = value;
|
|
}
|
|
}, {
|
|
key: "deltaTime",
|
|
get: function get() {
|
|
return this._fixedTime;
|
|
},
|
|
set: function set(value) {
|
|
this._fixedTime = value;
|
|
}
|
|
}, {
|
|
key: "useFixedTime",
|
|
get: function get() {
|
|
return this._useFixedTime;
|
|
},
|
|
set: function set(value) {
|
|
this._useFixedTime = value;
|
|
}
|
|
}, {
|
|
key: "gravity",
|
|
get: function get() {
|
|
return this._gravity;
|
|
},
|
|
set: function set(gravity) {
|
|
this._gravity.set(gravity);
|
|
true, true;
|
|
this.physicsWorld.gravity = gravity;
|
|
}
|
|
}, {
|
|
key: "defaultMaterial",
|
|
get: function get() {
|
|
return this._material;
|
|
}
|
|
} ]);
|
|
function Physics3DManager() {
|
|
this.physicsWorld = void 0;
|
|
this.raycastClosestResult = new _physicsRayResult.PhysicsRayResult();
|
|
this.raycastResults = [];
|
|
_initializerDefineProperty(this, "_enabled", _descriptor, this);
|
|
_initializerDefineProperty(this, "_allowSleep", _descriptor2, this);
|
|
_initializerDefineProperty(this, "_gravity", _descriptor3, this);
|
|
_initializerDefineProperty(this, "_maxSubStep", _descriptor4, this);
|
|
_initializerDefineProperty(this, "_fixedTime", _descriptor5, this);
|
|
_initializerDefineProperty(this, "_useFixedTime", _descriptor6, this);
|
|
this.useAccumulator = false;
|
|
this._accumulator = 0;
|
|
this.useFixedDigit = false;
|
|
this.useInternalTime = false;
|
|
this.fixDigits = {
|
|
position: 5,
|
|
rotation: 12,
|
|
timeNow: 3
|
|
};
|
|
this._deltaTime = 0;
|
|
this._lastTime = 0;
|
|
this._material = null;
|
|
this.raycastOptions = {
|
|
groupIndex: -1,
|
|
queryTrigger: true,
|
|
maxDistance: Infinity
|
|
};
|
|
this.raycastResultPool = new cc.RecyclePool(function() {
|
|
return new _physicsRayResult.PhysicsRayResult();
|
|
}, 1);
|
|
cc.director._scheduler && cc.director._scheduler.enableForTarget(this);
|
|
this.physicsWorld = (0, _instance.createPhysicsWorld)();
|
|
this._lastTime = performance.now();
|
|
true;
|
|
this.gravity = this._gravity;
|
|
this.allowSleep = this._allowSleep;
|
|
this._material = new _physicsMaterial.PhysicsMaterial();
|
|
this._material.friction = .1;
|
|
this._material.restitution = .1;
|
|
this._material.on("physics_material_update", this._updateMaterial, this);
|
|
this.physicsWorld.defaultMaterial = this._material;
|
|
}
|
|
var _proto = Physics3DManager.prototype;
|
|
_proto.update = function update(deltaTime) {
|
|
false;
|
|
if (!this._enabled) return;
|
|
if (this.useInternalTime) {
|
|
var now = parseFloat(performance.now().toFixed(this.fixDigits.timeNow));
|
|
this._deltaTime = now > this._lastTime ? (now - this._lastTime) / 1e3 : 0;
|
|
this._lastTime = now;
|
|
} else this._deltaTime = deltaTime;
|
|
cc.director.emit(cc.Director.EVENT_BEFORE_PHYSICS);
|
|
false;
|
|
if (this._useFixedTime) this.physicsWorld.step(this._fixedTime); else if (this.useAccumulator) {
|
|
var i = 0;
|
|
this._accumulator += this._deltaTime;
|
|
while (i < this._maxSubStep && this._accumulator > this._fixedTime) {
|
|
this.physicsWorld.step(this._fixedTime);
|
|
this._accumulator -= this._fixedTime;
|
|
i++;
|
|
}
|
|
} else this.physicsWorld.step(this._fixedTime, this._deltaTime, this._maxSubStep);
|
|
cc.director.emit(cc.Director.EVENT_AFTER_PHYSICS);
|
|
};
|
|
_proto.raycast = function raycast(worldRay, groupIndexOrName, maxDistance, queryTrigger) {
|
|
void 0 === groupIndexOrName && (groupIndexOrName = 0);
|
|
void 0 === maxDistance && (maxDistance = Infinity);
|
|
void 0 === queryTrigger && (queryTrigger = true);
|
|
this.raycastResultPool.reset();
|
|
this.raycastResults.length = 0;
|
|
if ("string" == typeof groupIndexOrName) {
|
|
var groupIndex = cc.game.groupList.indexOf(groupIndexOrName);
|
|
-1 == groupIndex && (groupIndex = 0);
|
|
this.raycastOptions.groupIndex = groupIndex;
|
|
} else this.raycastOptions.groupIndex = groupIndexOrName;
|
|
this.raycastOptions.maxDistance = maxDistance;
|
|
this.raycastOptions.queryTrigger = queryTrigger;
|
|
var result = this.physicsWorld.raycast(worldRay, this.raycastOptions, this.raycastResultPool, this.raycastResults);
|
|
if (result) return this.raycastResults;
|
|
return null;
|
|
};
|
|
_proto.raycastClosest = function raycastClosest(worldRay, groupIndexOrName, maxDistance, queryTrigger) {
|
|
void 0 === groupIndexOrName && (groupIndexOrName = 0);
|
|
void 0 === maxDistance && (maxDistance = Infinity);
|
|
void 0 === queryTrigger && (queryTrigger = true);
|
|
if ("string" == typeof groupIndexOrName) {
|
|
var groupIndex = cc.game.groupList.indexOf(groupIndexOrName);
|
|
-1 == groupIndex && (groupIndex = 0);
|
|
this.raycastOptions.groupIndex = groupIndex;
|
|
} else this.raycastOptions.groupIndex = groupIndexOrName;
|
|
this.raycastOptions.maxDistance = maxDistance;
|
|
this.raycastOptions.queryTrigger = queryTrigger;
|
|
var result = this.physicsWorld.raycastClosest(worldRay, this.raycastOptions, this.raycastClosestResult);
|
|
if (result) return this.raycastClosestResult;
|
|
return null;
|
|
};
|
|
_proto._updateMaterial = function _updateMaterial() {
|
|
true;
|
|
this.physicsWorld.defaultMaterial = this._material;
|
|
};
|
|
return Physics3DManager;
|
|
}(), _temp), _descriptor = _applyDecoratedDescriptor(_class2.prototype, "_enabled", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return false;
|
|
}
|
|
}), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "_allowSleep", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return true;
|
|
}
|
|
}), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, "_gravity", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return new cc.Vec3(0, -10, 0);
|
|
}
|
|
}), _descriptor4 = _applyDecoratedDescriptor(_class2.prototype, "_maxSubStep", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return 1;
|
|
}
|
|
}), _descriptor5 = _applyDecoratedDescriptor(_class2.prototype, "_fixedTime", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return 1 / 60;
|
|
}
|
|
}), _descriptor6 = _applyDecoratedDescriptor(_class2.prototype, "_useFixedTime", [ property ], {
|
|
configurable: true,
|
|
enumerable: true,
|
|
writable: true,
|
|
initializer: function initializer() {
|
|
return true;
|
|
}
|
|
}), _class2)) || _class);
|
|
exports.Physics3DManager = Physics3DManager;
|
|
}, {
|
|
"./assets/physics-material": 11,
|
|
"./instance": 18,
|
|
"./physics-ray-result": 21
|
|
} ],
|
|
21: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.PhysicsRayResult = void 0;
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
"value" in descriptor && (descriptor.writable = true);
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
protoProps && _defineProperties(Constructor.prototype, protoProps);
|
|
staticProps && _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
var Vec3 = cc.Vec3;
|
|
var PhysicsRayResult = function() {
|
|
function PhysicsRayResult() {
|
|
this._hitPoint = new Vec3();
|
|
this._distance = 0;
|
|
this._collidier = null;
|
|
}
|
|
var _proto = PhysicsRayResult.prototype;
|
|
_proto._assign = function _assign(hitPoint, distance, collider) {
|
|
Vec3.copy(this._hitPoint, hitPoint);
|
|
this._distance = distance;
|
|
this._collidier = collider;
|
|
};
|
|
_proto.clone = function clone() {
|
|
var c = new PhysicsRayResult();
|
|
Vec3.copy(c._hitPoint, this._hitPoint);
|
|
c._distance = this._distance;
|
|
c._collidier = this._collidier;
|
|
return c;
|
|
};
|
|
_createClass(PhysicsRayResult, [ {
|
|
key: "hitPoint",
|
|
get: function get() {
|
|
return this._hitPoint;
|
|
}
|
|
}, {
|
|
key: "distance",
|
|
get: function get() {
|
|
return this._distance;
|
|
}
|
|
}, {
|
|
key: "collider",
|
|
get: function get() {
|
|
return this._collidier;
|
|
}
|
|
} ]);
|
|
return PhysicsRayResult;
|
|
}();
|
|
exports.PhysicsRayResult = PhysicsRayResult;
|
|
}, {} ],
|
|
22: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.instantiate = instantiate;
|
|
exports.PhysicsWorld = exports.RigidBody = exports.SphereShape = exports.BoxShape = void 0;
|
|
var BoxShape;
|
|
exports.BoxShape = BoxShape;
|
|
var SphereShape;
|
|
exports.SphereShape = SphereShape;
|
|
var RigidBody;
|
|
exports.RigidBody = RigidBody;
|
|
var PhysicsWorld;
|
|
exports.PhysicsWorld = PhysicsWorld;
|
|
function instantiate(boxShape, sphereShape, body, world) {
|
|
exports.BoxShape = BoxShape = boxShape;
|
|
exports.SphereShape = SphereShape = sphereShape;
|
|
exports.RigidBody = RigidBody = body;
|
|
exports.PhysicsWorld = PhysicsWorld = world;
|
|
}
|
|
}, {} ],
|
|
23: [ function(require, module, exports) {
|
|
"use strict";
|
|
exports.__esModule = true;
|
|
exports.stringfyVec3 = stringfyVec3;
|
|
exports.stringfyQuat = stringfyQuat;
|
|
exports.setWrap = setWrap;
|
|
exports.getWrap = getWrap;
|
|
exports.clearNodeTransformDirtyFlag = clearNodeTransformDirtyFlag;
|
|
exports.clearNodeTransformRecord = clearNodeTransformRecord;
|
|
exports.updateWorldTransform = updateWorldTransform;
|
|
exports.updateWorldRT = updateWorldRT;
|
|
exports.worldDirty = worldDirty;
|
|
function stringfyVec3(value) {
|
|
return "(x: " + value.x + ", y: " + value.y + ", z: " + value.z + ")";
|
|
}
|
|
function stringfyQuat(value) {
|
|
return "(x: " + value.x + ", y: " + value.y + ", z: " + value.z + ", w: " + value.w + ")";
|
|
}
|
|
function setWrap(object, wrapper) {
|
|
object.__cc_wrapper__ = wrapper;
|
|
}
|
|
function getWrap(object) {
|
|
return object.__cc_wrapper__;
|
|
}
|
|
var LocalDirtyFlag = cc.Node._LocalDirtyFlag;
|
|
var PHYSICS_TRS = LocalDirtyFlag.PHYSICS_TRS;
|
|
var ALL_TRS = LocalDirtyFlag.ALL_TRS;
|
|
var SKEW = LocalDirtyFlag.SKEW;
|
|
var FLAG_TRANSFORM = cc.RenderFlow.FLAG_TRANSFORM;
|
|
var Mat3 = cc.Mat3;
|
|
var Mat4 = cc.Mat4;
|
|
var Vec3 = cc.Vec3;
|
|
var Quat = cc.Quat;
|
|
var Trs = cc.Trs;
|
|
var _nodeArray = [];
|
|
var _lpos = cc.v3();
|
|
var _lrot = cc.quat();
|
|
var _mat3 = new Mat3();
|
|
var _mat3m = _mat3.m;
|
|
var _quat = cc.quat();
|
|
var _mat4 = cc.mat4();
|
|
var _nodeTransformRecord = {};
|
|
function clearNodeTransformDirtyFlag() {
|
|
for (var key in _nodeTransformRecord) {
|
|
var physicsNode = _nodeTransformRecord[key];
|
|
physicsNode._localMatDirty &= ~ALL_TRS;
|
|
if (!(physicsNode._localMatDirty & SKEW)) {
|
|
physicsNode._worldMatDirty = false;
|
|
true, physicsNode._renderFlag &= ~FLAG_TRANSFORM;
|
|
}
|
|
}
|
|
_nodeTransformRecord = {};
|
|
_nodeArray.length = 0;
|
|
}
|
|
function clearNodeTransformRecord() {
|
|
_nodeTransformRecord = {};
|
|
_nodeArray.length = 0;
|
|
}
|
|
function updateWorldTransform(node, traverseAllNode) {
|
|
void 0 === traverseAllNode && (traverseAllNode = false);
|
|
var cur = node;
|
|
var i = 0;
|
|
var needUpdateTransform = false;
|
|
var physicsDirtyFlag = 0;
|
|
while (cur) {
|
|
if (!traverseAllNode && _nodeTransformRecord[cur._id]) {
|
|
physicsDirtyFlag |= cur._localMatDirty & PHYSICS_TRS;
|
|
needUpdateTransform = needUpdateTransform || !!physicsDirtyFlag;
|
|
break;
|
|
}
|
|
_nodeArray[i++] = cur;
|
|
cur._localMatDirty & PHYSICS_TRS && (needUpdateTransform = true);
|
|
cur = cur._parent;
|
|
}
|
|
if (!needUpdateTransform) return false;
|
|
var child;
|
|
var childWorldMat, curWorldMat, childTrs, childLocalMat;
|
|
var wpos, wrot, wscale;
|
|
_nodeArray.length = i;
|
|
while (i) {
|
|
child = _nodeArray[--i];
|
|
!traverseAllNode && (_nodeTransformRecord[child._id] = child);
|
|
childWorldMat = child._worldMatrix;
|
|
childLocalMat = child._matrix;
|
|
childTrs = child._trs;
|
|
wpos = child.__wpos = child.__wpos || cc.v3();
|
|
wrot = child.__wrot = child.__wrot || cc.quat();
|
|
wscale = child.__wscale = child.__wscale || cc.v3();
|
|
child._localMatDirty & PHYSICS_TRS && Trs.toMat4(childLocalMat, childTrs);
|
|
child._localMatDirty |= physicsDirtyFlag;
|
|
physicsDirtyFlag |= child._localMatDirty & PHYSICS_TRS;
|
|
if (!(physicsDirtyFlag & PHYSICS_TRS)) {
|
|
cur = child;
|
|
continue;
|
|
}
|
|
if (cur) {
|
|
curWorldMat = cur._worldMatrix;
|
|
Trs.toPosition(_lpos, childTrs);
|
|
Vec3.transformMat4(wpos, _lpos, curWorldMat);
|
|
Mat4.multiply(childWorldMat, curWorldMat, childLocalMat);
|
|
Trs.toRotation(_lrot, childTrs);
|
|
Quat.multiply(wrot, cur.__wrot, _lrot);
|
|
Mat3.fromQuat(_mat3, Quat.conjugate(_quat, wrot));
|
|
Mat3.multiplyMat4(_mat3, _mat3, childWorldMat);
|
|
wscale.x = _mat3m[0];
|
|
wscale.y = _mat3m[4];
|
|
wscale.z = _mat3m[8];
|
|
} else {
|
|
Trs.toPosition(wpos, childTrs);
|
|
Trs.toRotation(wrot, childTrs);
|
|
Trs.toScale(wscale, childTrs);
|
|
Mat4.copy(childWorldMat, childLocalMat);
|
|
}
|
|
cur = child;
|
|
}
|
|
return true;
|
|
}
|
|
function updateWorldRT(node, position, rotation) {
|
|
var parent = node.parent;
|
|
if (parent) {
|
|
updateWorldTransform(parent, true);
|
|
Vec3.transformMat4(_lpos, position, Mat4.invert(_mat4, parent._worldMatrix));
|
|
Quat.multiply(_quat, Quat.conjugate(_quat, parent.__wrot), rotation);
|
|
node.setPosition(_lpos);
|
|
node.setRotation(_quat);
|
|
} else {
|
|
node.setPosition(position);
|
|
node.setRotation(rotation);
|
|
}
|
|
}
|
|
function worldDirty(node) {
|
|
var cur = node;
|
|
while (cur) {
|
|
if (cur._worldMatDirty) return true;
|
|
cur = cur._parent;
|
|
}
|
|
return false;
|
|
}
|
|
}, {} ],
|
|
24: [ function(require, module, exports) {
|
|
(function(global) {
|
|
"use strict";
|
|
!function(e) {
|
|
if ("object" == typeof exports && "undefined" != typeof module) module.exports = e(); else if ("function" == typeof define && define.amd) define([], e); else {
|
|
var f;
|
|
"undefined" != typeof window ? f = window : "undefined" != typeof global ? f = global : "undefined" != typeof self && (f = self),
|
|
f.CANNON = e();
|
|
}
|
|
}(function() {
|
|
var define, module, exports;
|
|
return function e(t, n, r) {
|
|
function s(o, u) {
|
|
if (!n[o]) {
|
|
if (!t[o]) {
|
|
var a = "function" == typeof require && require;
|
|
if (!u && a) return a(o, !0);
|
|
if (i) return i(o, !0);
|
|
throw new Error("Cannot find module '" + o + "'");
|
|
}
|
|
var f = n[o] = {
|
|
exports: {}
|
|
};
|
|
t[o][0].call(f.exports, function(e) {
|
|
var n = t[o][1][e];
|
|
return s(n || e);
|
|
}, f, f.exports, e, t, n, r);
|
|
}
|
|
return n[o].exports;
|
|
}
|
|
var i = "function" == typeof require && require;
|
|
for (var o = 0; o < r.length; o++) s(r[o]);
|
|
return s;
|
|
}({
|
|
1: [ function(_dereq_, module, exports) {
|
|
module.exports = {
|
|
name: "@cocos/cannon",
|
|
version: "1.1.1-exp.3",
|
|
description: "A lightweight 3D physics engine written in JavaScript.",
|
|
homepage: "https://github.com/cocos-creator/cannon.js",
|
|
author: "Stefan Hedman <schteppe@gmail.com> (http://steffe.se), JayceLai",
|
|
keywords: [ "cannon.js", "cocos", "creator", "physics", "engine", "3d" ],
|
|
scripts: {
|
|
build: "grunt && npm run preprocess && grunt addLicense && grunt addDate",
|
|
preprocess: "node node_modules/uglify-js/bin/uglifyjs build/cannon.js -o build/cannon.min.js -c -m"
|
|
},
|
|
main: "./build/cannon.min.js",
|
|
engines: {
|
|
node: "*"
|
|
},
|
|
repository: {
|
|
type: "git",
|
|
url: "https://github.com/cocos-creator/cannon.js.git"
|
|
},
|
|
bugs: {
|
|
url: "https://github.com/cocos-creator/cannon.js/issues"
|
|
},
|
|
licenses: [ {
|
|
type: "MIT"
|
|
} ],
|
|
devDependencies: {
|
|
jshint: "latest",
|
|
"uglify-js": "latest",
|
|
nodeunit: "^0.9.0",
|
|
grunt: "~0.4.0",
|
|
"grunt-contrib-jshint": "~0.1.1",
|
|
"grunt-contrib-nodeunit": "^0.4.1",
|
|
"grunt-contrib-concat": "~0.1.3",
|
|
"grunt-contrib-uglify": "^0.5.1",
|
|
"grunt-browserify": "^2.1.4",
|
|
"grunt-contrib-yuidoc": "^0.5.2",
|
|
browserify: "*"
|
|
},
|
|
dependencies: {}
|
|
};
|
|
}, {} ],
|
|
2: [ function(_dereq_, module, exports) {
|
|
module.exports = {
|
|
version: _dereq_("../package.json").version,
|
|
AABB: _dereq_("./collision/AABB"),
|
|
ArrayCollisionMatrix: _dereq_("./collision/ArrayCollisionMatrix"),
|
|
Body: _dereq_("./objects/Body"),
|
|
Box: _dereq_("./shapes/Box"),
|
|
Broadphase: _dereq_("./collision/Broadphase"),
|
|
Constraint: _dereq_("./constraints/Constraint"),
|
|
ContactEquation: _dereq_("./equations/ContactEquation"),
|
|
Narrowphase: _dereq_("./world/Narrowphase"),
|
|
ConeTwistConstraint: _dereq_("./constraints/ConeTwistConstraint"),
|
|
ContactMaterial: _dereq_("./material/ContactMaterial"),
|
|
ConvexPolyhedron: _dereq_("./shapes/ConvexPolyhedron"),
|
|
Cylinder: _dereq_("./shapes/Cylinder"),
|
|
DistanceConstraint: _dereq_("./constraints/DistanceConstraint"),
|
|
Equation: _dereq_("./equations/Equation"),
|
|
EventTarget: _dereq_("./utils/EventTarget"),
|
|
FrictionEquation: _dereq_("./equations/FrictionEquation"),
|
|
GSSolver: _dereq_("./solver/GSSolver"),
|
|
GridBroadphase: _dereq_("./collision/GridBroadphase"),
|
|
Heightfield: _dereq_("./shapes/Heightfield"),
|
|
HingeConstraint: _dereq_("./constraints/HingeConstraint"),
|
|
LockConstraint: _dereq_("./constraints/LockConstraint"),
|
|
Mat3: _dereq_("./math/Mat3"),
|
|
Material: _dereq_("./material/Material"),
|
|
NaiveBroadphase: _dereq_("./collision/NaiveBroadphase"),
|
|
ObjectCollisionMatrix: _dereq_("./collision/ObjectCollisionMatrix"),
|
|
Pool: _dereq_("./utils/Pool"),
|
|
Particle: _dereq_("./shapes/Particle"),
|
|
Plane: _dereq_("./shapes/Plane"),
|
|
PointToPointConstraint: _dereq_("./constraints/PointToPointConstraint"),
|
|
Quaternion: _dereq_("./math/Quaternion"),
|
|
Ray: _dereq_("./collision/Ray"),
|
|
RaycastVehicle: _dereq_("./objects/RaycastVehicle"),
|
|
RaycastResult: _dereq_("./collision/RaycastResult"),
|
|
RigidVehicle: _dereq_("./objects/RigidVehicle"),
|
|
RotationalEquation: _dereq_("./equations/RotationalEquation"),
|
|
RotationalMotorEquation: _dereq_("./equations/RotationalMotorEquation"),
|
|
SAPBroadphase: _dereq_("./collision/SAPBroadphase"),
|
|
SPHSystem: _dereq_("./objects/SPHSystem"),
|
|
Shape: _dereq_("./shapes/Shape"),
|
|
Solver: _dereq_("./solver/Solver"),
|
|
Sphere: _dereq_("./shapes/Sphere"),
|
|
SplitSolver: _dereq_("./solver/SplitSolver"),
|
|
Spring: _dereq_("./objects/Spring"),
|
|
Transform: _dereq_("./math/Transform"),
|
|
Trimesh: _dereq_("./shapes/Trimesh"),
|
|
Vec3: _dereq_("./math/Vec3"),
|
|
Vec3Pool: _dereq_("./utils/Vec3Pool"),
|
|
World: _dereq_("./world/World"),
|
|
Octree: _dereq_("./utils/Octree"),
|
|
CMath: _dereq_("./math/CMath")
|
|
};
|
|
}, {
|
|
"../package.json": 1,
|
|
"./collision/AABB": 3,
|
|
"./collision/ArrayCollisionMatrix": 4,
|
|
"./collision/Broadphase": 5,
|
|
"./collision/GridBroadphase": 6,
|
|
"./collision/NaiveBroadphase": 7,
|
|
"./collision/ObjectCollisionMatrix": 8,
|
|
"./collision/Ray": 10,
|
|
"./collision/RaycastResult": 11,
|
|
"./collision/SAPBroadphase": 12,
|
|
"./constraints/ConeTwistConstraint": 13,
|
|
"./constraints/Constraint": 14,
|
|
"./constraints/DistanceConstraint": 15,
|
|
"./constraints/HingeConstraint": 16,
|
|
"./constraints/LockConstraint": 17,
|
|
"./constraints/PointToPointConstraint": 18,
|
|
"./equations/ContactEquation": 20,
|
|
"./equations/Equation": 21,
|
|
"./equations/FrictionEquation": 22,
|
|
"./equations/RotationalEquation": 23,
|
|
"./equations/RotationalMotorEquation": 24,
|
|
"./material/ContactMaterial": 25,
|
|
"./material/Material": 26,
|
|
"./math/CMath": 27,
|
|
"./math/Mat3": 29,
|
|
"./math/Quaternion": 30,
|
|
"./math/Transform": 31,
|
|
"./math/Vec3": 32,
|
|
"./objects/Body": 33,
|
|
"./objects/RaycastVehicle": 34,
|
|
"./objects/RigidVehicle": 35,
|
|
"./objects/SPHSystem": 36,
|
|
"./objects/Spring": 37,
|
|
"./shapes/Box": 39,
|
|
"./shapes/ConvexPolyhedron": 40,
|
|
"./shapes/Cylinder": 41,
|
|
"./shapes/Heightfield": 42,
|
|
"./shapes/Particle": 43,
|
|
"./shapes/Plane": 44,
|
|
"./shapes/Shape": 45,
|
|
"./shapes/Sphere": 46,
|
|
"./shapes/Trimesh": 47,
|
|
"./solver/GSSolver": 48,
|
|
"./solver/Solver": 49,
|
|
"./solver/SplitSolver": 50,
|
|
"./utils/EventTarget": 51,
|
|
"./utils/Octree": 52,
|
|
"./utils/Pool": 53,
|
|
"./utils/Vec3Pool": 56,
|
|
"./world/Narrowphase": 57,
|
|
"./world/World": 58
|
|
} ],
|
|
3: [ function(_dereq_, module, exports) {
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Utils = _dereq_("../utils/Utils");
|
|
module.exports = AABB;
|
|
function AABB(options) {
|
|
options = options || {};
|
|
this.lowerBound = new Vec3();
|
|
options.lowerBound && this.lowerBound.copy(options.lowerBound);
|
|
this.upperBound = new Vec3();
|
|
options.upperBound && this.upperBound.copy(options.upperBound);
|
|
}
|
|
var tmp = new Vec3();
|
|
AABB.prototype.setFromPoints = function(points, position, quaternion, skinSize) {
|
|
var l = this.lowerBound, u = this.upperBound, q = quaternion;
|
|
l.copy(points[0]);
|
|
q && q.vmult(l, l);
|
|
u.copy(l);
|
|
for (var i = 1; i < points.length; i++) {
|
|
var p = points[i];
|
|
if (q) {
|
|
q.vmult(p, tmp);
|
|
p = tmp;
|
|
}
|
|
p.x > u.x && (u.x = p.x);
|
|
p.x < l.x && (l.x = p.x);
|
|
p.y > u.y && (u.y = p.y);
|
|
p.y < l.y && (l.y = p.y);
|
|
p.z > u.z && (u.z = p.z);
|
|
p.z < l.z && (l.z = p.z);
|
|
}
|
|
if (position) {
|
|
position.vadd(l, l);
|
|
position.vadd(u, u);
|
|
}
|
|
if (skinSize) {
|
|
l.x -= skinSize;
|
|
l.y -= skinSize;
|
|
l.z -= skinSize;
|
|
u.x += skinSize;
|
|
u.y += skinSize;
|
|
u.z += skinSize;
|
|
}
|
|
return this;
|
|
};
|
|
AABB.prototype.copy = function(aabb) {
|
|
this.lowerBound.copy(aabb.lowerBound);
|
|
this.upperBound.copy(aabb.upperBound);
|
|
return this;
|
|
};
|
|
AABB.prototype.clone = function() {
|
|
return new AABB().copy(this);
|
|
};
|
|
AABB.prototype.extend = function(aabb) {
|
|
this.lowerBound.x = Math.min(this.lowerBound.x, aabb.lowerBound.x);
|
|
this.upperBound.x = Math.max(this.upperBound.x, aabb.upperBound.x);
|
|
this.lowerBound.y = Math.min(this.lowerBound.y, aabb.lowerBound.y);
|
|
this.upperBound.y = Math.max(this.upperBound.y, aabb.upperBound.y);
|
|
this.lowerBound.z = Math.min(this.lowerBound.z, aabb.lowerBound.z);
|
|
this.upperBound.z = Math.max(this.upperBound.z, aabb.upperBound.z);
|
|
};
|
|
AABB.prototype.overlaps = function(aabb) {
|
|
var l1 = this.lowerBound, u1 = this.upperBound, l2 = aabb.lowerBound, u2 = aabb.upperBound;
|
|
var overlapsX = l2.x <= u1.x && u1.x <= u2.x || l1.x <= u2.x && u2.x <= u1.x;
|
|
var overlapsY = l2.y <= u1.y && u1.y <= u2.y || l1.y <= u2.y && u2.y <= u1.y;
|
|
var overlapsZ = l2.z <= u1.z && u1.z <= u2.z || l1.z <= u2.z && u2.z <= u1.z;
|
|
return overlapsX && overlapsY && overlapsZ;
|
|
};
|
|
AABB.prototype.volume = function() {
|
|
var l = this.lowerBound, u = this.upperBound;
|
|
return (u.x - l.x) * (u.y - l.y) * (u.z - l.z);
|
|
};
|
|
AABB.prototype.contains = function(aabb) {
|
|
var l1 = this.lowerBound, u1 = this.upperBound, l2 = aabb.lowerBound, u2 = aabb.upperBound;
|
|
return l1.x <= l2.x && u1.x >= u2.x && l1.y <= l2.y && u1.y >= u2.y && l1.z <= l2.z && u1.z >= u2.z;
|
|
};
|
|
AABB.prototype.getCorners = function(a, b, c, d, e, f, g, h) {
|
|
var l = this.lowerBound, u = this.upperBound;
|
|
a.copy(l);
|
|
b.set(u.x, l.y, l.z);
|
|
c.set(u.x, u.y, l.z);
|
|
d.set(l.x, u.y, u.z);
|
|
e.set(u.x, l.y, u.z);
|
|
f.set(l.x, u.y, l.z);
|
|
g.set(l.x, l.y, u.z);
|
|
h.copy(u);
|
|
};
|
|
var transformIntoFrame_corners = [ new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3() ];
|
|
AABB.prototype.toLocalFrame = function(frame, target) {
|
|
var corners = transformIntoFrame_corners;
|
|
var a = corners[0];
|
|
var b = corners[1];
|
|
var c = corners[2];
|
|
var d = corners[3];
|
|
var e = corners[4];
|
|
var f = corners[5];
|
|
var g = corners[6];
|
|
var h = corners[7];
|
|
this.getCorners(a, b, c, d, e, f, g, h);
|
|
for (var i = 0; 8 !== i; i++) {
|
|
var corner = corners[i];
|
|
frame.pointToLocal(corner, corner);
|
|
}
|
|
return target.setFromPoints(corners);
|
|
};
|
|
AABB.prototype.toWorldFrame = function(frame, target) {
|
|
var corners = transformIntoFrame_corners;
|
|
var a = corners[0];
|
|
var b = corners[1];
|
|
var c = corners[2];
|
|
var d = corners[3];
|
|
var e = corners[4];
|
|
var f = corners[5];
|
|
var g = corners[6];
|
|
var h = corners[7];
|
|
this.getCorners(a, b, c, d, e, f, g, h);
|
|
for (var i = 0; 8 !== i; i++) {
|
|
var corner = corners[i];
|
|
frame.pointToWorld(corner, corner);
|
|
}
|
|
return target.setFromPoints(corners);
|
|
};
|
|
AABB.prototype.overlapsRay = function(ray) {
|
|
var t = 0;
|
|
var dirFracX = 1 / ray._direction.x;
|
|
var dirFracY = 1 / ray._direction.y;
|
|
var dirFracZ = 1 / ray._direction.z;
|
|
var t1 = (this.lowerBound.x - ray.from.x) * dirFracX;
|
|
var t2 = (this.upperBound.x - ray.from.x) * dirFracX;
|
|
var t3 = (this.lowerBound.y - ray.from.y) * dirFracY;
|
|
var t4 = (this.upperBound.y - ray.from.y) * dirFracY;
|
|
var t5 = (this.lowerBound.z - ray.from.z) * dirFracZ;
|
|
var t6 = (this.upperBound.z - ray.from.z) * dirFracZ;
|
|
var tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6));
|
|
var tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6));
|
|
if (tmax < 0) return false;
|
|
if (tmin > tmax) return false;
|
|
return true;
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"../utils/Utils": 55
|
|
} ],
|
|
4: [ function(_dereq_, module, exports) {
|
|
module.exports = ArrayCollisionMatrix;
|
|
function ArrayCollisionMatrix() {
|
|
this.matrix = [];
|
|
}
|
|
ArrayCollisionMatrix.prototype.get = function(i, j) {
|
|
i = i.index;
|
|
j = j.index;
|
|
if (j > i) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return this.matrix[(i * (i + 1) >> 1) + j - 1];
|
|
};
|
|
ArrayCollisionMatrix.prototype.set = function(i, j, value) {
|
|
i = i.index;
|
|
j = j.index;
|
|
if (j > i) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
this.matrix[(i * (i + 1) >> 1) + j - 1] = value ? 1 : 0;
|
|
};
|
|
ArrayCollisionMatrix.prototype.reset = function() {
|
|
for (var i = 0, l = this.matrix.length; i !== l; i++) this.matrix[i] = 0;
|
|
};
|
|
ArrayCollisionMatrix.prototype.setNumObjects = function(n) {
|
|
this.matrix.length = n * (n - 1) >> 1;
|
|
};
|
|
}, {} ],
|
|
5: [ function(_dereq_, module, exports) {
|
|
var Body = _dereq_("../objects/Body");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var Plane = _dereq_("../shapes/Plane");
|
|
module.exports = Broadphase;
|
|
function Broadphase() {
|
|
this.world = null;
|
|
this.useBoundingBoxes = false;
|
|
this.dirty = true;
|
|
}
|
|
Broadphase.prototype.collisionPairs = function(world, p1, p2) {
|
|
throw new Error("collisionPairs not implemented for this BroadPhase class!");
|
|
};
|
|
Broadphase.prototype.needBroadphaseCollision = function(bodyA, bodyB) {
|
|
if (0 === (bodyA.collisionFilterGroup & bodyB.collisionFilterMask) || 0 === (bodyB.collisionFilterGroup & bodyA.collisionFilterMask)) return false;
|
|
if (bodyA.hasTrigger || bodyB.hasTrigger) return true;
|
|
if ((0 !== (bodyA.type & Body.STATIC) || bodyA.sleepState === Body.SLEEPING) && (0 !== (bodyB.type & Body.STATIC) || bodyB.sleepState === Body.SLEEPING)) return false;
|
|
return true;
|
|
};
|
|
Broadphase.prototype.intersectionTest = function(bodyA, bodyB, pairs1, pairs2) {
|
|
this.useBoundingBoxes ? this.doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2) : this.doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2);
|
|
};
|
|
var Broadphase_collisionPairs_r = new Vec3(), Broadphase_collisionPairs_normal = new Vec3(), Broadphase_collisionPairs_quat = new Quaternion(), Broadphase_collisionPairs_relpos = new Vec3();
|
|
Broadphase.prototype.doBoundingSphereBroadphase = function(bodyA, bodyB, pairs1, pairs2) {
|
|
var r = Broadphase_collisionPairs_r;
|
|
bodyB.position.vsub(bodyA.position, r);
|
|
var boundingRadiusSum2 = Math.pow(bodyA.boundingRadius + bodyB.boundingRadius, 2);
|
|
var norm2 = r.norm2();
|
|
if (norm2 < boundingRadiusSum2) {
|
|
pairs1.push(bodyA);
|
|
pairs2.push(bodyB);
|
|
}
|
|
};
|
|
Broadphase.prototype.doBoundingBoxBroadphase = function(bodyA, bodyB, pairs1, pairs2) {
|
|
bodyA.aabbNeedsUpdate && bodyA.computeAABB();
|
|
bodyB.aabbNeedsUpdate && bodyB.computeAABB();
|
|
if (bodyA.aabb.overlaps(bodyB.aabb)) {
|
|
pairs1.push(bodyA);
|
|
pairs2.push(bodyB);
|
|
}
|
|
};
|
|
var Broadphase_makePairsUnique_temp = {
|
|
keys: []
|
|
}, Broadphase_makePairsUnique_p1 = [], Broadphase_makePairsUnique_p2 = [];
|
|
Broadphase.prototype.makePairsUnique = function(pairs1, pairs2) {
|
|
var t = Broadphase_makePairsUnique_temp, p1 = Broadphase_makePairsUnique_p1, p2 = Broadphase_makePairsUnique_p2, N = pairs1.length;
|
|
for (var i = 0; i !== N; i++) {
|
|
p1[i] = pairs1[i];
|
|
p2[i] = pairs2[i];
|
|
}
|
|
pairs1.length = 0;
|
|
pairs2.length = 0;
|
|
for (var i = 0; i !== N; i++) {
|
|
var id1 = p1[i].id, id2 = p2[i].id;
|
|
var key = id1 < id2 ? id1 + "," + id2 : id2 + "," + id1;
|
|
t[key] = i;
|
|
t.keys.push(key);
|
|
}
|
|
for (var i = 0; i !== t.keys.length; i++) {
|
|
var key = t.keys.pop(), pairIndex = t[key];
|
|
pairs1.push(p1[pairIndex]);
|
|
pairs2.push(p2[pairIndex]);
|
|
delete t[key];
|
|
}
|
|
};
|
|
Broadphase.prototype.setWorld = function(world) {};
|
|
var bsc_dist = new Vec3();
|
|
Broadphase.boundingSphereCheck = function(bodyA, bodyB) {
|
|
var dist = bsc_dist;
|
|
bodyA.position.vsub(bodyB.position, dist);
|
|
return Math.pow(bodyA.shape.boundingSphereRadius + bodyB.shape.boundingSphereRadius, 2) > dist.norm2();
|
|
};
|
|
Broadphase.prototype.aabbQuery = function(world, aabb, result) {
|
|
console.warn(".aabbQuery is not implemented in this Broadphase subclass.");
|
|
return [];
|
|
};
|
|
}, {
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../objects/Body": 33,
|
|
"../shapes/Plane": 44,
|
|
"../shapes/Shape": 45
|
|
} ],
|
|
6: [ function(_dereq_, module, exports) {
|
|
module.exports = GridBroadphase;
|
|
var Broadphase = _dereq_("./Broadphase");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
function GridBroadphase(aabbMin, aabbMax, nx, ny, nz) {
|
|
Broadphase.apply(this);
|
|
this.nx = nx || 10;
|
|
this.ny = ny || 10;
|
|
this.nz = nz || 10;
|
|
this.aabbMin = aabbMin || new Vec3(100, 100, 100);
|
|
this.aabbMax = aabbMax || new Vec3(-100, -100, -100);
|
|
var nbins = this.nx * this.ny * this.nz;
|
|
if (nbins <= 0) throw "GridBroadphase: Each dimension's n must be >0";
|
|
this.bins = [];
|
|
this.binLengths = [];
|
|
this.bins.length = nbins;
|
|
this.binLengths.length = nbins;
|
|
for (var i = 0; i < nbins; i++) {
|
|
this.bins[i] = [];
|
|
this.binLengths[i] = 0;
|
|
}
|
|
}
|
|
GridBroadphase.prototype = new Broadphase();
|
|
GridBroadphase.prototype.constructor = GridBroadphase;
|
|
var GridBroadphase_collisionPairs_d = new Vec3();
|
|
var GridBroadphase_collisionPairs_binPos = new Vec3();
|
|
GridBroadphase.prototype.collisionPairs = function(world, pairs1, pairs2) {
|
|
var N = world.numObjects(), bodies = world.bodies;
|
|
var max = this.aabbMax, min = this.aabbMin, nx = this.nx, ny = this.ny, nz = this.nz;
|
|
var xstep = ny * nz;
|
|
var ystep = nz;
|
|
var zstep = 1;
|
|
var xmax = max.x, ymax = max.y, zmax = max.z, xmin = min.x, ymin = min.y, zmin = min.z;
|
|
var xmult = nx / (xmax - xmin), ymult = ny / (ymax - ymin), zmult = nz / (zmax - zmin);
|
|
var binsizeX = (xmax - xmin) / nx, binsizeY = (ymax - ymin) / ny, binsizeZ = (zmax - zmin) / nz;
|
|
var binRadius = .5 * Math.sqrt(binsizeX * binsizeX + binsizeY * binsizeY + binsizeZ * binsizeZ);
|
|
var types = Shape.types;
|
|
var SPHERE = types.SPHERE, PLANE = types.PLANE, BOX = types.BOX, COMPOUND = types.COMPOUND, CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON;
|
|
var bins = this.bins, binLengths = this.binLengths, Nbins = this.bins.length;
|
|
for (var i = 0; i !== Nbins; i++) binLengths[i] = 0;
|
|
var ceil = Math.ceil;
|
|
var min = Math.min;
|
|
var max = Math.max;
|
|
function addBoxToBins(x0, y0, z0, x1, y1, z1, bi) {
|
|
var xoff0 = (x0 - xmin) * xmult | 0, yoff0 = (y0 - ymin) * ymult | 0, zoff0 = (z0 - zmin) * zmult | 0, xoff1 = ceil((x1 - xmin) * xmult), yoff1 = ceil((y1 - ymin) * ymult), zoff1 = ceil((z1 - zmin) * zmult);
|
|
xoff0 < 0 ? xoff0 = 0 : xoff0 >= nx && (xoff0 = nx - 1);
|
|
yoff0 < 0 ? yoff0 = 0 : yoff0 >= ny && (yoff0 = ny - 1);
|
|
zoff0 < 0 ? zoff0 = 0 : zoff0 >= nz && (zoff0 = nz - 1);
|
|
xoff1 < 0 ? xoff1 = 0 : xoff1 >= nx && (xoff1 = nx - 1);
|
|
yoff1 < 0 ? yoff1 = 0 : yoff1 >= ny && (yoff1 = ny - 1);
|
|
zoff1 < 0 ? zoff1 = 0 : zoff1 >= nz && (zoff1 = nz - 1);
|
|
xoff0 *= xstep;
|
|
yoff0 *= ystep;
|
|
zoff0 *= zstep;
|
|
xoff1 *= xstep;
|
|
yoff1 *= ystep;
|
|
zoff1 *= zstep;
|
|
for (var xoff = xoff0; xoff <= xoff1; xoff += xstep) for (var yoff = yoff0; yoff <= yoff1; yoff += ystep) for (var zoff = zoff0; zoff <= zoff1; zoff += zstep) {
|
|
var idx = xoff + yoff + zoff;
|
|
bins[idx][binLengths[idx]++] = bi;
|
|
}
|
|
}
|
|
for (var i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
var si = bi.shape;
|
|
switch (si.type) {
|
|
case SPHERE:
|
|
var x = bi.position.x, y = bi.position.y, z = bi.position.z;
|
|
var r = si.radius;
|
|
addBoxToBins(x - r, y - r, z - r, x + r, y + r, z + r, bi);
|
|
break;
|
|
|
|
case PLANE:
|
|
si.worldNormalNeedsUpdate && si.computeWorldNormal(bi.quaternion);
|
|
var planeNormal = si.worldNormal;
|
|
var xreset = xmin + .5 * binsizeX - bi.position.x, yreset = ymin + .5 * binsizeY - bi.position.y, zreset = zmin + .5 * binsizeZ - bi.position.z;
|
|
var d = GridBroadphase_collisionPairs_d;
|
|
d.set(xreset, yreset, zreset);
|
|
for (var xi = 0, xoff = 0; xi !== nx; xi++, xoff += xstep, d.y = yreset, d.x += binsizeX) for (var yi = 0, yoff = 0; yi !== ny; yi++,
|
|
yoff += ystep, d.z = zreset, d.y += binsizeY) for (var zi = 0, zoff = 0; zi !== nz; zi++,
|
|
zoff += zstep, d.z += binsizeZ) if (d.dot(planeNormal) < binRadius) {
|
|
var idx = xoff + yoff + zoff;
|
|
bins[idx][binLengths[idx]++] = bi;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bi.aabbNeedsUpdate && bi.computeAABB();
|
|
addBoxToBins(bi.aabb.lowerBound.x, bi.aabb.lowerBound.y, bi.aabb.lowerBound.z, bi.aabb.upperBound.x, bi.aabb.upperBound.y, bi.aabb.upperBound.z, bi);
|
|
}
|
|
}
|
|
for (var i = 0; i !== Nbins; i++) {
|
|
var binLength = binLengths[i];
|
|
if (binLength > 1) {
|
|
var bin = bins[i];
|
|
for (var xi = 0; xi !== binLength; xi++) {
|
|
var bi = bin[xi];
|
|
for (var yi = 0; yi !== xi; yi++) {
|
|
var bj = bin[yi];
|
|
this.needBroadphaseCollision(bi, bj) && this.intersectionTest(bi, bj, pairs1, pairs2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.makePairsUnique(pairs1, pairs2);
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"../shapes/Shape": 45,
|
|
"./Broadphase": 5
|
|
} ],
|
|
7: [ function(_dereq_, module, exports) {
|
|
module.exports = NaiveBroadphase;
|
|
var Broadphase = _dereq_("./Broadphase");
|
|
var AABB = _dereq_("./AABB");
|
|
function NaiveBroadphase() {
|
|
Broadphase.apply(this);
|
|
}
|
|
NaiveBroadphase.prototype = new Broadphase();
|
|
NaiveBroadphase.prototype.constructor = NaiveBroadphase;
|
|
NaiveBroadphase.prototype.collisionPairs = function(world, pairs1, pairs2) {
|
|
var bodies = world.bodies, n = bodies.length, i, j, bi, bj;
|
|
for (i = 0; i !== n; i++) for (j = 0; j !== i; j++) {
|
|
bi = bodies[i];
|
|
bj = bodies[j];
|
|
if (!this.needBroadphaseCollision(bi, bj)) continue;
|
|
this.intersectionTest(bi, bj, pairs1, pairs2);
|
|
}
|
|
};
|
|
var tmpAABB = new AABB();
|
|
NaiveBroadphase.prototype.aabbQuery = function(world, aabb, result) {
|
|
result = result || [];
|
|
for (var i = 0; i < world.bodies.length; i++) {
|
|
var b = world.bodies[i];
|
|
b.aabbNeedsUpdate && b.computeAABB();
|
|
b.aabb.overlaps(aabb) && result.push(b);
|
|
}
|
|
return result;
|
|
};
|
|
}, {
|
|
"./AABB": 3,
|
|
"./Broadphase": 5
|
|
} ],
|
|
8: [ function(_dereq_, module, exports) {
|
|
module.exports = ObjectCollisionMatrix;
|
|
function ObjectCollisionMatrix() {
|
|
this.matrix = {};
|
|
}
|
|
ObjectCollisionMatrix.prototype.get = function(i, j) {
|
|
i = i.id;
|
|
j = j.id;
|
|
if (j > i) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return i + "-" + j in this.matrix;
|
|
};
|
|
ObjectCollisionMatrix.prototype.set = function(i, j, value) {
|
|
i = i.id;
|
|
j = j.id;
|
|
if (j > i) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
value ? this.matrix[i + "-" + j] = true : delete this.matrix[i + "-" + j];
|
|
};
|
|
ObjectCollisionMatrix.prototype.reset = function() {
|
|
this.matrix = {};
|
|
};
|
|
ObjectCollisionMatrix.prototype.setNumObjects = function(n) {};
|
|
}, {} ],
|
|
9: [ function(_dereq_, module, exports) {
|
|
module.exports = OverlapKeeper;
|
|
function OverlapKeeper() {
|
|
this.current = [];
|
|
this.previous = [];
|
|
}
|
|
OverlapKeeper.prototype.getKey = function(i, j) {
|
|
if (j < i) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return i << 16 | j;
|
|
};
|
|
OverlapKeeper.prototype.set = function(i, j) {
|
|
var key = this.getKey(i, j);
|
|
var current = this.current;
|
|
var index = 0;
|
|
while (key > current[index]) index++;
|
|
if (key === current[index]) return;
|
|
for (var j = current.length - 1; j >= index; j--) current[j + 1] = current[j];
|
|
current[index] = key;
|
|
};
|
|
OverlapKeeper.prototype.tick = function() {
|
|
var tmp = this.current;
|
|
this.current = this.previous;
|
|
this.previous = tmp;
|
|
this.current.length = 0;
|
|
};
|
|
function unpackAndPush(array, key) {
|
|
array.push((4294901760 & key) >> 16, 65535 & key);
|
|
}
|
|
OverlapKeeper.prototype.getDiff = function(additions, removals) {
|
|
var a = this.current;
|
|
var b = this.previous;
|
|
var al = a.length;
|
|
var bl = b.length;
|
|
var j = 0;
|
|
for (var i = 0; i < al; i++) {
|
|
var found = false;
|
|
var keyA = a[i];
|
|
while (keyA > b[j]) j++;
|
|
found = keyA === b[j];
|
|
found || unpackAndPush(additions, keyA);
|
|
}
|
|
j = 0;
|
|
for (var i = 0; i < bl; i++) {
|
|
var found = false;
|
|
var keyB = b[i];
|
|
while (keyB > a[j]) j++;
|
|
found = a[j] === keyB;
|
|
found || unpackAndPush(removals, keyB);
|
|
}
|
|
};
|
|
}, {} ],
|
|
10: [ function(_dereq_, module, exports) {
|
|
module.exports = Ray;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Transform = _dereq_("../math/Transform");
|
|
var ConvexPolyhedron = _dereq_("../shapes/ConvexPolyhedron");
|
|
var Box = _dereq_("../shapes/Box");
|
|
var RaycastResult = _dereq_("../collision/RaycastResult");
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var AABB = _dereq_("../collision/AABB");
|
|
function Ray(from, to) {
|
|
this.from = from ? from.clone() : new Vec3();
|
|
this.to = to ? to.clone() : new Vec3();
|
|
this._direction = new Vec3();
|
|
this.precision = 1e-4;
|
|
this.checkCollisionResponse = true;
|
|
this.skipBackfaces = false;
|
|
this.collisionFilterMask = -1;
|
|
this.collisionFilterGroup = -1;
|
|
this.mode = Ray.ANY;
|
|
this.result = new RaycastResult();
|
|
this.hasHit = false;
|
|
this.callback = function(result) {};
|
|
}
|
|
Ray.prototype.constructor = Ray;
|
|
Ray.CLOSEST = 1;
|
|
Ray.ANY = 2;
|
|
Ray.ALL = 4;
|
|
var tmpAABB = new AABB();
|
|
var tmpArray = [];
|
|
Ray.prototype.intersectWorld = function(world, options) {
|
|
this.mode = options.mode || Ray.ANY;
|
|
this.result = options.result || new RaycastResult();
|
|
this.skipBackfaces = !!options.skipBackfaces;
|
|
this.checkCollisionResponse = !!options.checkCollisionResponse;
|
|
this.collisionFilterMask = "undefined" !== typeof options.collisionFilterMask ? options.collisionFilterMask : -1;
|
|
this.collisionFilterGroup = "undefined" !== typeof options.collisionFilterGroup ? options.collisionFilterGroup : -1;
|
|
options.from && this.from.copy(options.from);
|
|
options.to && this.to.copy(options.to);
|
|
this.callback = options.callback || function() {};
|
|
this.hasHit = false;
|
|
this.result.reset();
|
|
this._updateDirection();
|
|
this.getAABB(tmpAABB);
|
|
tmpArray.length = 0;
|
|
world.broadphase.aabbQuery(world, tmpAABB, tmpArray);
|
|
this.intersectBodies(tmpArray);
|
|
return this.hasHit;
|
|
};
|
|
var v1 = new Vec3(), v2 = new Vec3();
|
|
Ray.pointInTriangle = pointInTriangle;
|
|
function pointInTriangle(p, a, b, c) {
|
|
c.vsub(a, v0);
|
|
b.vsub(a, v1);
|
|
p.vsub(a, v2);
|
|
var dot00 = v0.dot(v0);
|
|
var dot01 = v0.dot(v1);
|
|
var dot02 = v0.dot(v2);
|
|
var dot11 = v1.dot(v1);
|
|
var dot12 = v1.dot(v2);
|
|
var u, v;
|
|
return (u = dot11 * dot02 - dot01 * dot12) >= 0 && (v = dot00 * dot12 - dot01 * dot02) >= 0 && u + v < dot00 * dot11 - dot01 * dot01;
|
|
}
|
|
var intersectBody_xi = new Vec3();
|
|
var intersectBody_qi = new Quaternion();
|
|
Ray.prototype.intersectBody = function(body, result) {
|
|
if (result) {
|
|
this.result = result;
|
|
this._updateDirection();
|
|
}
|
|
var checkCollisionResponse = this.checkCollisionResponse;
|
|
if (checkCollisionResponse && !body.collisionResponse) return;
|
|
if (0 === (this.collisionFilterGroup & body.collisionFilterMask) || 0 === (body.collisionFilterGroup & this.collisionFilterMask)) return;
|
|
var xi = intersectBody_xi;
|
|
var qi = intersectBody_qi;
|
|
for (var i = 0, N = body.shapes.length; i < N; i++) {
|
|
var shape = body.shapes[i];
|
|
if (checkCollisionResponse && !shape.collisionResponse) continue;
|
|
body.quaternion.mult(body.shapeOrientations[i], qi);
|
|
body.quaternion.vmult(body.shapeOffsets[i], xi);
|
|
xi.vadd(body.position, xi);
|
|
this.intersectShape(shape, qi, xi, body);
|
|
if (this.result._shouldStop) break;
|
|
}
|
|
};
|
|
Ray.prototype.intersectBodies = function(bodies, result) {
|
|
if (result) {
|
|
this.result = result;
|
|
this._updateDirection();
|
|
}
|
|
for (var i = 0, l = bodies.length; !this.result._shouldStop && i < l; i++) this.intersectBody(bodies[i]);
|
|
};
|
|
Ray.prototype._updateDirection = function() {
|
|
this.to.vsub(this.from, this._direction);
|
|
this._direction.normalize();
|
|
};
|
|
Ray.prototype.intersectShape = function(shape, quat, position, body) {
|
|
var from = this.from;
|
|
var distance = distanceFromIntersection(from, this._direction, position);
|
|
if (distance > shape.boundingSphereRadius) return;
|
|
var intersectMethod = this[shape.type];
|
|
intersectMethod && intersectMethod.call(this, shape, quat, position, body, shape);
|
|
};
|
|
var vector = new Vec3();
|
|
var normal = new Vec3();
|
|
var intersectPoint = new Vec3();
|
|
var a = new Vec3();
|
|
var b = new Vec3();
|
|
var c = new Vec3();
|
|
var d = new Vec3();
|
|
var tmpRaycastResult = new RaycastResult();
|
|
Ray.prototype.intersectBox = function(shape, quat, position, body, reportedShape) {
|
|
return this.intersectConvex(shape.convexPolyhedronRepresentation, quat, position, body, reportedShape);
|
|
};
|
|
Ray.prototype[Shape.types.BOX] = Ray.prototype.intersectBox;
|
|
Ray.prototype.intersectPlane = function(shape, quat, position, body, reportedShape) {
|
|
var from = this.from;
|
|
var to = this.to;
|
|
var direction = this._direction;
|
|
var worldNormal = new Vec3(0, 0, 1);
|
|
quat.vmult(worldNormal, worldNormal);
|
|
var len = new Vec3();
|
|
from.vsub(position, len);
|
|
var planeToFrom = len.dot(worldNormal);
|
|
to.vsub(position, len);
|
|
var planeToTo = len.dot(worldNormal);
|
|
if (planeToFrom * planeToTo > 0) return;
|
|
if (from.distanceTo(to) < planeToFrom) return;
|
|
var n_dot_dir = worldNormal.dot(direction);
|
|
if (Math.abs(n_dot_dir) < this.precision) return;
|
|
var planePointToFrom = new Vec3();
|
|
var dir_scaled_with_t = new Vec3();
|
|
var hitPointWorld = new Vec3();
|
|
from.vsub(position, planePointToFrom);
|
|
var t = -worldNormal.dot(planePointToFrom) / n_dot_dir;
|
|
direction.scale(t, dir_scaled_with_t);
|
|
from.vadd(dir_scaled_with_t, hitPointWorld);
|
|
this.reportIntersection(worldNormal, hitPointWorld, reportedShape, body, -1);
|
|
};
|
|
Ray.prototype[Shape.types.PLANE] = Ray.prototype.intersectPlane;
|
|
Ray.prototype.getAABB = function(result) {
|
|
var to = this.to;
|
|
var from = this.from;
|
|
result.lowerBound.x = Math.min(to.x, from.x);
|
|
result.lowerBound.y = Math.min(to.y, from.y);
|
|
result.lowerBound.z = Math.min(to.z, from.z);
|
|
result.upperBound.x = Math.max(to.x, from.x);
|
|
result.upperBound.y = Math.max(to.y, from.y);
|
|
result.upperBound.z = Math.max(to.z, from.z);
|
|
};
|
|
var intersectConvexOptions = {
|
|
faceList: [ 0 ]
|
|
};
|
|
var worldPillarOffset = new Vec3();
|
|
var intersectHeightfield_localRay = new Ray();
|
|
var intersectHeightfield_index = [];
|
|
var intersectHeightfield_minMax = [];
|
|
Ray.prototype.intersectHeightfield = function(shape, quat, position, body, reportedShape) {
|
|
var data = shape.data, w = shape.elementSize;
|
|
var localRay = intersectHeightfield_localRay;
|
|
localRay.from.copy(this.from);
|
|
localRay.to.copy(this.to);
|
|
Transform.pointToLocalFrame(position, quat, localRay.from, localRay.from);
|
|
Transform.pointToLocalFrame(position, quat, localRay.to, localRay.to);
|
|
localRay._updateDirection();
|
|
var index = intersectHeightfield_index;
|
|
var iMinX, iMinY, iMaxX, iMaxY;
|
|
iMinX = iMinY = 0;
|
|
iMaxX = iMaxY = shape.data.length - 1;
|
|
var aabb = new AABB();
|
|
localRay.getAABB(aabb);
|
|
shape.getIndexOfPosition(aabb.lowerBound.x, aabb.lowerBound.y, index, true);
|
|
iMinX = Math.max(iMinX, index[0]);
|
|
iMinY = Math.max(iMinY, index[1]);
|
|
shape.getIndexOfPosition(aabb.upperBound.x, aabb.upperBound.y, index, true);
|
|
iMaxX = Math.min(iMaxX, index[0] + 1);
|
|
iMaxY = Math.min(iMaxY, index[1] + 1);
|
|
for (var i = iMinX; i < iMaxX; i++) for (var j = iMinY; j < iMaxY; j++) {
|
|
if (this.result._shouldStop) return;
|
|
shape.getAabbAtIndex(i, j, aabb);
|
|
if (!aabb.overlapsRay(localRay)) continue;
|
|
shape.getConvexTrianglePillar(i, j, false);
|
|
Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
|
|
this.intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, reportedShape, intersectConvexOptions);
|
|
if (this.result._shouldStop) return;
|
|
shape.getConvexTrianglePillar(i, j, true);
|
|
Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
|
|
this.intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, reportedShape, intersectConvexOptions);
|
|
}
|
|
};
|
|
Ray.prototype[Shape.types.HEIGHTFIELD] = Ray.prototype.intersectHeightfield;
|
|
var Ray_intersectSphere_intersectionPoint = new Vec3();
|
|
var Ray_intersectSphere_normal = new Vec3();
|
|
Ray.prototype.intersectSphere = function(shape, quat, position, body, reportedShape) {
|
|
var from = this.from, to = this.to, r = shape.radius;
|
|
var a = Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2) + Math.pow(to.z - from.z, 2);
|
|
var b = 2 * ((to.x - from.x) * (from.x - position.x) + (to.y - from.y) * (from.y - position.y) + (to.z - from.z) * (from.z - position.z));
|
|
var c = Math.pow(from.x - position.x, 2) + Math.pow(from.y - position.y, 2) + Math.pow(from.z - position.z, 2) - Math.pow(r, 2);
|
|
var delta = Math.pow(b, 2) - 4 * a * c;
|
|
var intersectionPoint = Ray_intersectSphere_intersectionPoint;
|
|
var normal = Ray_intersectSphere_normal;
|
|
if (delta < 0) return;
|
|
if (0 === delta) {
|
|
from.lerp(to, delta, intersectionPoint);
|
|
intersectionPoint.vsub(position, normal);
|
|
normal.normalize();
|
|
this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1);
|
|
} else {
|
|
var d1 = (-b - Math.sqrt(delta)) / (2 * a);
|
|
var d2 = (-b + Math.sqrt(delta)) / (2 * a);
|
|
if (d1 >= 0 && d1 <= 1) {
|
|
from.lerp(to, d1, intersectionPoint);
|
|
intersectionPoint.vsub(position, normal);
|
|
normal.normalize();
|
|
this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1);
|
|
}
|
|
if (this.result._shouldStop) return;
|
|
if (d2 >= 0 && d2 <= 1) {
|
|
from.lerp(to, d2, intersectionPoint);
|
|
intersectionPoint.vsub(position, normal);
|
|
normal.normalize();
|
|
this.reportIntersection(normal, intersectionPoint, reportedShape, body, -1);
|
|
}
|
|
}
|
|
};
|
|
Ray.prototype[Shape.types.SPHERE] = Ray.prototype.intersectSphere;
|
|
var intersectConvex_normal = new Vec3();
|
|
var intersectConvex_minDistNormal = new Vec3();
|
|
var intersectConvex_minDistIntersect = new Vec3();
|
|
var intersectConvex_vector = new Vec3();
|
|
Ray.prototype.intersectConvex = function intersectConvex(shape, quat, position, body, reportedShape, options) {
|
|
var minDistNormal = intersectConvex_minDistNormal;
|
|
var normal = intersectConvex_normal;
|
|
var vector = intersectConvex_vector;
|
|
var minDistIntersect = intersectConvex_minDistIntersect;
|
|
var faceList = options && options.faceList || null;
|
|
var faces = shape.faces, vertices = shape.vertices, normals = shape.faceNormals;
|
|
var direction = this._direction;
|
|
var from = this.from;
|
|
var to = this.to;
|
|
var fromToDistance = from.distanceTo(to);
|
|
var minDist = -1;
|
|
var Nfaces = faceList ? faceList.length : faces.length;
|
|
var result = this.result;
|
|
for (var j = 0; !result._shouldStop && j < Nfaces; j++) {
|
|
var fi = faceList ? faceList[j] : j;
|
|
var face = faces[fi];
|
|
var faceNormal = normals[fi];
|
|
var q = quat;
|
|
var x = position;
|
|
vector.copy(vertices[face[0]]);
|
|
q.vmult(vector, vector);
|
|
vector.vadd(x, vector);
|
|
vector.vsub(from, vector);
|
|
q.vmult(faceNormal, normal);
|
|
var dot = direction.dot(normal);
|
|
if (Math.abs(dot) < this.precision) continue;
|
|
var scalar = normal.dot(vector) / dot;
|
|
if (scalar < 0) continue;
|
|
direction.mult(scalar, intersectPoint);
|
|
intersectPoint.vadd(from, intersectPoint);
|
|
a.copy(vertices[face[0]]);
|
|
q.vmult(a, a);
|
|
x.vadd(a, a);
|
|
for (var i = 1; !result._shouldStop && i < face.length - 1; i++) {
|
|
b.copy(vertices[face[i]]);
|
|
c.copy(vertices[face[i + 1]]);
|
|
q.vmult(b, b);
|
|
q.vmult(c, c);
|
|
x.vadd(b, b);
|
|
x.vadd(c, c);
|
|
var distance = intersectPoint.distanceTo(from);
|
|
if (!(pointInTriangle(intersectPoint, a, b, c) || pointInTriangle(intersectPoint, b, a, c)) || distance > fromToDistance) continue;
|
|
this.reportIntersection(normal, intersectPoint, reportedShape, body, fi);
|
|
}
|
|
}
|
|
};
|
|
Ray.prototype[Shape.types.CONVEXPOLYHEDRON] = Ray.prototype.intersectConvex;
|
|
var intersectTrimesh_normal = new Vec3();
|
|
var intersectTrimesh_localDirection = new Vec3();
|
|
var intersectTrimesh_localFrom = new Vec3();
|
|
var intersectTrimesh_localTo = new Vec3();
|
|
var intersectTrimesh_worldNormal = new Vec3();
|
|
var intersectTrimesh_worldIntersectPoint = new Vec3();
|
|
var intersectTrimesh_localAABB = new AABB();
|
|
var intersectTrimesh_triangles = [];
|
|
var intersectTrimesh_treeTransform = new Transform();
|
|
Ray.prototype.intersectTrimesh = function intersectTrimesh(mesh, quat, position, body, reportedShape, options) {
|
|
var normal = intersectTrimesh_normal;
|
|
var triangles = intersectTrimesh_triangles;
|
|
var treeTransform = intersectTrimesh_treeTransform;
|
|
var minDistNormal = intersectConvex_minDistNormal;
|
|
var vector = intersectConvex_vector;
|
|
var minDistIntersect = intersectConvex_minDistIntersect;
|
|
var localAABB = intersectTrimesh_localAABB;
|
|
var localDirection = intersectTrimesh_localDirection;
|
|
var localFrom = intersectTrimesh_localFrom;
|
|
var localTo = intersectTrimesh_localTo;
|
|
var worldIntersectPoint = intersectTrimesh_worldIntersectPoint;
|
|
var worldNormal = intersectTrimesh_worldNormal;
|
|
var faceList = options && options.faceList || null;
|
|
var indices = mesh.indices, vertices = mesh.vertices, normals = mesh.faceNormals;
|
|
var from = this.from;
|
|
var to = this.to;
|
|
var direction = this._direction;
|
|
var minDist = -1;
|
|
treeTransform.position.copy(position);
|
|
treeTransform.quaternion.copy(quat);
|
|
Transform.vectorToLocalFrame(position, quat, direction, localDirection);
|
|
Transform.pointToLocalFrame(position, quat, from, localFrom);
|
|
Transform.pointToLocalFrame(position, quat, to, localTo);
|
|
localTo.x *= mesh.scale.x;
|
|
localTo.y *= mesh.scale.y;
|
|
localTo.z *= mesh.scale.z;
|
|
localFrom.x *= mesh.scale.x;
|
|
localFrom.y *= mesh.scale.y;
|
|
localFrom.z *= mesh.scale.z;
|
|
localTo.vsub(localFrom, localDirection);
|
|
localDirection.normalize();
|
|
var fromToDistanceSquared = localFrom.distanceSquared(localTo);
|
|
mesh.tree.rayQuery(this, treeTransform, triangles);
|
|
for (var i = 0, N = triangles.length; !this.result._shouldStop && i !== N; i++) {
|
|
var trianglesIndex = triangles[i];
|
|
mesh.getNormal(trianglesIndex, normal);
|
|
mesh.getVertex(indices[3 * trianglesIndex], a);
|
|
a.vsub(localFrom, vector);
|
|
var dot = localDirection.dot(normal);
|
|
var scalar = normal.dot(vector) / dot;
|
|
if (scalar < 0) continue;
|
|
localDirection.scale(scalar, intersectPoint);
|
|
intersectPoint.vadd(localFrom, intersectPoint);
|
|
mesh.getVertex(indices[3 * trianglesIndex + 1], b);
|
|
mesh.getVertex(indices[3 * trianglesIndex + 2], c);
|
|
var squaredDistance = intersectPoint.distanceSquared(localFrom);
|
|
if (!(pointInTriangle(intersectPoint, b, a, c) || pointInTriangle(intersectPoint, a, b, c)) || squaredDistance > fromToDistanceSquared) continue;
|
|
Transform.vectorToWorldFrame(quat, normal, worldNormal);
|
|
Transform.pointToWorldFrame(position, quat, intersectPoint, worldIntersectPoint);
|
|
this.reportIntersection(worldNormal, worldIntersectPoint, reportedShape, body, trianglesIndex);
|
|
}
|
|
triangles.length = 0;
|
|
};
|
|
Ray.prototype[Shape.types.TRIMESH] = Ray.prototype.intersectTrimesh;
|
|
Ray.prototype.reportIntersection = function(normal, hitPointWorld, shape, body, hitFaceIndex) {
|
|
var from = this.from;
|
|
var to = this.to;
|
|
var distance = from.distanceTo(hitPointWorld);
|
|
var result = this.result;
|
|
if (this.skipBackfaces && normal.dot(this._direction) > 0) return;
|
|
result.hitFaceIndex = "undefined" !== typeof hitFaceIndex ? hitFaceIndex : -1;
|
|
switch (this.mode) {
|
|
case Ray.ALL:
|
|
this.hasHit = true;
|
|
result.set(from, to, normal, hitPointWorld, shape, body, distance);
|
|
result.hasHit = true;
|
|
this.callback(result);
|
|
break;
|
|
|
|
case Ray.CLOSEST:
|
|
if (distance < result.distance || !result.hasHit) {
|
|
this.hasHit = true;
|
|
result.hasHit = true;
|
|
result.set(from, to, normal, hitPointWorld, shape, body, distance);
|
|
}
|
|
break;
|
|
|
|
case Ray.ANY:
|
|
this.hasHit = true;
|
|
result.hasHit = true;
|
|
result.set(from, to, normal, hitPointWorld, shape, body, distance);
|
|
result._shouldStop = true;
|
|
}
|
|
};
|
|
var v0 = new Vec3(), intersect = new Vec3();
|
|
function distanceFromIntersection(from, direction, position) {
|
|
position.vsub(from, v0);
|
|
var dot = v0.dot(direction);
|
|
direction.mult(dot, intersect);
|
|
intersect.vadd(from, intersect);
|
|
var distance = position.distanceTo(intersect);
|
|
return distance;
|
|
}
|
|
}, {
|
|
"../collision/AABB": 3,
|
|
"../collision/RaycastResult": 11,
|
|
"../math/Quaternion": 30,
|
|
"../math/Transform": 31,
|
|
"../math/Vec3": 32,
|
|
"../shapes/Box": 39,
|
|
"../shapes/ConvexPolyhedron": 40,
|
|
"../shapes/Shape": 45
|
|
} ],
|
|
11: [ function(_dereq_, module, exports) {
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
module.exports = RaycastResult;
|
|
function RaycastResult() {
|
|
this.rayFromWorld = new Vec3();
|
|
this.rayToWorld = new Vec3();
|
|
this.hitNormalWorld = new Vec3();
|
|
this.hitPointWorld = new Vec3();
|
|
this.hasHit = false;
|
|
this.shape = null;
|
|
this.body = null;
|
|
this.hitFaceIndex = -1;
|
|
this.distance = -1;
|
|
this._shouldStop = false;
|
|
}
|
|
RaycastResult.prototype.reset = function() {
|
|
this.rayFromWorld.setZero();
|
|
this.rayToWorld.setZero();
|
|
this.hitNormalWorld.setZero();
|
|
this.hitPointWorld.setZero();
|
|
this.hasHit = false;
|
|
this.shape = null;
|
|
this.body = null;
|
|
this.hitFaceIndex = -1;
|
|
this.distance = -1;
|
|
this._shouldStop = false;
|
|
};
|
|
RaycastResult.prototype.abort = function() {
|
|
this._shouldStop = true;
|
|
};
|
|
RaycastResult.prototype.set = function(rayFromWorld, rayToWorld, hitNormalWorld, hitPointWorld, shape, body, distance) {
|
|
this.rayFromWorld.copy(rayFromWorld);
|
|
this.rayToWorld.copy(rayToWorld);
|
|
this.hitNormalWorld.copy(hitNormalWorld);
|
|
this.hitPointWorld.copy(hitPointWorld);
|
|
this.shape = shape;
|
|
this.body = body;
|
|
this.distance = distance;
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32
|
|
} ],
|
|
12: [ function(_dereq_, module, exports) {
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var Broadphase = _dereq_("../collision/Broadphase");
|
|
module.exports = SAPBroadphase;
|
|
function SAPBroadphase(world) {
|
|
Broadphase.apply(this);
|
|
this.axisList = [];
|
|
this.world = null;
|
|
this.axisIndex = 0;
|
|
var axisList = this.axisList;
|
|
this._addBodyHandler = function(e) {
|
|
axisList.push(e.body);
|
|
};
|
|
this._removeBodyHandler = function(e) {
|
|
var idx = axisList.indexOf(e.body);
|
|
-1 !== idx && axisList.splice(idx, 1);
|
|
};
|
|
world && this.setWorld(world);
|
|
}
|
|
SAPBroadphase.prototype = new Broadphase();
|
|
SAPBroadphase.prototype.setWorld = function(world) {
|
|
this.axisList.length = 0;
|
|
for (var i = 0; i < world.bodies.length; i++) this.axisList.push(world.bodies[i]);
|
|
world.removeEventListener("addBody", this._addBodyHandler);
|
|
world.removeEventListener("removeBody", this._removeBodyHandler);
|
|
world.addEventListener("addBody", this._addBodyHandler);
|
|
world.addEventListener("removeBody", this._removeBodyHandler);
|
|
this.world = world;
|
|
this.dirty = true;
|
|
};
|
|
SAPBroadphase.insertionSortX = function(a) {
|
|
for (var i = 1, l = a.length; i < l; i++) {
|
|
var v = a[i];
|
|
for (var j = i - 1; j >= 0; j--) {
|
|
if (a[j].aabb.lowerBound.x <= v.aabb.lowerBound.x) break;
|
|
a[j + 1] = a[j];
|
|
}
|
|
a[j + 1] = v;
|
|
}
|
|
return a;
|
|
};
|
|
SAPBroadphase.insertionSortY = function(a) {
|
|
for (var i = 1, l = a.length; i < l; i++) {
|
|
var v = a[i];
|
|
for (var j = i - 1; j >= 0; j--) {
|
|
if (a[j].aabb.lowerBound.y <= v.aabb.lowerBound.y) break;
|
|
a[j + 1] = a[j];
|
|
}
|
|
a[j + 1] = v;
|
|
}
|
|
return a;
|
|
};
|
|
SAPBroadphase.insertionSortZ = function(a) {
|
|
for (var i = 1, l = a.length; i < l; i++) {
|
|
var v = a[i];
|
|
for (var j = i - 1; j >= 0; j--) {
|
|
if (a[j].aabb.lowerBound.z <= v.aabb.lowerBound.z) break;
|
|
a[j + 1] = a[j];
|
|
}
|
|
a[j + 1] = v;
|
|
}
|
|
return a;
|
|
};
|
|
SAPBroadphase.prototype.collisionPairs = function(world, p1, p2) {
|
|
var bodies = this.axisList, N = bodies.length, axisIndex = this.axisIndex, i, j;
|
|
if (this.dirty) {
|
|
this.sortList();
|
|
this.dirty = false;
|
|
}
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
for (j = i + 1; j < N; j++) {
|
|
var bj = bodies[j];
|
|
if (!this.needBroadphaseCollision(bi, bj)) continue;
|
|
if (!SAPBroadphase.checkBounds(bi, bj, axisIndex)) break;
|
|
this.intersectionTest(bi, bj, p1, p2);
|
|
}
|
|
}
|
|
};
|
|
SAPBroadphase.prototype.sortList = function() {
|
|
var axisList = this.axisList;
|
|
var axisIndex = this.axisIndex;
|
|
var N = axisList.length;
|
|
for (var i = 0; i !== N; i++) {
|
|
var bi = axisList[i];
|
|
bi.aabbNeedsUpdate && bi.computeAABB();
|
|
}
|
|
0 === axisIndex ? SAPBroadphase.insertionSortX(axisList) : 1 === axisIndex ? SAPBroadphase.insertionSortY(axisList) : 2 === axisIndex && SAPBroadphase.insertionSortZ(axisList);
|
|
};
|
|
SAPBroadphase.checkBounds = function(bi, bj, axisIndex) {
|
|
var biPos;
|
|
var bjPos;
|
|
if (0 === axisIndex) {
|
|
biPos = bi.position.x;
|
|
bjPos = bj.position.x;
|
|
} else if (1 === axisIndex) {
|
|
biPos = bi.position.y;
|
|
bjPos = bj.position.y;
|
|
} else if (2 === axisIndex) {
|
|
biPos = bi.position.z;
|
|
bjPos = bj.position.z;
|
|
}
|
|
var ri = bi.boundingRadius, rj = bj.boundingRadius, boundA1 = biPos - ri, boundA2 = biPos + ri, boundB1 = bjPos - rj, boundB2 = bjPos + rj;
|
|
return boundB1 < boundA2;
|
|
};
|
|
SAPBroadphase.prototype.autoDetectAxis = function() {
|
|
var sumX = 0, sumX2 = 0, sumY = 0, sumY2 = 0, sumZ = 0, sumZ2 = 0, bodies = this.axisList, N = bodies.length, invN = 1 / N;
|
|
for (var i = 0; i !== N; i++) {
|
|
var b = bodies[i];
|
|
var centerX = b.position.x;
|
|
sumX += centerX;
|
|
sumX2 += centerX * centerX;
|
|
var centerY = b.position.y;
|
|
sumY += centerY;
|
|
sumY2 += centerY * centerY;
|
|
var centerZ = b.position.z;
|
|
sumZ += centerZ;
|
|
sumZ2 += centerZ * centerZ;
|
|
}
|
|
var varianceX = sumX2 - sumX * sumX * invN, varianceY = sumY2 - sumY * sumY * invN, varianceZ = sumZ2 - sumZ * sumZ * invN;
|
|
this.axisIndex = varianceX > varianceY ? varianceX > varianceZ ? 0 : 2 : varianceY > varianceZ ? 1 : 2;
|
|
};
|
|
SAPBroadphase.prototype.aabbQuery = function(world, aabb, result) {
|
|
result = result || [];
|
|
if (this.dirty) {
|
|
this.sortList();
|
|
this.dirty = false;
|
|
}
|
|
var axisIndex = this.axisIndex, axis = "x";
|
|
1 === axisIndex && (axis = "y");
|
|
2 === axisIndex && (axis = "z");
|
|
var axisList = this.axisList;
|
|
var lower = aabb.lowerBound[axis];
|
|
var upper = aabb.upperBound[axis];
|
|
for (var i = 0; i < axisList.length; i++) {
|
|
var b = axisList[i];
|
|
b.aabbNeedsUpdate && b.computeAABB();
|
|
b.aabb.overlaps(aabb) && result.push(b);
|
|
}
|
|
return result;
|
|
};
|
|
}, {
|
|
"../collision/Broadphase": 5,
|
|
"../shapes/Shape": 45
|
|
} ],
|
|
13: [ function(_dereq_, module, exports) {
|
|
module.exports = ConeTwistConstraint;
|
|
var Constraint = _dereq_("./Constraint");
|
|
var PointToPointConstraint = _dereq_("./PointToPointConstraint");
|
|
var ConeEquation = _dereq_("../equations/ConeEquation");
|
|
var RotationalEquation = _dereq_("../equations/RotationalEquation");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function ConeTwistConstraint(bodyA, bodyB, options) {
|
|
options = options || {};
|
|
var maxForce = "undefined" !== typeof options.maxForce ? options.maxForce : 1e6;
|
|
var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
|
|
var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
|
|
this.axisA = options.axisA ? options.axisA.clone() : new Vec3();
|
|
this.axisB = options.axisB ? options.axisB.clone() : new Vec3();
|
|
PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
|
|
this.collideConnected = !!options.collideConnected;
|
|
this.angle = "undefined" !== typeof options.angle ? options.angle : 0;
|
|
var c = this.coneEquation = new ConeEquation(bodyA, bodyB, options);
|
|
var t = this.twistEquation = new RotationalEquation(bodyA, bodyB, options);
|
|
this.twistAngle = "undefined" !== typeof options.twistAngle ? options.twistAngle : 0;
|
|
c.maxForce = 0;
|
|
c.minForce = -maxForce;
|
|
t.maxForce = 0;
|
|
t.minForce = -maxForce;
|
|
this.equations.push(c, t);
|
|
}
|
|
ConeTwistConstraint.prototype = new PointToPointConstraint();
|
|
ConeTwistConstraint.constructor = ConeTwistConstraint;
|
|
var ConeTwistConstraint_update_tmpVec1 = new Vec3();
|
|
var ConeTwistConstraint_update_tmpVec2 = new Vec3();
|
|
ConeTwistConstraint.prototype.update = function() {
|
|
var bodyA = this.bodyA, bodyB = this.bodyB, cone = this.coneEquation, twist = this.twistEquation;
|
|
PointToPointConstraint.prototype.update.call(this);
|
|
bodyA.vectorToWorldFrame(this.axisA, cone.axisA);
|
|
bodyB.vectorToWorldFrame(this.axisB, cone.axisB);
|
|
this.axisA.tangents(twist.axisA, twist.axisA);
|
|
bodyA.vectorToWorldFrame(twist.axisA, twist.axisA);
|
|
this.axisB.tangents(twist.axisB, twist.axisB);
|
|
bodyB.vectorToWorldFrame(twist.axisB, twist.axisB);
|
|
cone.angle = this.angle;
|
|
twist.maxAngle = this.twistAngle;
|
|
};
|
|
}, {
|
|
"../equations/ConeEquation": 19,
|
|
"../equations/ContactEquation": 20,
|
|
"../equations/RotationalEquation": 23,
|
|
"../math/Vec3": 32,
|
|
"./Constraint": 14,
|
|
"./PointToPointConstraint": 18
|
|
} ],
|
|
14: [ function(_dereq_, module, exports) {
|
|
module.exports = Constraint;
|
|
var Utils = _dereq_("../utils/Utils");
|
|
function Constraint(bodyA, bodyB, options) {
|
|
options = Utils.defaults(options, {
|
|
collideConnected: true,
|
|
wakeUpBodies: true
|
|
});
|
|
this.equations = [];
|
|
this.bodyA = bodyA;
|
|
this.bodyB = bodyB;
|
|
this.id = Constraint.idCounter++;
|
|
this.collideConnected = options.collideConnected;
|
|
if (options.wakeUpBodies) {
|
|
bodyA && bodyA.wakeUp();
|
|
bodyB && bodyB.wakeUp();
|
|
}
|
|
}
|
|
Constraint.prototype.update = function() {
|
|
throw new Error("method update() not implmemented in this Constraint subclass!");
|
|
};
|
|
Constraint.prototype.enable = function() {
|
|
var eqs = this.equations;
|
|
for (var i = 0; i < eqs.length; i++) eqs[i].enabled = true;
|
|
};
|
|
Constraint.prototype.disable = function() {
|
|
var eqs = this.equations;
|
|
for (var i = 0; i < eqs.length; i++) eqs[i].enabled = false;
|
|
};
|
|
Constraint.idCounter = 0;
|
|
}, {
|
|
"../utils/Utils": 55
|
|
} ],
|
|
15: [ function(_dereq_, module, exports) {
|
|
module.exports = DistanceConstraint;
|
|
var Constraint = _dereq_("./Constraint");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
function DistanceConstraint(bodyA, bodyB, distance, maxForce) {
|
|
Constraint.call(this, bodyA, bodyB);
|
|
"undefined" === typeof distance && (distance = bodyA.position.distanceTo(bodyB.position));
|
|
"undefined" === typeof maxForce && (maxForce = 1e6);
|
|
this.distance = distance;
|
|
var eq = this.distanceEquation = new ContactEquation(bodyA, bodyB);
|
|
this.equations.push(eq);
|
|
eq.minForce = -maxForce;
|
|
eq.maxForce = maxForce;
|
|
}
|
|
DistanceConstraint.prototype = new Constraint();
|
|
DistanceConstraint.prototype.update = function() {
|
|
var bodyA = this.bodyA;
|
|
var bodyB = this.bodyB;
|
|
var eq = this.distanceEquation;
|
|
var halfDist = .5 * this.distance;
|
|
var normal = eq.ni;
|
|
bodyB.position.vsub(bodyA.position, normal);
|
|
normal.normalize();
|
|
normal.mult(halfDist, eq.ri);
|
|
normal.mult(-halfDist, eq.rj);
|
|
};
|
|
}, {
|
|
"../equations/ContactEquation": 20,
|
|
"./Constraint": 14
|
|
} ],
|
|
16: [ function(_dereq_, module, exports) {
|
|
module.exports = HingeConstraint;
|
|
var Constraint = _dereq_("./Constraint");
|
|
var PointToPointConstraint = _dereq_("./PointToPointConstraint");
|
|
var RotationalEquation = _dereq_("../equations/RotationalEquation");
|
|
var RotationalMotorEquation = _dereq_("../equations/RotationalMotorEquation");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function HingeConstraint(bodyA, bodyB, options) {
|
|
options = options || {};
|
|
var maxForce = "undefined" !== typeof options.maxForce ? options.maxForce : 1e6;
|
|
var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
|
|
var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
|
|
PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
|
|
var axisA = this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
|
|
axisA.normalize();
|
|
var axisB = this.axisB = options.axisB ? options.axisB.clone() : new Vec3(1, 0, 0);
|
|
axisB.normalize();
|
|
var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options);
|
|
var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options);
|
|
var motor = this.motorEquation = new RotationalMotorEquation(bodyA, bodyB, maxForce);
|
|
motor.enabled = false;
|
|
this.equations.push(r1, r2, motor);
|
|
}
|
|
HingeConstraint.prototype = new PointToPointConstraint();
|
|
HingeConstraint.constructor = HingeConstraint;
|
|
HingeConstraint.prototype.enableMotor = function() {
|
|
this.motorEquation.enabled = true;
|
|
};
|
|
HingeConstraint.prototype.disableMotor = function() {
|
|
this.motorEquation.enabled = false;
|
|
};
|
|
HingeConstraint.prototype.setMotorSpeed = function(speed) {
|
|
this.motorEquation.targetVelocity = speed;
|
|
};
|
|
HingeConstraint.prototype.setMotorMaxForce = function(maxForce) {
|
|
this.motorEquation.maxForce = maxForce;
|
|
this.motorEquation.minForce = -maxForce;
|
|
};
|
|
var HingeConstraint_update_tmpVec1 = new Vec3();
|
|
var HingeConstraint_update_tmpVec2 = new Vec3();
|
|
HingeConstraint.prototype.update = function() {
|
|
var bodyA = this.bodyA, bodyB = this.bodyB, motor = this.motorEquation, r1 = this.rotationalEquation1, r2 = this.rotationalEquation2, worldAxisA = HingeConstraint_update_tmpVec1, worldAxisB = HingeConstraint_update_tmpVec2;
|
|
var axisA = this.axisA;
|
|
var axisB = this.axisB;
|
|
PointToPointConstraint.prototype.update.call(this);
|
|
bodyA.quaternion.vmult(axisA, worldAxisA);
|
|
bodyB.quaternion.vmult(axisB, worldAxisB);
|
|
worldAxisA.tangents(r1.axisA, r2.axisA);
|
|
r1.axisB.copy(worldAxisB);
|
|
r2.axisB.copy(worldAxisB);
|
|
if (this.motorEquation.enabled) {
|
|
bodyA.quaternion.vmult(this.axisA, motor.axisA);
|
|
bodyB.quaternion.vmult(this.axisB, motor.axisB);
|
|
}
|
|
};
|
|
}, {
|
|
"../equations/ContactEquation": 20,
|
|
"../equations/RotationalEquation": 23,
|
|
"../equations/RotationalMotorEquation": 24,
|
|
"../math/Vec3": 32,
|
|
"./Constraint": 14,
|
|
"./PointToPointConstraint": 18
|
|
} ],
|
|
17: [ function(_dereq_, module, exports) {
|
|
module.exports = LockConstraint;
|
|
var Constraint = _dereq_("./Constraint");
|
|
var PointToPointConstraint = _dereq_("./PointToPointConstraint");
|
|
var RotationalEquation = _dereq_("../equations/RotationalEquation");
|
|
var RotationalMotorEquation = _dereq_("../equations/RotationalMotorEquation");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function LockConstraint(bodyA, bodyB, options) {
|
|
options = options || {};
|
|
var maxForce = "undefined" !== typeof options.maxForce ? options.maxForce : 1e6;
|
|
var pivotA = new Vec3();
|
|
var pivotB = new Vec3();
|
|
var halfWay = new Vec3();
|
|
bodyA.position.vadd(bodyB.position, halfWay);
|
|
halfWay.scale(.5, halfWay);
|
|
bodyB.pointToLocalFrame(halfWay, pivotB);
|
|
bodyA.pointToLocalFrame(halfWay, pivotA);
|
|
PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
|
|
this.xA = bodyA.vectorToLocalFrame(Vec3.UNIT_X);
|
|
this.xB = bodyB.vectorToLocalFrame(Vec3.UNIT_X);
|
|
this.yA = bodyA.vectorToLocalFrame(Vec3.UNIT_Y);
|
|
this.yB = bodyB.vectorToLocalFrame(Vec3.UNIT_Y);
|
|
this.zA = bodyA.vectorToLocalFrame(Vec3.UNIT_Z);
|
|
this.zB = bodyB.vectorToLocalFrame(Vec3.UNIT_Z);
|
|
var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options);
|
|
var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options);
|
|
var r3 = this.rotationalEquation3 = new RotationalEquation(bodyA, bodyB, options);
|
|
this.equations.push(r1, r2, r3);
|
|
}
|
|
LockConstraint.prototype = new PointToPointConstraint();
|
|
LockConstraint.constructor = LockConstraint;
|
|
var LockConstraint_update_tmpVec1 = new Vec3();
|
|
var LockConstraint_update_tmpVec2 = new Vec3();
|
|
LockConstraint.prototype.update = function() {
|
|
var bodyA = this.bodyA, bodyB = this.bodyB, motor = this.motorEquation, r1 = this.rotationalEquation1, r2 = this.rotationalEquation2, r3 = this.rotationalEquation3, worldAxisA = LockConstraint_update_tmpVec1, worldAxisB = LockConstraint_update_tmpVec2;
|
|
PointToPointConstraint.prototype.update.call(this);
|
|
bodyA.vectorToWorldFrame(this.xA, r1.axisA);
|
|
bodyB.vectorToWorldFrame(this.yB, r1.axisB);
|
|
bodyA.vectorToWorldFrame(this.yA, r2.axisA);
|
|
bodyB.vectorToWorldFrame(this.zB, r2.axisB);
|
|
bodyA.vectorToWorldFrame(this.zA, r3.axisA);
|
|
bodyB.vectorToWorldFrame(this.xB, r3.axisB);
|
|
};
|
|
}, {
|
|
"../equations/ContactEquation": 20,
|
|
"../equations/RotationalEquation": 23,
|
|
"../equations/RotationalMotorEquation": 24,
|
|
"../math/Vec3": 32,
|
|
"./Constraint": 14,
|
|
"./PointToPointConstraint": 18
|
|
} ],
|
|
18: [ function(_dereq_, module, exports) {
|
|
module.exports = PointToPointConstraint;
|
|
var Constraint = _dereq_("./Constraint");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function PointToPointConstraint(bodyA, pivotA, bodyB, pivotB, maxForce) {
|
|
Constraint.call(this, bodyA, bodyB);
|
|
maxForce = "undefined" !== typeof maxForce ? maxForce : 1e6;
|
|
this.pivotA = pivotA ? pivotA.clone() : new Vec3();
|
|
this.pivotB = pivotB ? pivotB.clone() : new Vec3();
|
|
var x = this.equationX = new ContactEquation(bodyA, bodyB);
|
|
var y = this.equationY = new ContactEquation(bodyA, bodyB);
|
|
var z = this.equationZ = new ContactEquation(bodyA, bodyB);
|
|
this.equations.push(x, y, z);
|
|
x.minForce = y.minForce = z.minForce = -maxForce;
|
|
x.maxForce = y.maxForce = z.maxForce = maxForce;
|
|
x.ni.set(1, 0, 0);
|
|
y.ni.set(0, 1, 0);
|
|
z.ni.set(0, 0, 1);
|
|
}
|
|
PointToPointConstraint.prototype = new Constraint();
|
|
PointToPointConstraint.prototype.update = function() {
|
|
var bodyA = this.bodyA;
|
|
var bodyB = this.bodyB;
|
|
var x = this.equationX;
|
|
var y = this.equationY;
|
|
var z = this.equationZ;
|
|
bodyA.quaternion.vmult(this.pivotA, x.ri);
|
|
bodyB.quaternion.vmult(this.pivotB, x.rj);
|
|
y.ri.copy(x.ri);
|
|
y.rj.copy(x.rj);
|
|
z.ri.copy(x.ri);
|
|
z.rj.copy(x.rj);
|
|
};
|
|
}, {
|
|
"../equations/ContactEquation": 20,
|
|
"../math/Vec3": 32,
|
|
"./Constraint": 14
|
|
} ],
|
|
19: [ function(_dereq_, module, exports) {
|
|
module.exports = ConeEquation;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Mat3 = _dereq_("../math/Mat3");
|
|
var Equation = _dereq_("./Equation");
|
|
var CMath = _dereq_("../math/CMath");
|
|
function ConeEquation(bodyA, bodyB, options) {
|
|
options = options || {};
|
|
var maxForce = "undefined" !== typeof options.maxForce ? options.maxForce : 1e6;
|
|
Equation.call(this, bodyA, bodyB, -maxForce, maxForce);
|
|
this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
|
|
this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0);
|
|
this.angle = "undefined" !== typeof options.angle ? options.angle : 0;
|
|
}
|
|
ConeEquation.prototype = new Equation();
|
|
ConeEquation.prototype.constructor = ConeEquation;
|
|
var tmpVec1 = new Vec3();
|
|
var tmpVec2 = new Vec3();
|
|
ConeEquation.prototype.computeB = function(h) {
|
|
var a = this.a, b = this.b, ni = this.axisA, nj = this.axisB, nixnj = tmpVec1, njxni = tmpVec2, GA = this.jacobianElementA, GB = this.jacobianElementB;
|
|
ni.cross(nj, nixnj);
|
|
nj.cross(ni, njxni);
|
|
GA.rotational.copy(njxni);
|
|
GB.rotational.copy(nixnj);
|
|
var g = CMath.cos(this.angle) - ni.dot(nj), GW = this.computeGW(), GiMf = this.computeGiMf();
|
|
var B = -g * a - GW * b - h * GiMf;
|
|
return B;
|
|
};
|
|
}, {
|
|
"../math/CMath": 27,
|
|
"../math/Mat3": 29,
|
|
"../math/Vec3": 32,
|
|
"./Equation": 21
|
|
} ],
|
|
20: [ function(_dereq_, module, exports) {
|
|
module.exports = ContactEquation;
|
|
var Equation = _dereq_("./Equation");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Mat3 = _dereq_("../math/Mat3");
|
|
function ContactEquation(bodyA, bodyB, maxForce) {
|
|
maxForce = "undefined" !== typeof maxForce ? maxForce : 1e6;
|
|
Equation.call(this, bodyA, bodyB, 0, maxForce);
|
|
this.si = null;
|
|
this.sj = null;
|
|
this.restitution = 0;
|
|
this.ri = new Vec3();
|
|
this.rj = new Vec3();
|
|
this.ni = new Vec3();
|
|
}
|
|
ContactEquation.prototype = new Equation();
|
|
ContactEquation.prototype.constructor = ContactEquation;
|
|
var ContactEquation_computeB_temp1 = new Vec3();
|
|
var ContactEquation_computeB_temp2 = new Vec3();
|
|
var ContactEquation_computeB_temp3 = new Vec3();
|
|
ContactEquation.prototype.computeB = function(h) {
|
|
var a = this.a, b = this.b, bi = this.bi, bj = this.bj, ri = this.ri, rj = this.rj, rixn = ContactEquation_computeB_temp1, rjxn = ContactEquation_computeB_temp2, vi = bi.velocity, wi = bi.angularVelocity, fi = bi.force, taui = bi.torque, vj = bj.velocity, wj = bj.angularVelocity, fj = bj.force, tauj = bj.torque, penetrationVec = ContactEquation_computeB_temp3, GA = this.jacobianElementA, GB = this.jacobianElementB, n = this.ni;
|
|
ri.cross(n, rixn);
|
|
rj.cross(n, rjxn);
|
|
n.negate(GA.spatial);
|
|
rixn.negate(GA.rotational);
|
|
GB.spatial.copy(n);
|
|
GB.rotational.copy(rjxn);
|
|
penetrationVec.copy(bj.position);
|
|
penetrationVec.vadd(rj, penetrationVec);
|
|
penetrationVec.vsub(bi.position, penetrationVec);
|
|
penetrationVec.vsub(ri, penetrationVec);
|
|
var g = n.dot(penetrationVec);
|
|
var ePlusOne = this.restitution + 1;
|
|
var GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn);
|
|
var GiMf = this.computeGiMf();
|
|
var B = -g * a - GW * b - h * GiMf;
|
|
return B;
|
|
};
|
|
var ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3();
|
|
var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3();
|
|
ContactEquation.prototype.getImpactVelocityAlongNormal = function() {
|
|
var vi = ContactEquation_getImpactVelocityAlongNormal_vi;
|
|
var vj = ContactEquation_getImpactVelocityAlongNormal_vj;
|
|
var xi = ContactEquation_getImpactVelocityAlongNormal_xi;
|
|
var xj = ContactEquation_getImpactVelocityAlongNormal_xj;
|
|
var relVel = ContactEquation_getImpactVelocityAlongNormal_relVel;
|
|
this.bi.position.vadd(this.ri, xi);
|
|
this.bj.position.vadd(this.rj, xj);
|
|
this.bi.getVelocityAtWorldPoint(xi, vi);
|
|
this.bj.getVelocityAtWorldPoint(xj, vj);
|
|
vi.vsub(vj, relVel);
|
|
return this.ni.dot(relVel);
|
|
};
|
|
}, {
|
|
"../math/Mat3": 29,
|
|
"../math/Vec3": 32,
|
|
"./Equation": 21
|
|
} ],
|
|
21: [ function(_dereq_, module, exports) {
|
|
module.exports = Equation;
|
|
var JacobianElement = _dereq_("../math/JacobianElement"), Vec3 = _dereq_("../math/Vec3");
|
|
function Equation(bi, bj, minForce, maxForce) {
|
|
this.id = Equation.id++;
|
|
this.minForce = "undefined" === typeof minForce ? -1e6 : minForce;
|
|
this.maxForce = "undefined" === typeof maxForce ? 1e6 : maxForce;
|
|
this.bi = bi;
|
|
this.bj = bj;
|
|
this.a = 0;
|
|
this.b = 0;
|
|
this.eps = 0;
|
|
this.jacobianElementA = new JacobianElement();
|
|
this.jacobianElementB = new JacobianElement();
|
|
this.enabled = true;
|
|
this.multiplier = 0;
|
|
this.setSpookParams(1e7, 4, 1 / 60);
|
|
}
|
|
Equation.prototype.constructor = Equation;
|
|
Equation.id = 0;
|
|
Equation.prototype.setSpookParams = function(stiffness, relaxation, timeStep) {
|
|
var d = relaxation, k = stiffness, h = timeStep;
|
|
this.a = 4 / (h * (1 + 4 * d));
|
|
this.b = 4 * d / (1 + 4 * d);
|
|
this.eps = 4 / (h * h * k * (1 + 4 * d));
|
|
};
|
|
Equation.prototype.computeB = function(a, b, h) {
|
|
var GW = this.computeGW(), Gq = this.computeGq(), GiMf = this.computeGiMf();
|
|
return -Gq * a - GW * b - GiMf * h;
|
|
};
|
|
Equation.prototype.computeGq = function() {
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB, bi = this.bi, bj = this.bj, xi = bi.position, xj = bj.position;
|
|
return GA.spatial.dot(xi) + GB.spatial.dot(xj);
|
|
};
|
|
var zero = new Vec3();
|
|
Equation.prototype.computeGW = function() {
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB, bi = this.bi, bj = this.bj, vi = bi.velocity, vj = bj.velocity, wi = bi.angularVelocity, wj = bj.angularVelocity;
|
|
return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj);
|
|
};
|
|
Equation.prototype.computeGWlambda = function() {
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB, bi = this.bi, bj = this.bj, vi = bi.vlambda, vj = bj.vlambda, wi = bi.wlambda, wj = bj.wlambda;
|
|
return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj);
|
|
};
|
|
var iMfi = new Vec3(), iMfj = new Vec3(), invIi_vmult_taui = new Vec3(), invIj_vmult_tauj = new Vec3();
|
|
Equation.prototype.computeGiMf = function() {
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB, bi = this.bi, bj = this.bj, fi = bi.force, ti = bi.torque, fj = bj.force, tj = bj.torque, invMassi = bi.invMassSolve, invMassj = bj.invMassSolve;
|
|
fi.scale(invMassi, iMfi);
|
|
fj.scale(invMassj, iMfj);
|
|
bi.invInertiaWorldSolve.vmult(ti, invIi_vmult_taui);
|
|
bj.invInertiaWorldSolve.vmult(tj, invIj_vmult_tauj);
|
|
return GA.multiplyVectors(iMfi, invIi_vmult_taui) + GB.multiplyVectors(iMfj, invIj_vmult_tauj);
|
|
};
|
|
var tmp = new Vec3();
|
|
Equation.prototype.computeGiMGt = function() {
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB, bi = this.bi, bj = this.bj, invMassi = bi.invMassSolve, invMassj = bj.invMassSolve, invIi = bi.invInertiaWorldSolve, invIj = bj.invInertiaWorldSolve, result = invMassi + invMassj;
|
|
invIi.vmult(GA.rotational, tmp);
|
|
result += tmp.dot(GA.rotational);
|
|
invIj.vmult(GB.rotational, tmp);
|
|
result += tmp.dot(GB.rotational);
|
|
return result;
|
|
};
|
|
var addToWlambda_temp = new Vec3(), addToWlambda_Gi = new Vec3(), addToWlambda_Gj = new Vec3(), addToWlambda_ri = new Vec3(), addToWlambda_rj = new Vec3(), addToWlambda_Mdiag = new Vec3();
|
|
Equation.prototype.addToWlambda = function(deltalambda) {
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB, bi = this.bi, bj = this.bj, temp = addToWlambda_temp;
|
|
bi.vlambda.addScaledVector(bi.invMassSolve * deltalambda, GA.spatial, bi.vlambda);
|
|
bj.vlambda.addScaledVector(bj.invMassSolve * deltalambda, GB.spatial, bj.vlambda);
|
|
bi.invInertiaWorldSolve.vmult(GA.rotational, temp);
|
|
bi.wlambda.addScaledVector(deltalambda, temp, bi.wlambda);
|
|
bj.invInertiaWorldSolve.vmult(GB.rotational, temp);
|
|
bj.wlambda.addScaledVector(deltalambda, temp, bj.wlambda);
|
|
};
|
|
Equation.prototype.computeC = function() {
|
|
return this.computeGiMGt() + this.eps;
|
|
};
|
|
}, {
|
|
"../math/JacobianElement": 28,
|
|
"../math/Vec3": 32
|
|
} ],
|
|
22: [ function(_dereq_, module, exports) {
|
|
module.exports = FrictionEquation;
|
|
var Equation = _dereq_("./Equation");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Mat3 = _dereq_("../math/Mat3");
|
|
function FrictionEquation(bodyA, bodyB, slipForce) {
|
|
Equation.call(this, bodyA, bodyB, -slipForce, slipForce);
|
|
this.ri = new Vec3();
|
|
this.rj = new Vec3();
|
|
this.t = new Vec3();
|
|
}
|
|
FrictionEquation.prototype = new Equation();
|
|
FrictionEquation.prototype.constructor = FrictionEquation;
|
|
var FrictionEquation_computeB_temp1 = new Vec3();
|
|
var FrictionEquation_computeB_temp2 = new Vec3();
|
|
FrictionEquation.prototype.computeB = function(h) {
|
|
var a = this.a, b = this.b, bi = this.bi, bj = this.bj, ri = this.ri, rj = this.rj, rixt = FrictionEquation_computeB_temp1, rjxt = FrictionEquation_computeB_temp2, t = this.t;
|
|
ri.cross(t, rixt);
|
|
rj.cross(t, rjxt);
|
|
var GA = this.jacobianElementA, GB = this.jacobianElementB;
|
|
t.negate(GA.spatial);
|
|
rixt.negate(GA.rotational);
|
|
GB.spatial.copy(t);
|
|
GB.rotational.copy(rjxt);
|
|
var GW = this.computeGW();
|
|
var GiMf = this.computeGiMf();
|
|
var B = -GW * b - h * GiMf;
|
|
return B;
|
|
};
|
|
}, {
|
|
"../math/Mat3": 29,
|
|
"../math/Vec3": 32,
|
|
"./Equation": 21
|
|
} ],
|
|
23: [ function(_dereq_, module, exports) {
|
|
module.exports = RotationalEquation;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Mat3 = _dereq_("../math/Mat3");
|
|
var Equation = _dereq_("./Equation");
|
|
var CMath = _dereq_("../math/CMath");
|
|
function RotationalEquation(bodyA, bodyB, options) {
|
|
options = options || {};
|
|
var maxForce = "undefined" !== typeof options.maxForce ? options.maxForce : 1e6;
|
|
Equation.call(this, bodyA, bodyB, -maxForce, maxForce);
|
|
this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
|
|
this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0);
|
|
this.maxAngle = Math.PI / 2;
|
|
}
|
|
RotationalEquation.prototype = new Equation();
|
|
RotationalEquation.prototype.constructor = RotationalEquation;
|
|
var tmpVec1 = new Vec3();
|
|
var tmpVec2 = new Vec3();
|
|
RotationalEquation.prototype.computeB = function(h) {
|
|
var a = this.a, b = this.b, ni = this.axisA, nj = this.axisB, nixnj = tmpVec1, njxni = tmpVec2, GA = this.jacobianElementA, GB = this.jacobianElementB;
|
|
ni.cross(nj, nixnj);
|
|
nj.cross(ni, njxni);
|
|
GA.rotational.copy(njxni);
|
|
GB.rotational.copy(nixnj);
|
|
var g = CMath.cos(this.maxAngle) - ni.dot(nj), GW = this.computeGW(), GiMf = this.computeGiMf();
|
|
var B = -g * a - GW * b - h * GiMf;
|
|
return B;
|
|
};
|
|
}, {
|
|
"../math/CMath": 27,
|
|
"../math/Mat3": 29,
|
|
"../math/Vec3": 32,
|
|
"./Equation": 21
|
|
} ],
|
|
24: [ function(_dereq_, module, exports) {
|
|
module.exports = RotationalMotorEquation;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Mat3 = _dereq_("../math/Mat3");
|
|
var Equation = _dereq_("./Equation");
|
|
function RotationalMotorEquation(bodyA, bodyB, maxForce) {
|
|
maxForce = "undefined" !== typeof maxForce ? maxForce : 1e6;
|
|
Equation.call(this, bodyA, bodyB, -maxForce, maxForce);
|
|
this.axisA = new Vec3();
|
|
this.axisB = new Vec3();
|
|
this.targetVelocity = 0;
|
|
}
|
|
RotationalMotorEquation.prototype = new Equation();
|
|
RotationalMotorEquation.prototype.constructor = RotationalMotorEquation;
|
|
RotationalMotorEquation.prototype.computeB = function(h) {
|
|
var a = this.a, b = this.b, bi = this.bi, bj = this.bj, axisA = this.axisA, axisB = this.axisB, GA = this.jacobianElementA, GB = this.jacobianElementB;
|
|
GA.rotational.copy(axisA);
|
|
axisB.negate(GB.rotational);
|
|
var GW = this.computeGW() - this.targetVelocity, GiMf = this.computeGiMf();
|
|
var B = -GW * b - h * GiMf;
|
|
return B;
|
|
};
|
|
}, {
|
|
"../math/Mat3": 29,
|
|
"../math/Vec3": 32,
|
|
"./Equation": 21
|
|
} ],
|
|
25: [ function(_dereq_, module, exports) {
|
|
var Utils = _dereq_("../utils/Utils");
|
|
module.exports = ContactMaterial;
|
|
function ContactMaterial(m1, m2, options) {
|
|
options = Utils.defaults(options, {
|
|
friction: .3,
|
|
restitution: .3,
|
|
contactEquationStiffness: 1e7,
|
|
contactEquationRelaxation: 3,
|
|
frictionEquationStiffness: 1e7,
|
|
frictionEquationRelaxation: 3
|
|
});
|
|
this.id = ContactMaterial.idCounter++;
|
|
this.materials = [ m1, m2 ];
|
|
this.friction = options.friction;
|
|
this.restitution = options.restitution;
|
|
this.contactEquationStiffness = options.contactEquationStiffness;
|
|
this.contactEquationRelaxation = options.contactEquationRelaxation;
|
|
this.frictionEquationStiffness = options.frictionEquationStiffness;
|
|
this.frictionEquationRelaxation = options.frictionEquationRelaxation;
|
|
}
|
|
ContactMaterial.idCounter = 0;
|
|
}, {
|
|
"../utils/Utils": 55
|
|
} ],
|
|
26: [ function(_dereq_, module, exports) {
|
|
module.exports = Material;
|
|
function Material(options) {
|
|
var name = "";
|
|
options = options || {};
|
|
if ("string" === typeof options) {
|
|
name = options;
|
|
options = {};
|
|
} else "object" === typeof options && (name = "");
|
|
this.name = name;
|
|
this.id = Material.idCounter++;
|
|
this.friction = "undefined" !== typeof options.friction ? options.friction : -1;
|
|
this.restitution = "undefined" !== typeof options.restitution ? options.restitution : -1;
|
|
}
|
|
Material.idCounter = 0;
|
|
}, {} ],
|
|
27: [ function(_dereq_, module, exports) {
|
|
var rad2ang = 180 / Math.PI;
|
|
function radian2angle(rad) {
|
|
return rad * rad2ang;
|
|
}
|
|
var sinArr = {};
|
|
function calculateSinByDigit(digit) {
|
|
if (sinArr.digit == digit) return;
|
|
var step = 1 / Math.pow(10, digit);
|
|
for (var i = 0; i <= 90; i += step) sinArr[i.toFixed(digit)] = Math.sin(i / rad2ang);
|
|
sinArr.digit = digit;
|
|
}
|
|
function sin360(angle, digit) {
|
|
if (angle <= 90) return sinArr[angle.toFixed(digit)];
|
|
if (angle <= 180) {
|
|
angle = 180 - angle;
|
|
return sinArr[angle.toFixed(digit)];
|
|
}
|
|
if (angle <= 270) {
|
|
angle -= 180;
|
|
return -sinArr[angle.toFixed(digit)];
|
|
}
|
|
angle = 360 - angle;
|
|
return -sinArr[angle.toFixed(digit)];
|
|
}
|
|
function sin(rad) {
|
|
var angle = radian2angle(rad) % 360;
|
|
angle < 0 && (angle += 360);
|
|
return sin360(angle, CMath._digit);
|
|
}
|
|
function cos(rad) {
|
|
var angle = (radian2angle(rad) + 90) % 360;
|
|
angle < 0 && (angle += 360);
|
|
return sin360(angle, CMath._digit);
|
|
}
|
|
function sinNative(rad) {
|
|
return Math.sin(rad).toFixed(CMath.digit);
|
|
}
|
|
function cosNative(rad) {
|
|
return Math.cos(rad).toFixed(CMath.digit);
|
|
}
|
|
var CMath = {
|
|
sin: Math.sin,
|
|
cos: Math.cos,
|
|
atan2: Math.atan2
|
|
};
|
|
CMath._sin = sin;
|
|
CMath._cos = cos;
|
|
CMath._sinArr = sinArr;
|
|
CMath._sin360 = sin360;
|
|
CMath._sinNative = sinNative;
|
|
CMath._cosNative = cosNative;
|
|
CMath._radian2angle = radian2angle;
|
|
CMath._calculateSinByDigit = calculateSinByDigit;
|
|
CMath._digit = 1;
|
|
Object.defineProperty(CMath, "digit", {
|
|
get: function get() {
|
|
return this._digit;
|
|
},
|
|
set: function set(v) {
|
|
this._digit = v;
|
|
1 == this._mode && calculateSinByDigit(v);
|
|
}
|
|
});
|
|
CMath._mode = 0;
|
|
Object.defineProperty(CMath, "mode", {
|
|
get: function get() {
|
|
return this._mode;
|
|
},
|
|
set: function set(v) {
|
|
if (this._mode != v) {
|
|
this._mode = v;
|
|
if (0 == v) {
|
|
CMath.sin = Math.sin;
|
|
CMath.cos = Math.cos;
|
|
} else if (1 == v) {
|
|
CMath.digit = CMath._digit;
|
|
CMath.sin = sin;
|
|
CMath.cos = cos;
|
|
} else if (2 == v) {
|
|
CMath.sin = sinNative;
|
|
CMath.cos = cosNative;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
module.exports = CMath;
|
|
}, {} ],
|
|
28: [ function(_dereq_, module, exports) {
|
|
module.exports = JacobianElement;
|
|
var Vec3 = _dereq_("./Vec3");
|
|
function JacobianElement() {
|
|
this.spatial = new Vec3();
|
|
this.rotational = new Vec3();
|
|
}
|
|
JacobianElement.prototype.multiplyElement = function(element) {
|
|
return element.spatial.dot(this.spatial) + element.rotational.dot(this.rotational);
|
|
};
|
|
JacobianElement.prototype.multiplyVectors = function(spatial, rotational) {
|
|
return spatial.dot(this.spatial) + rotational.dot(this.rotational);
|
|
};
|
|
}, {
|
|
"./Vec3": 32
|
|
} ],
|
|
29: [ function(_dereq_, module, exports) {
|
|
module.exports = Mat3;
|
|
var Vec3 = _dereq_("./Vec3");
|
|
function Mat3(elements) {
|
|
this.elements = elements || [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
|
|
}
|
|
Mat3.prototype.identity = function() {
|
|
var e = this.elements;
|
|
e[0] = 1;
|
|
e[1] = 0;
|
|
e[2] = 0;
|
|
e[3] = 0;
|
|
e[4] = 1;
|
|
e[5] = 0;
|
|
e[6] = 0;
|
|
e[7] = 0;
|
|
e[8] = 1;
|
|
};
|
|
Mat3.prototype.setZero = function() {
|
|
var e = this.elements;
|
|
e[0] = 0;
|
|
e[1] = 0;
|
|
e[2] = 0;
|
|
e[3] = 0;
|
|
e[4] = 0;
|
|
e[5] = 0;
|
|
e[6] = 0;
|
|
e[7] = 0;
|
|
e[8] = 0;
|
|
};
|
|
Mat3.prototype.setTrace = function(vec3) {
|
|
var e = this.elements;
|
|
e[0] = vec3.x;
|
|
e[4] = vec3.y;
|
|
e[8] = vec3.z;
|
|
};
|
|
Mat3.prototype.getTrace = function(target) {
|
|
var target = target || new Vec3();
|
|
var e = this.elements;
|
|
target.x = e[0];
|
|
target.y = e[4];
|
|
target.z = e[8];
|
|
};
|
|
Mat3.prototype.vmult = function(v, target) {
|
|
target = target || new Vec3();
|
|
var e = this.elements, x = v.x, y = v.y, z = v.z;
|
|
target.x = e[0] * x + e[1] * y + e[2] * z;
|
|
target.y = e[3] * x + e[4] * y + e[5] * z;
|
|
target.z = e[6] * x + e[7] * y + e[8] * z;
|
|
return target;
|
|
};
|
|
Mat3.prototype.smult = function(s) {
|
|
for (var i = 0; i < this.elements.length; i++) this.elements[i] *= s;
|
|
};
|
|
Mat3.prototype.mmult = function(m, target) {
|
|
var r = target || new Mat3();
|
|
for (var i = 0; i < 3; i++) for (var j = 0; j < 3; j++) {
|
|
var sum = 0;
|
|
for (var k = 0; k < 3; k++) sum += m.elements[i + 3 * k] * this.elements[k + 3 * j];
|
|
r.elements[i + 3 * j] = sum;
|
|
}
|
|
return r;
|
|
};
|
|
Mat3.prototype.scale = function(v, target) {
|
|
target = target || new Mat3();
|
|
var e = this.elements, t = target.elements;
|
|
for (var i = 0; 3 !== i; i++) {
|
|
t[3 * i + 0] = v.x * e[3 * i + 0];
|
|
t[3 * i + 1] = v.y * e[3 * i + 1];
|
|
t[3 * i + 2] = v.z * e[3 * i + 2];
|
|
}
|
|
return target;
|
|
};
|
|
Mat3.prototype.solve = function(b, target) {
|
|
target = target || new Vec3();
|
|
var nr = 3;
|
|
var nc = 4;
|
|
var eqns = [];
|
|
for (var i = 0; i < nr * nc; i++) eqns.push(0);
|
|
var i, j;
|
|
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) eqns[i + nc * j] = this.elements[i + 3 * j];
|
|
eqns[3] = b.x;
|
|
eqns[7] = b.y;
|
|
eqns[11] = b.z;
|
|
var n = 3, k = n, np;
|
|
var kp = 4;
|
|
var p, els;
|
|
do {
|
|
i = k - n;
|
|
if (0 === eqns[i + nc * i]) for (j = i + 1; j < k; j++) if (0 !== eqns[i + nc * j]) {
|
|
np = kp;
|
|
do {
|
|
p = kp - np;
|
|
eqns[p + nc * i] += eqns[p + nc * j];
|
|
} while (--np);
|
|
break;
|
|
}
|
|
if (0 !== eqns[i + nc * i]) for (j = i + 1; j < k; j++) {
|
|
var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
|
|
np = kp;
|
|
do {
|
|
p = kp - np;
|
|
eqns[p + nc * j] = p <= i ? 0 : eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
|
|
} while (--np);
|
|
}
|
|
} while (--n);
|
|
target.z = eqns[2 * nc + 3] / eqns[2 * nc + 2];
|
|
target.y = (eqns[1 * nc + 3] - eqns[1 * nc + 2] * target.z) / eqns[1 * nc + 1];
|
|
target.x = (eqns[0 * nc + 3] - eqns[0 * nc + 2] * target.z - eqns[0 * nc + 1] * target.y) / eqns[0 * nc + 0];
|
|
if (isNaN(target.x) || isNaN(target.y) || isNaN(target.z) || Infinity === target.x || Infinity === target.y || Infinity === target.z) throw "Could not solve equation! Got x=[" + target.toString() + "], b=[" + b.toString() + "], A=[" + this.toString() + "]";
|
|
return target;
|
|
};
|
|
Mat3.prototype.e = function(row, column, value) {
|
|
if (void 0 === value) return this.elements[column + 3 * row];
|
|
this.elements[column + 3 * row] = value;
|
|
};
|
|
Mat3.prototype.copy = function(source) {
|
|
for (var i = 0; i < source.elements.length; i++) this.elements[i] = source.elements[i];
|
|
return this;
|
|
};
|
|
Mat3.prototype.toString = function() {
|
|
var r = "";
|
|
var sep = ",";
|
|
for (var i = 0; i < 9; i++) r += this.elements[i] + sep;
|
|
return r;
|
|
};
|
|
Mat3.prototype.reverse = function(target) {
|
|
target = target || new Mat3();
|
|
var nr = 3;
|
|
var nc = 6;
|
|
var eqns = [];
|
|
for (var i = 0; i < nr * nc; i++) eqns.push(0);
|
|
var i, j;
|
|
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) eqns[i + nc * j] = this.elements[i + 3 * j];
|
|
eqns[3] = 1;
|
|
eqns[9] = 0;
|
|
eqns[15] = 0;
|
|
eqns[4] = 0;
|
|
eqns[10] = 1;
|
|
eqns[16] = 0;
|
|
eqns[5] = 0;
|
|
eqns[11] = 0;
|
|
eqns[17] = 1;
|
|
var n = 3, k = n, np;
|
|
var kp = nc;
|
|
var p;
|
|
do {
|
|
i = k - n;
|
|
if (0 === eqns[i + nc * i]) for (j = i + 1; j < k; j++) if (0 !== eqns[i + nc * j]) {
|
|
np = kp;
|
|
do {
|
|
p = kp - np;
|
|
eqns[p + nc * i] += eqns[p + nc * j];
|
|
} while (--np);
|
|
break;
|
|
}
|
|
if (0 !== eqns[i + nc * i]) for (j = i + 1; j < k; j++) {
|
|
var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
|
|
np = kp;
|
|
do {
|
|
p = kp - np;
|
|
eqns[p + nc * j] = p <= i ? 0 : eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
|
|
} while (--np);
|
|
}
|
|
} while (--n);
|
|
i = 2;
|
|
do {
|
|
j = i - 1;
|
|
do {
|
|
var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
|
|
np = nc;
|
|
do {
|
|
p = nc - np;
|
|
eqns[p + nc * j] = eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
|
|
} while (--np);
|
|
} while (j--);
|
|
} while (--i);
|
|
i = 2;
|
|
do {
|
|
var multiplier = 1 / eqns[i + nc * i];
|
|
np = nc;
|
|
do {
|
|
p = nc - np;
|
|
eqns[p + nc * i] = eqns[p + nc * i] * multiplier;
|
|
} while (--np);
|
|
} while (i--);
|
|
i = 2;
|
|
do {
|
|
j = 2;
|
|
do {
|
|
p = eqns[nr + j + nc * i];
|
|
if (isNaN(p) || Infinity === p) throw "Could not reverse! A=[" + this.toString() + "]";
|
|
target.e(i, j, p);
|
|
} while (j--);
|
|
} while (i--);
|
|
return target;
|
|
};
|
|
Mat3.prototype.setRotationFromQuaternion = function(q) {
|
|
var x = q.x, y = q.y, z = q.z, w = q.w, x2 = x + x, y2 = y + y, z2 = z + z, xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2, e = this.elements;
|
|
e[0] = 1 - (yy + zz);
|
|
e[1] = xy - wz;
|
|
e[2] = xz + wy;
|
|
e[3] = xy + wz;
|
|
e[4] = 1 - (xx + zz);
|
|
e[5] = yz - wx;
|
|
e[6] = xz - wy;
|
|
e[7] = yz + wx;
|
|
e[8] = 1 - (xx + yy);
|
|
return this;
|
|
};
|
|
Mat3.prototype.transpose = function(target) {
|
|
target = target || new Mat3();
|
|
var Mt = target.elements, M = this.elements;
|
|
for (var i = 0; 3 !== i; i++) for (var j = 0; 3 !== j; j++) Mt[3 * i + j] = M[3 * j + i];
|
|
return target;
|
|
};
|
|
}, {
|
|
"./Vec3": 32
|
|
} ],
|
|
30: [ function(_dereq_, module, exports) {
|
|
module.exports = Quaternion;
|
|
var Vec3 = _dereq_("./Vec3");
|
|
var CMath = _dereq_("./CMath");
|
|
function Quaternion(x, y, z, w) {
|
|
this.x = void 0 !== x ? x : 0;
|
|
this.y = void 0 !== y ? y : 0;
|
|
this.z = void 0 !== z ? z : 0;
|
|
this.w = void 0 !== w ? w : 1;
|
|
}
|
|
Quaternion.prototype.set = function(x, y, z, w) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w;
|
|
return this;
|
|
};
|
|
Quaternion.prototype.toString = function() {
|
|
return this.x + "," + this.y + "," + this.z + "," + this.w;
|
|
};
|
|
Quaternion.prototype.toArray = function() {
|
|
return [ this.x, this.y, this.z, this.w ];
|
|
};
|
|
Quaternion.prototype.setFromAxisAngle = function(axis, angle) {
|
|
var s = CMath.sin(.5 * angle);
|
|
this.x = axis.x * s;
|
|
this.y = axis.y * s;
|
|
this.z = axis.z * s;
|
|
this.w = CMath.cos(.5 * angle);
|
|
return this;
|
|
};
|
|
Quaternion.prototype.toAxisAngle = function(targetAxis) {
|
|
targetAxis = targetAxis || new Vec3();
|
|
this.normalize();
|
|
var angle = 2 * Math.acos(this.w);
|
|
var s = Math.sqrt(1 - this.w * this.w);
|
|
if (s < .001) {
|
|
targetAxis.x = this.x;
|
|
targetAxis.y = this.y;
|
|
targetAxis.z = this.z;
|
|
} else {
|
|
targetAxis.x = this.x / s;
|
|
targetAxis.y = this.y / s;
|
|
targetAxis.z = this.z / s;
|
|
}
|
|
return [ targetAxis, angle ];
|
|
};
|
|
var sfv_t1 = new Vec3(), sfv_t2 = new Vec3();
|
|
Quaternion.prototype.setFromVectors = function(u, v) {
|
|
if (u.isAntiparallelTo(v)) {
|
|
var t1 = sfv_t1;
|
|
var t2 = sfv_t2;
|
|
u.tangents(t1, t2);
|
|
this.setFromAxisAngle(t1, Math.PI);
|
|
} else {
|
|
var a = u.cross(v);
|
|
this.x = a.x;
|
|
this.y = a.y;
|
|
this.z = a.z;
|
|
this.w = Math.sqrt(Math.pow(u.norm(), 2) * Math.pow(v.norm(), 2)) + u.dot(v);
|
|
this.normalize();
|
|
}
|
|
return this;
|
|
};
|
|
var Quaternion_mult_va = new Vec3();
|
|
var Quaternion_mult_vb = new Vec3();
|
|
var Quaternion_mult_vaxvb = new Vec3();
|
|
Quaternion.prototype.mult = function(q, target) {
|
|
target = target || new Quaternion();
|
|
var ax = this.x, ay = this.y, az = this.z, aw = this.w, bx = q.x, by = q.y, bz = q.z, bw = q.w;
|
|
target.x = ax * bw + aw * bx + ay * bz - az * by;
|
|
target.y = ay * bw + aw * by + az * bx - ax * bz;
|
|
target.z = az * bw + aw * bz + ax * by - ay * bx;
|
|
target.w = aw * bw - ax * bx - ay * by - az * bz;
|
|
return target;
|
|
};
|
|
Quaternion.prototype.inverse = function(target) {
|
|
var x = this.x, y = this.y, z = this.z, w = this.w;
|
|
target = target || new Quaternion();
|
|
this.conjugate(target);
|
|
var inorm2 = 1 / (x * x + y * y + z * z + w * w);
|
|
target.x *= inorm2;
|
|
target.y *= inorm2;
|
|
target.z *= inorm2;
|
|
target.w *= inorm2;
|
|
return target;
|
|
};
|
|
Quaternion.prototype.conjugate = function(target) {
|
|
target = target || new Quaternion();
|
|
target.x = -this.x;
|
|
target.y = -this.y;
|
|
target.z = -this.z;
|
|
target.w = this.w;
|
|
return target;
|
|
};
|
|
Quaternion.prototype.normalize = function() {
|
|
var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
|
if (0 === l) {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
this.w = 0;
|
|
} else {
|
|
l = 1 / l;
|
|
this.x *= l;
|
|
this.y *= l;
|
|
this.z *= l;
|
|
this.w *= l;
|
|
}
|
|
return this;
|
|
};
|
|
Quaternion.prototype.normalizeFast = function() {
|
|
var f = (3 - (this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w)) / 2;
|
|
if (0 === f) {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
this.w = 0;
|
|
} else {
|
|
this.x *= f;
|
|
this.y *= f;
|
|
this.z *= f;
|
|
this.w *= f;
|
|
}
|
|
return this;
|
|
};
|
|
Quaternion.prototype.vmult = function(v, target) {
|
|
target = target || new Vec3();
|
|
var x = v.x, y = v.y, z = v.z;
|
|
var qx = this.x, qy = this.y, qz = this.z, qw = this.w;
|
|
var ix = qw * x + qy * z - qz * y, iy = qw * y + qz * x - qx * z, iz = qw * z + qx * y - qy * x, iw = -qx * x - qy * y - qz * z;
|
|
target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
|
target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
|
target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
|
return target;
|
|
};
|
|
Quaternion.prototype.copy = function(source) {
|
|
this.x = source.x;
|
|
this.y = source.y;
|
|
this.z = source.z;
|
|
this.w = source.w;
|
|
return this;
|
|
};
|
|
Quaternion.prototype.toEuler = function(target, order) {
|
|
order = order || "YZX";
|
|
var heading, attitude, bank;
|
|
var x = this.x, y = this.y, z = this.z, w = this.w;
|
|
switch (order) {
|
|
case "YZX":
|
|
var test = x * y + z * w;
|
|
if (test > .499) {
|
|
heading = 2 * CMath.atan2(x, w);
|
|
attitude = Math.PI / 2;
|
|
bank = 0;
|
|
}
|
|
if (test < -.499) {
|
|
heading = -2 * CMath.atan2(x, w);
|
|
attitude = -Math.PI / 2;
|
|
bank = 0;
|
|
}
|
|
if (isNaN(heading)) {
|
|
var sqx = x * x;
|
|
var sqy = y * y;
|
|
var sqz = z * z;
|
|
heading = CMath.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
|
|
attitude = Math.asin(2 * test);
|
|
bank = CMath.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw new Error("Euler order " + order + " not supported yet.");
|
|
}
|
|
target.y = heading;
|
|
target.z = attitude;
|
|
target.x = bank;
|
|
};
|
|
Quaternion.prototype.setFromEuler = function(x, y, z, order) {
|
|
order = order || "XYZ";
|
|
var c1 = CMath.cos(x / 2);
|
|
var c2 = CMath.cos(y / 2);
|
|
var c3 = CMath.cos(z / 2);
|
|
var s1 = CMath.sin(x / 2);
|
|
var s2 = CMath.sin(y / 2);
|
|
var s3 = CMath.sin(z / 2);
|
|
if ("XYZ" === order) {
|
|
this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
this.y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
this.z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
} else if ("YXZ" === order) {
|
|
this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
this.y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
this.w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
} else if ("ZXY" === order) {
|
|
this.x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
this.z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
} else if ("ZYX" === order) {
|
|
this.x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
this.w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
} else if ("YZX" === order) {
|
|
this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
} else if ("XZY" === order) {
|
|
this.x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
this.y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
this.z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
this.w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
}
|
|
return this;
|
|
};
|
|
Quaternion.prototype.clone = function() {
|
|
return new Quaternion(this.x, this.y, this.z, this.w);
|
|
};
|
|
Quaternion.prototype.slerp = function(toQuat, t, target) {
|
|
target = target || new Quaternion();
|
|
var ax = this.x, ay = this.y, az = this.z, aw = this.w, bx = toQuat.x, by = toQuat.y, bz = toQuat.z, bw = toQuat.w;
|
|
var omega, cosom, sinom, scale0, scale1;
|
|
cosom = ax * bx + ay * by + az * bz + aw * bw;
|
|
if (cosom < 0) {
|
|
cosom = -cosom;
|
|
bx = -bx;
|
|
by = -by;
|
|
bz = -bz;
|
|
bw = -bw;
|
|
}
|
|
if (1 - cosom > 1e-6) {
|
|
omega = Math.acos(cosom);
|
|
sinom = CMath.sin(omega);
|
|
scale0 = CMath.sin((1 - t) * omega) / sinom;
|
|
scale1 = CMath.sin(t * omega) / sinom;
|
|
} else {
|
|
scale0 = 1 - t;
|
|
scale1 = t;
|
|
}
|
|
target.x = scale0 * ax + scale1 * bx;
|
|
target.y = scale0 * ay + scale1 * by;
|
|
target.z = scale0 * az + scale1 * bz;
|
|
target.w = scale0 * aw + scale1 * bw;
|
|
return target;
|
|
};
|
|
Quaternion.prototype.integrate = function(angularVelocity, dt, angularFactor, target) {
|
|
target = target || new Quaternion();
|
|
var ax = angularVelocity.x * angularFactor.x, ay = angularVelocity.y * angularFactor.y, az = angularVelocity.z * angularFactor.z, bx = this.x, by = this.y, bz = this.z, bw = this.w;
|
|
var half_dt = .5 * dt;
|
|
target.x += half_dt * (ax * bw + ay * bz - az * by);
|
|
target.y += half_dt * (ay * bw + az * bx - ax * bz);
|
|
target.z += half_dt * (az * bw + ax * by - ay * bx);
|
|
target.w += half_dt * (-ax * bx - ay * by - az * bz);
|
|
return target;
|
|
};
|
|
}, {
|
|
"./CMath": 27,
|
|
"./Vec3": 32
|
|
} ],
|
|
31: [ function(_dereq_, module, exports) {
|
|
var Vec3 = _dereq_("./Vec3");
|
|
var Quaternion = _dereq_("./Quaternion");
|
|
module.exports = Transform;
|
|
function Transform(options) {
|
|
options = options || {};
|
|
this.position = new Vec3();
|
|
options.position && this.position.copy(options.position);
|
|
this.quaternion = new Quaternion();
|
|
options.quaternion && this.quaternion.copy(options.quaternion);
|
|
}
|
|
var tmpQuat = new Quaternion();
|
|
Transform.pointToLocalFrame = function(position, quaternion, worldPoint, result) {
|
|
var result = result || new Vec3();
|
|
worldPoint.vsub(position, result);
|
|
quaternion.conjugate(tmpQuat);
|
|
tmpQuat.vmult(result, result);
|
|
return result;
|
|
};
|
|
Transform.prototype.pointToLocal = function(worldPoint, result) {
|
|
return Transform.pointToLocalFrame(this.position, this.quaternion, worldPoint, result);
|
|
};
|
|
Transform.pointToWorldFrame = function(position, quaternion, localPoint, result) {
|
|
var result = result || new Vec3();
|
|
quaternion.vmult(localPoint, result);
|
|
result.vadd(position, result);
|
|
return result;
|
|
};
|
|
Transform.prototype.pointToWorld = function(localPoint, result) {
|
|
return Transform.pointToWorldFrame(this.position, this.quaternion, localPoint, result);
|
|
};
|
|
Transform.prototype.vectorToWorldFrame = function(localVector, result) {
|
|
var result = result || new Vec3();
|
|
this.quaternion.vmult(localVector, result);
|
|
return result;
|
|
};
|
|
Transform.vectorToWorldFrame = function(quaternion, localVector, result) {
|
|
quaternion.vmult(localVector, result);
|
|
return result;
|
|
};
|
|
Transform.vectorToLocalFrame = function(position, quaternion, worldVector, result) {
|
|
var result = result || new Vec3();
|
|
quaternion.w *= -1;
|
|
quaternion.vmult(worldVector, result);
|
|
quaternion.w *= -1;
|
|
return result;
|
|
};
|
|
}, {
|
|
"./Quaternion": 30,
|
|
"./Vec3": 32
|
|
} ],
|
|
32: [ function(_dereq_, module, exports) {
|
|
module.exports = Vec3;
|
|
var Mat3 = _dereq_("./Mat3");
|
|
function Vec3(x, y, z) {
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
}
|
|
Vec3.ZERO = new Vec3(0, 0, 0);
|
|
Vec3.UNIT_X = new Vec3(1, 0, 0);
|
|
Vec3.UNIT_Y = new Vec3(0, 1, 0);
|
|
Vec3.UNIT_Z = new Vec3(0, 0, 1);
|
|
Vec3.prototype.cross = function(v, target) {
|
|
var vx = v.x, vy = v.y, vz = v.z, x = this.x, y = this.y, z = this.z;
|
|
target = target || new Vec3();
|
|
target.x = y * vz - z * vy;
|
|
target.y = z * vx - x * vz;
|
|
target.z = x * vy - y * vx;
|
|
return target;
|
|
};
|
|
Vec3.prototype.set = function(x, y, z) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
return this;
|
|
};
|
|
Vec3.prototype.setZero = function() {
|
|
this.x = this.y = this.z = 0;
|
|
};
|
|
Vec3.prototype.vadd = function(v, target) {
|
|
if (!target) return new Vec3(this.x + v.x, this.y + v.y, this.z + v.z);
|
|
target.x = v.x + this.x;
|
|
target.y = v.y + this.y;
|
|
target.z = v.z + this.z;
|
|
};
|
|
Vec3.prototype.vsub = function(v, target) {
|
|
if (!target) return new Vec3(this.x - v.x, this.y - v.y, this.z - v.z);
|
|
target.x = this.x - v.x;
|
|
target.y = this.y - v.y;
|
|
target.z = this.z - v.z;
|
|
};
|
|
Vec3.prototype.crossmat = function() {
|
|
return new Mat3([ 0, -this.z, this.y, this.z, 0, -this.x, -this.y, this.x, 0 ]);
|
|
};
|
|
Vec3.prototype.normalize = function() {
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var n = Math.sqrt(x * x + y * y + z * z);
|
|
if (n > 0) {
|
|
var invN = 1 / n;
|
|
this.x *= invN;
|
|
this.y *= invN;
|
|
this.z *= invN;
|
|
} else {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
}
|
|
return n;
|
|
};
|
|
Vec3.prototype.unit = function(target) {
|
|
target = target || new Vec3();
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var ninv = Math.sqrt(x * x + y * y + z * z);
|
|
if (ninv > 0) {
|
|
ninv = 1 / ninv;
|
|
target.x = x * ninv;
|
|
target.y = y * ninv;
|
|
target.z = z * ninv;
|
|
} else {
|
|
target.x = 1;
|
|
target.y = 0;
|
|
target.z = 0;
|
|
}
|
|
return target;
|
|
};
|
|
Vec3.prototype.norm = function() {
|
|
var x = this.x, y = this.y, z = this.z;
|
|
return Math.sqrt(x * x + y * y + z * z);
|
|
};
|
|
Vec3.prototype.length = Vec3.prototype.norm;
|
|
Vec3.prototype.norm2 = function() {
|
|
return this.dot(this);
|
|
};
|
|
Vec3.prototype.lengthSquared = Vec3.prototype.norm2;
|
|
Vec3.prototype.distanceTo = function(p) {
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var px = p.x, py = p.y, pz = p.z;
|
|
return Math.sqrt((px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z));
|
|
};
|
|
Vec3.prototype.distanceSquared = function(p) {
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var px = p.x, py = p.y, pz = p.z;
|
|
return (px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z);
|
|
};
|
|
Vec3.prototype.mult = function(scalar, target) {
|
|
target = target || new Vec3();
|
|
var x = this.x, y = this.y, z = this.z;
|
|
target.x = scalar * x;
|
|
target.y = scalar * y;
|
|
target.z = scalar * z;
|
|
return target;
|
|
};
|
|
Vec3.prototype.vmul = function(vector, target) {
|
|
target = target || new Vec3();
|
|
target.x = vector.x * this.x;
|
|
target.y = vector.y * this.y;
|
|
target.z = vector.z * this.z;
|
|
return target;
|
|
};
|
|
Vec3.prototype.scale = Vec3.prototype.mult;
|
|
Vec3.prototype.addScaledVector = function(scalar, vector, target) {
|
|
target = target || new Vec3();
|
|
target.x = this.x + scalar * vector.x;
|
|
target.y = this.y + scalar * vector.y;
|
|
target.z = this.z + scalar * vector.z;
|
|
return target;
|
|
};
|
|
Vec3.prototype.dot = function(v) {
|
|
return this.x * v.x + this.y * v.y + this.z * v.z;
|
|
};
|
|
Vec3.prototype.isZero = function() {
|
|
return 0 === this.x && 0 === this.y && 0 === this.z;
|
|
};
|
|
Vec3.prototype.negate = function(target) {
|
|
target = target || new Vec3();
|
|
target.x = -this.x;
|
|
target.y = -this.y;
|
|
target.z = -this.z;
|
|
return target;
|
|
};
|
|
var Vec3_tangents_n = new Vec3();
|
|
var Vec3_tangents_randVec = new Vec3();
|
|
Vec3.prototype.tangents = function(t1, t2) {
|
|
var norm = this.norm();
|
|
if (norm > 0) {
|
|
var n = Vec3_tangents_n;
|
|
var inorm = 1 / norm;
|
|
n.set(this.x * inorm, this.y * inorm, this.z * inorm);
|
|
var randVec = Vec3_tangents_randVec;
|
|
if (Math.abs(n.x) < .9) {
|
|
randVec.set(1, 0, 0);
|
|
n.cross(randVec, t1);
|
|
} else {
|
|
randVec.set(0, 1, 0);
|
|
n.cross(randVec, t1);
|
|
}
|
|
n.cross(t1, t2);
|
|
} else {
|
|
t1.set(1, 0, 0);
|
|
t2.set(0, 1, 0);
|
|
}
|
|
};
|
|
Vec3.prototype.toString = function() {
|
|
return this.x + "," + this.y + "," + this.z;
|
|
};
|
|
Vec3.prototype.toArray = function() {
|
|
return [ this.x, this.y, this.z ];
|
|
};
|
|
Vec3.prototype.copy = function(source) {
|
|
this.x = source.x;
|
|
this.y = source.y;
|
|
this.z = source.z;
|
|
return this;
|
|
};
|
|
Vec3.prototype.lerp = function(v, t, target) {
|
|
var x = this.x, y = this.y, z = this.z;
|
|
target.x = x + (v.x - x) * t;
|
|
target.y = y + (v.y - y) * t;
|
|
target.z = z + (v.z - z) * t;
|
|
};
|
|
Vec3.prototype.almostEquals = function(v, precision) {
|
|
void 0 === precision && (precision = 1e-6);
|
|
if (Math.abs(this.x - v.x) > precision || Math.abs(this.y - v.y) > precision || Math.abs(this.z - v.z) > precision) return false;
|
|
return true;
|
|
};
|
|
Vec3.prototype.almostZero = function(precision) {
|
|
void 0 === precision && (precision = 1e-6);
|
|
if (Math.abs(this.x) > precision || Math.abs(this.y) > precision || Math.abs(this.z) > precision) return false;
|
|
return true;
|
|
};
|
|
var antip_neg = new Vec3();
|
|
Vec3.prototype.isAntiparallelTo = function(v, precision) {
|
|
this.negate(antip_neg);
|
|
return antip_neg.almostEquals(v, precision);
|
|
};
|
|
Vec3.prototype.clone = function() {
|
|
return new Vec3(this.x, this.y, this.z);
|
|
};
|
|
}, {
|
|
"./Mat3": 29
|
|
} ],
|
|
33: [ function(_dereq_, module, exports) {
|
|
module.exports = Body;
|
|
var EventTarget = _dereq_("../utils/EventTarget");
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Mat3 = _dereq_("../math/Mat3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Material = _dereq_("../material/Material");
|
|
var AABB = _dereq_("../collision/AABB");
|
|
var Box = _dereq_("../shapes/Box");
|
|
var World = _dereq_("../world/World");
|
|
function Body(options) {
|
|
options = options || {};
|
|
EventTarget.apply(this);
|
|
this.id = Body.idCounter++;
|
|
this.world = null;
|
|
this.preStep = null;
|
|
this.postStep = null;
|
|
this.vlambda = new Vec3();
|
|
this.collisionFilterGroup = "number" === typeof options.collisionFilterGroup ? options.collisionFilterGroup : 1;
|
|
this.collisionFilterMask = "number" === typeof options.collisionFilterMask ? options.collisionFilterMask : -1;
|
|
this.collisionResponse = true;
|
|
this.position = new Vec3();
|
|
this.previousPosition = new Vec3();
|
|
this.interpolatedPosition = new Vec3();
|
|
this.initPosition = new Vec3();
|
|
if (options.position) {
|
|
this.position.copy(options.position);
|
|
this.previousPosition.copy(options.position);
|
|
this.interpolatedPosition.copy(options.position);
|
|
this.initPosition.copy(options.position);
|
|
}
|
|
this.velocity = new Vec3();
|
|
options.velocity && this.velocity.copy(options.velocity);
|
|
this.initVelocity = new Vec3();
|
|
this.force = new Vec3();
|
|
var mass = "number" === typeof options.mass ? options.mass : 0;
|
|
this.mass = mass;
|
|
this.invMass = mass > 0 ? 1 / mass : 0;
|
|
this.material = options.material || null;
|
|
this.linearDamping = "number" === typeof options.linearDamping ? options.linearDamping : .01;
|
|
this.type = mass <= 0 ? Body.STATIC : Body.DYNAMIC;
|
|
typeof options.type === typeof Body.STATIC && (this.type = options.type);
|
|
this.allowSleep = "undefined" === typeof options.allowSleep || options.allowSleep;
|
|
this.sleepState = 0;
|
|
this.sleepSpeedLimit = "undefined" !== typeof options.sleepSpeedLimit ? options.sleepSpeedLimit : .1;
|
|
this.sleepTimeLimit = "undefined" !== typeof options.sleepTimeLimit ? options.sleepTimeLimit : 1;
|
|
this.timeLastSleepy = 0;
|
|
this._wakeUpAfterNarrowphase = false;
|
|
this.torque = new Vec3();
|
|
this.quaternion = new Quaternion();
|
|
this.initQuaternion = new Quaternion();
|
|
this.previousQuaternion = new Quaternion();
|
|
this.interpolatedQuaternion = new Quaternion();
|
|
if (options.quaternion) {
|
|
this.quaternion.copy(options.quaternion);
|
|
this.initQuaternion.copy(options.quaternion);
|
|
this.previousQuaternion.copy(options.quaternion);
|
|
this.interpolatedQuaternion.copy(options.quaternion);
|
|
}
|
|
this.angularVelocity = new Vec3();
|
|
options.angularVelocity && this.angularVelocity.copy(options.angularVelocity);
|
|
this.initAngularVelocity = new Vec3();
|
|
this.shapes = [];
|
|
this.shapeOffsets = [];
|
|
this.shapeOrientations = [];
|
|
this.inertia = new Vec3();
|
|
this.invInertia = new Vec3();
|
|
this.invInertiaWorld = new Mat3();
|
|
this.invMassSolve = 0;
|
|
this.invInertiaSolve = new Vec3();
|
|
this.invInertiaWorldSolve = new Mat3();
|
|
this.fixedRotation = "undefined" !== typeof options.fixedRotation && options.fixedRotation;
|
|
this.useGravity = true;
|
|
this.angularDamping = "undefined" !== typeof options.angularDamping ? options.angularDamping : .01;
|
|
this.linearFactor = new Vec3(1, 1, 1);
|
|
options.linearFactor && this.linearFactor.copy(options.linearFactor);
|
|
this.angularFactor = new Vec3(1, 1, 1);
|
|
options.angularFactor && this.angularFactor.copy(options.angularFactor);
|
|
this.aabb = new AABB();
|
|
this.aabbNeedsUpdate = true;
|
|
this.boundingRadius = 0;
|
|
this.wlambda = new Vec3();
|
|
options.shape && this.addShape(options.shape);
|
|
this.hasTrigger = true;
|
|
this.updateMassProperties();
|
|
}
|
|
Body.prototype = new EventTarget();
|
|
Body.prototype.constructor = Body;
|
|
Body.COLLIDE_EVENT_NAME = "collide";
|
|
Body.DYNAMIC = 1;
|
|
Body.STATIC = 2;
|
|
Body.KINEMATIC = 4;
|
|
Body.AWAKE = 0;
|
|
Body.SLEEPY = 1;
|
|
Body.SLEEPING = 2;
|
|
Body.idCounter = 0;
|
|
Body.wakeupEvent = {
|
|
type: "wakeup"
|
|
};
|
|
Body.prototype.wakeUp = function() {
|
|
World.SLEEPING = false;
|
|
var s = this.sleepState;
|
|
this.sleepState = 0;
|
|
this._wakeUpAfterNarrowphase = false;
|
|
s === Body.SLEEPING && this.dispatchEvent(Body.wakeupEvent);
|
|
};
|
|
Body.prototype.sleep = function() {
|
|
this.sleepState = Body.SLEEPING;
|
|
this.velocity.set(0, 0, 0);
|
|
this.angularVelocity.set(0, 0, 0);
|
|
this._wakeUpAfterNarrowphase = false;
|
|
};
|
|
Body.sleepyEvent = {
|
|
type: "sleepy"
|
|
};
|
|
Body.sleepEvent = {
|
|
type: "sleep"
|
|
};
|
|
Body.prototype.sleepTick = function(time) {
|
|
if (this.allowSleep) {
|
|
var sleepState = this.sleepState;
|
|
var speedSquared = this.velocity.norm2() + this.angularVelocity.norm2();
|
|
var speedLimitSquared = Math.pow(this.sleepSpeedLimit, 2);
|
|
if (sleepState === Body.AWAKE && speedSquared < speedLimitSquared) {
|
|
this.sleepState = Body.SLEEPY;
|
|
this.timeLastSleepy = time;
|
|
this.dispatchEvent(Body.sleepyEvent);
|
|
} else if (sleepState === Body.SLEEPY && speedSquared > speedLimitSquared) this.wakeUp(); else if (sleepState === Body.SLEEPY && time - this.timeLastSleepy > this.sleepTimeLimit) {
|
|
this.sleep();
|
|
this.dispatchEvent(Body.sleepEvent);
|
|
}
|
|
}
|
|
};
|
|
Body.prototype.updateSolveMassProperties = function() {
|
|
if (this.sleepState === Body.SLEEPING || this.type === Body.KINEMATIC) {
|
|
this.invMassSolve = 0;
|
|
this.invInertiaSolve.setZero();
|
|
this.invInertiaWorldSolve.setZero();
|
|
} else {
|
|
this.invMassSolve = this.invMass;
|
|
this.invInertiaSolve.copy(this.invInertia);
|
|
this.invInertiaWorldSolve.copy(this.invInertiaWorld);
|
|
}
|
|
};
|
|
Body.prototype.pointToLocalFrame = function(worldPoint, result) {
|
|
var result = result || new Vec3();
|
|
worldPoint.vsub(this.position, result);
|
|
this.quaternion.conjugate().vmult(result, result);
|
|
return result;
|
|
};
|
|
Body.prototype.vectorToLocalFrame = function(worldVector, result) {
|
|
var result = result || new Vec3();
|
|
this.quaternion.conjugate().vmult(worldVector, result);
|
|
return result;
|
|
};
|
|
Body.prototype.pointToWorldFrame = function(localPoint, result) {
|
|
var result = result || new Vec3();
|
|
this.quaternion.vmult(localPoint, result);
|
|
result.vadd(this.position, result);
|
|
return result;
|
|
};
|
|
Body.prototype.vectorToWorldFrame = function(localVector, result) {
|
|
var result = result || new Vec3();
|
|
this.quaternion.vmult(localVector, result);
|
|
return result;
|
|
};
|
|
var tmpVec = new Vec3();
|
|
var tmpQuat = new Quaternion();
|
|
Body.prototype.addShape = function(shape, _offset, _orientation) {
|
|
var offset = new Vec3();
|
|
var orientation = new Quaternion();
|
|
_offset && offset.copy(_offset);
|
|
_orientation && orientation.copy(_orientation);
|
|
this.shapes.push(shape);
|
|
this.shapeOffsets.push(offset);
|
|
this.shapeOrientations.push(orientation);
|
|
this.aabbNeedsUpdate = true;
|
|
this.updateMassProperties();
|
|
this.updateBoundingRadius();
|
|
this.updateHasTrigger();
|
|
World.idToShapeMap[shape.id] = shape;
|
|
shape.body = this;
|
|
return this;
|
|
};
|
|
Body.prototype.removeShape = function(shape) {
|
|
var idx = this.shapes.indexOf(shape);
|
|
if (-1 === idx) return;
|
|
this.shapes.splice(idx, 1);
|
|
this.shapeOffsets.splice(idx, 1);
|
|
this.shapeOrientations.splice(idx, 1);
|
|
this.aabbNeedsUpdate = true;
|
|
this.updateMassProperties();
|
|
this.updateBoundingRadius();
|
|
this.updateHasTrigger();
|
|
};
|
|
Body.prototype.updateBoundingRadius = function() {
|
|
var shapes = this.shapes, shapeOffsets = this.shapeOffsets, N = shapes.length, radius = 0;
|
|
for (var i = 0; i !== N; i++) {
|
|
var shape = shapes[i];
|
|
shape.updateBoundingSphereRadius();
|
|
var offset = shapeOffsets[i].norm(), r = shape.boundingSphereRadius;
|
|
offset + r > radius && (radius = offset + r);
|
|
}
|
|
this.boundingRadius = radius;
|
|
};
|
|
var computeAABB_shapeAABB = new AABB();
|
|
Body.prototype.computeAABB = function() {
|
|
var shapes = this.shapes, shapeOffsets = this.shapeOffsets, shapeOrientations = this.shapeOrientations, N = shapes.length, offset = tmpVec, orientation = tmpQuat, bodyQuat = this.quaternion, aabb = this.aabb, shapeAABB = computeAABB_shapeAABB;
|
|
for (var i = 0; i !== N; i++) {
|
|
var shape = shapes[i];
|
|
bodyQuat.vmult(shapeOffsets[i], offset);
|
|
offset.vadd(this.position, offset);
|
|
shapeOrientations[i].mult(bodyQuat, orientation);
|
|
shape.calculateWorldAABB(offset, orientation, shapeAABB.lowerBound, shapeAABB.upperBound);
|
|
0 === i ? aabb.copy(shapeAABB) : aabb.extend(shapeAABB);
|
|
}
|
|
this.aabbNeedsUpdate = false;
|
|
};
|
|
var uiw_m1 = new Mat3(), uiw_m2 = new Mat3(), uiw_m3 = new Mat3();
|
|
Body.prototype.updateInertiaWorld = function(force) {
|
|
var I = this.invInertia;
|
|
if (I.x !== I.y || I.y !== I.z || force) {
|
|
var m1 = uiw_m1, m2 = uiw_m2, m3 = uiw_m3;
|
|
m1.setRotationFromQuaternion(this.quaternion);
|
|
m1.transpose(m2);
|
|
m1.scale(I, m1);
|
|
m1.mmult(m2, this.invInertiaWorld);
|
|
} else ;
|
|
};
|
|
var Body_applyForce_r = new Vec3();
|
|
var Body_applyForce_rotForce = new Vec3();
|
|
Body.prototype.applyForce = function(force, relativePoint) {
|
|
if (this.type !== Body.DYNAMIC) return;
|
|
var rotForce = Body_applyForce_rotForce;
|
|
relativePoint.cross(force, rotForce);
|
|
this.force.vadd(force, this.force);
|
|
this.torque.vadd(rotForce, this.torque);
|
|
};
|
|
var Body_applyLocalForce_worldForce = new Vec3();
|
|
var Body_applyLocalForce_relativePointWorld = new Vec3();
|
|
Body.prototype.applyLocalForce = function(localForce, localPoint) {
|
|
if (this.type !== Body.DYNAMIC) return;
|
|
var worldForce = Body_applyLocalForce_worldForce;
|
|
var relativePointWorld = Body_applyLocalForce_relativePointWorld;
|
|
this.vectorToWorldFrame(localForce, worldForce);
|
|
this.vectorToWorldFrame(localPoint, relativePointWorld);
|
|
this.applyForce(worldForce, relativePointWorld);
|
|
};
|
|
var Body_applyImpulse_r = new Vec3();
|
|
var Body_applyImpulse_velo = new Vec3();
|
|
var Body_applyImpulse_rotVelo = new Vec3();
|
|
Body.prototype.applyImpulse = function(impulse, relativePoint) {
|
|
if (this.type !== Body.DYNAMIC) return;
|
|
var r = relativePoint;
|
|
var velo = Body_applyImpulse_velo;
|
|
velo.copy(impulse);
|
|
velo.mult(this.invMass, velo);
|
|
this.velocity.vadd(velo, this.velocity);
|
|
var rotVelo = Body_applyImpulse_rotVelo;
|
|
r.cross(impulse, rotVelo);
|
|
this.invInertiaWorld.vmult(rotVelo, rotVelo);
|
|
this.angularVelocity.vadd(rotVelo, this.angularVelocity);
|
|
};
|
|
var Body_applyLocalImpulse_worldImpulse = new Vec3();
|
|
var Body_applyLocalImpulse_relativePoint = new Vec3();
|
|
Body.prototype.applyLocalImpulse = function(localImpulse, localPoint) {
|
|
if (this.type !== Body.DYNAMIC) return;
|
|
var worldImpulse = Body_applyLocalImpulse_worldImpulse;
|
|
var relativePointWorld = Body_applyLocalImpulse_relativePoint;
|
|
this.vectorToWorldFrame(localImpulse, worldImpulse);
|
|
this.vectorToWorldFrame(localPoint, relativePointWorld);
|
|
this.applyImpulse(worldImpulse, relativePointWorld);
|
|
};
|
|
var Body_updateMassProperties_halfExtents = new Vec3();
|
|
Body.prototype.updateMassProperties = function() {
|
|
var halfExtents = Body_updateMassProperties_halfExtents;
|
|
this.invMass = this.mass > 0 ? 1 / this.mass : 0;
|
|
var I = this.inertia;
|
|
var fixed = this.fixedRotation;
|
|
this.computeAABB();
|
|
halfExtents.set((this.aabb.upperBound.x - this.aabb.lowerBound.x) / 2, (this.aabb.upperBound.y - this.aabb.lowerBound.y) / 2, (this.aabb.upperBound.z - this.aabb.lowerBound.z) / 2);
|
|
Box.calculateInertia(halfExtents, this.mass, I);
|
|
this.invInertia.set(I.x > 0 && !fixed ? 1 / I.x : 0, I.y > 0 && !fixed ? 1 / I.y : 0, I.z > 0 && !fixed ? 1 / I.z : 0);
|
|
this.updateInertiaWorld(true);
|
|
};
|
|
Body.prototype.getVelocityAtWorldPoint = function(worldPoint, result) {
|
|
var r = new Vec3();
|
|
worldPoint.vsub(this.position, r);
|
|
this.angularVelocity.cross(r, result);
|
|
this.velocity.vadd(result, result);
|
|
return result;
|
|
};
|
|
var torque = new Vec3();
|
|
var invI_tau_dt = new Vec3();
|
|
var w = new Quaternion();
|
|
var wq = new Quaternion();
|
|
Body.prototype.integrate = function(dt, quatNormalize, quatNormalizeFast) {
|
|
this.previousPosition.copy(this.position);
|
|
this.previousQuaternion.copy(this.quaternion);
|
|
if (!(this.type === Body.DYNAMIC || this.type === Body.KINEMATIC) || this.sleepState === Body.SLEEPING) return;
|
|
var velo = this.velocity, angularVelo = this.angularVelocity, pos = this.position, force = this.force, torque = this.torque, quat = this.quaternion, invMass = this.invMass, invInertia = this.invInertiaWorld, linearFactor = this.linearFactor;
|
|
var iMdt = invMass * dt;
|
|
velo.x += force.x * iMdt * linearFactor.x;
|
|
velo.y += force.y * iMdt * linearFactor.y;
|
|
velo.z += force.z * iMdt * linearFactor.z;
|
|
var e = invInertia.elements;
|
|
var angularFactor = this.angularFactor;
|
|
var tx = torque.x * angularFactor.x;
|
|
var ty = torque.y * angularFactor.y;
|
|
var tz = torque.z * angularFactor.z;
|
|
angularVelo.x += dt * (e[0] * tx + e[1] * ty + e[2] * tz);
|
|
angularVelo.y += dt * (e[3] * tx + e[4] * ty + e[5] * tz);
|
|
angularVelo.z += dt * (e[6] * tx + e[7] * ty + e[8] * tz);
|
|
pos.x += velo.x * dt;
|
|
pos.y += velo.y * dt;
|
|
pos.z += velo.z * dt;
|
|
quat.integrate(this.angularVelocity, dt, this.angularFactor, quat);
|
|
quatNormalize && (quatNormalizeFast ? quat.normalizeFast() : quat.normalize());
|
|
this.aabbNeedsUpdate = true;
|
|
this.updateInertiaWorld();
|
|
};
|
|
Body.prototype.isSleeping = function() {
|
|
return this.sleepState === Body.SLEEPING;
|
|
};
|
|
Body.prototype.isSleepy = function() {
|
|
return this.sleepState === Body.SLEEPY;
|
|
};
|
|
Body.prototype.isAwake = function() {
|
|
return this.sleepState === Body.AWAKE;
|
|
};
|
|
Body.prototype.updateHasTrigger = function() {
|
|
for (var i = this.shapes.length; i--; ) {
|
|
this.hasTrigger = !this.shapes[i].collisionResponse;
|
|
if (this.hasTrigger) break;
|
|
}
|
|
};
|
|
}, {
|
|
"../collision/AABB": 3,
|
|
"../material/Material": 26,
|
|
"../math/Mat3": 29,
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../shapes/Box": 39,
|
|
"../shapes/Shape": 45,
|
|
"../utils/EventTarget": 51,
|
|
"../world/World": 58
|
|
} ],
|
|
34: [ function(_dereq_, module, exports) {
|
|
var Body = _dereq_("./Body");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var RaycastResult = _dereq_("../collision/RaycastResult");
|
|
var Ray = _dereq_("../collision/Ray");
|
|
var WheelInfo = _dereq_("../objects/WheelInfo");
|
|
module.exports = RaycastVehicle;
|
|
function RaycastVehicle(options) {
|
|
this.chassisBody = options.chassisBody;
|
|
this.wheelInfos = [];
|
|
this.sliding = false;
|
|
this.world = null;
|
|
this.indexRightAxis = "undefined" !== typeof options.indexRightAxis ? options.indexRightAxis : 1;
|
|
this.indexForwardAxis = "undefined" !== typeof options.indexForwardAxis ? options.indexForwardAxis : 0;
|
|
this.indexUpAxis = "undefined" !== typeof options.indexUpAxis ? options.indexUpAxis : 2;
|
|
}
|
|
var tmpVec1 = new Vec3();
|
|
var tmpVec2 = new Vec3();
|
|
var tmpVec3 = new Vec3();
|
|
var tmpVec4 = new Vec3();
|
|
var tmpVec5 = new Vec3();
|
|
var tmpVec6 = new Vec3();
|
|
var tmpRay = new Ray();
|
|
RaycastVehicle.prototype.addWheel = function(options) {
|
|
options = options || {};
|
|
var info = new WheelInfo(options);
|
|
var index = this.wheelInfos.length;
|
|
this.wheelInfos.push(info);
|
|
return index;
|
|
};
|
|
RaycastVehicle.prototype.setSteeringValue = function(value, wheelIndex) {
|
|
var wheel = this.wheelInfos[wheelIndex];
|
|
wheel.steering = value;
|
|
};
|
|
var torque = new Vec3();
|
|
RaycastVehicle.prototype.applyEngineForce = function(value, wheelIndex) {
|
|
this.wheelInfos[wheelIndex].engineForce = value;
|
|
};
|
|
RaycastVehicle.prototype.setBrake = function(brake, wheelIndex) {
|
|
this.wheelInfos[wheelIndex].brake = brake;
|
|
};
|
|
RaycastVehicle.prototype.addToWorld = function(world) {
|
|
var constraints = this.constraints;
|
|
world.addBody(this.chassisBody);
|
|
var that = this;
|
|
this.preStepCallback = function() {
|
|
that.updateVehicle(world.dt);
|
|
};
|
|
world.addEventListener("preStep", this.preStepCallback);
|
|
this.world = world;
|
|
};
|
|
RaycastVehicle.prototype.getVehicleAxisWorld = function(axisIndex, result) {
|
|
result.set(0 === axisIndex ? 1 : 0, 1 === axisIndex ? 1 : 0, 2 === axisIndex ? 1 : 0);
|
|
this.chassisBody.vectorToWorldFrame(result, result);
|
|
};
|
|
RaycastVehicle.prototype.updateVehicle = function(timeStep) {
|
|
var wheelInfos = this.wheelInfos;
|
|
var numWheels = wheelInfos.length;
|
|
var chassisBody = this.chassisBody;
|
|
for (var i = 0; i < numWheels; i++) this.updateWheelTransform(i);
|
|
this.currentVehicleSpeedKmHour = 3.6 * chassisBody.velocity.norm();
|
|
var forwardWorld = new Vec3();
|
|
this.getVehicleAxisWorld(this.indexForwardAxis, forwardWorld);
|
|
forwardWorld.dot(chassisBody.velocity) < 0 && (this.currentVehicleSpeedKmHour *= -1);
|
|
for (var i = 0; i < numWheels; i++) this.castRay(wheelInfos[i]);
|
|
this.updateSuspension(timeStep);
|
|
var impulse = new Vec3();
|
|
var relpos = new Vec3();
|
|
for (var i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
var suspensionForce = wheel.suspensionForce;
|
|
suspensionForce > wheel.maxSuspensionForce && (suspensionForce = wheel.maxSuspensionForce);
|
|
wheel.raycastResult.hitNormalWorld.scale(suspensionForce * timeStep, impulse);
|
|
wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, relpos);
|
|
chassisBody.applyImpulse(impulse, relpos);
|
|
}
|
|
this.updateFriction(timeStep);
|
|
var hitNormalWorldScaledWithProj = new Vec3();
|
|
var fwd = new Vec3();
|
|
var vel = new Vec3();
|
|
for (i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
chassisBody.getVelocityAtWorldPoint(wheel.chassisConnectionPointWorld, vel);
|
|
var m = 1;
|
|
switch (this.indexUpAxis) {
|
|
case 1:
|
|
m = -1;
|
|
}
|
|
if (wheel.isInContact) {
|
|
this.getVehicleAxisWorld(this.indexForwardAxis, fwd);
|
|
var proj = fwd.dot(wheel.raycastResult.hitNormalWorld);
|
|
wheel.raycastResult.hitNormalWorld.scale(proj, hitNormalWorldScaledWithProj);
|
|
fwd.vsub(hitNormalWorldScaledWithProj, fwd);
|
|
var proj2 = fwd.dot(vel);
|
|
wheel.deltaRotation = m * proj2 * timeStep / wheel.radius;
|
|
}
|
|
!wheel.sliding && wheel.isInContact || 0 === wheel.engineForce || !wheel.useCustomSlidingRotationalSpeed || (wheel.deltaRotation = (wheel.engineForce > 0 ? 1 : -1) * wheel.customSlidingRotationalSpeed * timeStep);
|
|
Math.abs(wheel.brake) > Math.abs(wheel.engineForce) && (wheel.deltaRotation = 0);
|
|
wheel.rotation += wheel.deltaRotation;
|
|
wheel.deltaRotation *= .99;
|
|
}
|
|
};
|
|
RaycastVehicle.prototype.updateSuspension = function(deltaTime) {
|
|
var chassisBody = this.chassisBody;
|
|
var chassisMass = chassisBody.mass;
|
|
var wheelInfos = this.wheelInfos;
|
|
var numWheels = wheelInfos.length;
|
|
for (var w_it = 0; w_it < numWheels; w_it++) {
|
|
var wheel = wheelInfos[w_it];
|
|
if (wheel.isInContact) {
|
|
var force;
|
|
var susp_length = wheel.suspensionRestLength;
|
|
var current_length = wheel.suspensionLength;
|
|
var length_diff = susp_length - current_length;
|
|
force = wheel.suspensionStiffness * length_diff * wheel.clippedInvContactDotSuspension;
|
|
var projected_rel_vel = wheel.suspensionRelativeVelocity;
|
|
var susp_damping;
|
|
susp_damping = projected_rel_vel < 0 ? wheel.dampingCompression : wheel.dampingRelaxation;
|
|
force -= susp_damping * projected_rel_vel;
|
|
wheel.suspensionForce = force * chassisMass;
|
|
wheel.suspensionForce < 0 && (wheel.suspensionForce = 0);
|
|
} else wheel.suspensionForce = 0;
|
|
}
|
|
};
|
|
RaycastVehicle.prototype.removeFromWorld = function(world) {
|
|
var constraints = this.constraints;
|
|
world.remove(this.chassisBody);
|
|
world.removeEventListener("preStep", this.preStepCallback);
|
|
this.world = null;
|
|
};
|
|
var castRay_rayvector = new Vec3();
|
|
var castRay_target = new Vec3();
|
|
RaycastVehicle.prototype.castRay = function(wheel) {
|
|
var rayvector = castRay_rayvector;
|
|
var target = castRay_target;
|
|
this.updateWheelTransformWorld(wheel);
|
|
var chassisBody = this.chassisBody;
|
|
var depth = -1;
|
|
var raylen = wheel.suspensionRestLength + wheel.radius;
|
|
wheel.directionWorld.scale(raylen, rayvector);
|
|
var source = wheel.chassisConnectionPointWorld;
|
|
source.vadd(rayvector, target);
|
|
var raycastResult = wheel.raycastResult;
|
|
var param = 0;
|
|
raycastResult.reset();
|
|
var oldState = chassisBody.collisionResponse;
|
|
chassisBody.collisionResponse = false;
|
|
this.world.rayTest(source, target, raycastResult);
|
|
chassisBody.collisionResponse = oldState;
|
|
var object = raycastResult.body;
|
|
wheel.raycastResult.groundObject = 0;
|
|
if (object) {
|
|
depth = raycastResult.distance;
|
|
wheel.raycastResult.hitNormalWorld = raycastResult.hitNormalWorld;
|
|
wheel.isInContact = true;
|
|
var hitDistance = raycastResult.distance;
|
|
wheel.suspensionLength = hitDistance - wheel.radius;
|
|
var minSuspensionLength = wheel.suspensionRestLength - wheel.maxSuspensionTravel;
|
|
var maxSuspensionLength = wheel.suspensionRestLength + wheel.maxSuspensionTravel;
|
|
wheel.suspensionLength < minSuspensionLength && (wheel.suspensionLength = minSuspensionLength);
|
|
if (wheel.suspensionLength > maxSuspensionLength) {
|
|
wheel.suspensionLength = maxSuspensionLength;
|
|
wheel.raycastResult.reset();
|
|
}
|
|
var denominator = wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld);
|
|
var chassis_velocity_at_contactPoint = new Vec3();
|
|
chassisBody.getVelocityAtWorldPoint(wheel.raycastResult.hitPointWorld, chassis_velocity_at_contactPoint);
|
|
var projVel = wheel.raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint);
|
|
if (denominator >= -.1) {
|
|
wheel.suspensionRelativeVelocity = 0;
|
|
wheel.clippedInvContactDotSuspension = 10;
|
|
} else {
|
|
var inv = -1 / denominator;
|
|
wheel.suspensionRelativeVelocity = projVel * inv;
|
|
wheel.clippedInvContactDotSuspension = inv;
|
|
}
|
|
} else {
|
|
wheel.suspensionLength = wheel.suspensionRestLength + 0 * wheel.maxSuspensionTravel;
|
|
wheel.suspensionRelativeVelocity = 0;
|
|
wheel.directionWorld.scale(-1, wheel.raycastResult.hitNormalWorld);
|
|
wheel.clippedInvContactDotSuspension = 1;
|
|
}
|
|
return depth;
|
|
};
|
|
RaycastVehicle.prototype.updateWheelTransformWorld = function(wheel) {
|
|
wheel.isInContact = false;
|
|
var chassisBody = this.chassisBody;
|
|
chassisBody.pointToWorldFrame(wheel.chassisConnectionPointLocal, wheel.chassisConnectionPointWorld);
|
|
chassisBody.vectorToWorldFrame(wheel.directionLocal, wheel.directionWorld);
|
|
chassisBody.vectorToWorldFrame(wheel.axleLocal, wheel.axleWorld);
|
|
};
|
|
RaycastVehicle.prototype.updateWheelTransform = function(wheelIndex) {
|
|
var up = tmpVec4;
|
|
var right = tmpVec5;
|
|
var fwd = tmpVec6;
|
|
var wheel = this.wheelInfos[wheelIndex];
|
|
this.updateWheelTransformWorld(wheel);
|
|
wheel.directionLocal.scale(-1, up);
|
|
right.copy(wheel.axleLocal);
|
|
up.cross(right, fwd);
|
|
fwd.normalize();
|
|
right.normalize();
|
|
var steering = wheel.steering;
|
|
var steeringOrn = new Quaternion();
|
|
steeringOrn.setFromAxisAngle(up, steering);
|
|
var rotatingOrn = new Quaternion();
|
|
rotatingOrn.setFromAxisAngle(right, wheel.rotation);
|
|
var q = wheel.worldTransform.quaternion;
|
|
this.chassisBody.quaternion.mult(steeringOrn, q);
|
|
q.mult(rotatingOrn, q);
|
|
q.normalize();
|
|
var p = wheel.worldTransform.position;
|
|
p.copy(wheel.directionWorld);
|
|
p.scale(wheel.suspensionLength, p);
|
|
p.vadd(wheel.chassisConnectionPointWorld, p);
|
|
};
|
|
var directions = [ new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1) ];
|
|
RaycastVehicle.prototype.getWheelTransformWorld = function(wheelIndex) {
|
|
return this.wheelInfos[wheelIndex].worldTransform;
|
|
};
|
|
var updateFriction_surfNormalWS_scaled_proj = new Vec3();
|
|
var updateFriction_axle = [];
|
|
var updateFriction_forwardWS = [];
|
|
var sideFrictionStiffness2 = 1;
|
|
RaycastVehicle.prototype.updateFriction = function(timeStep) {
|
|
var surfNormalWS_scaled_proj = updateFriction_surfNormalWS_scaled_proj;
|
|
var wheelInfos = this.wheelInfos;
|
|
var numWheels = wheelInfos.length;
|
|
var chassisBody = this.chassisBody;
|
|
var forwardWS = updateFriction_forwardWS;
|
|
var axle = updateFriction_axle;
|
|
var numWheelsOnGround = 0;
|
|
for (var i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
var groundObject = wheel.raycastResult.body;
|
|
groundObject && numWheelsOnGround++;
|
|
wheel.sideImpulse = 0;
|
|
wheel.forwardImpulse = 0;
|
|
forwardWS[i] || (forwardWS[i] = new Vec3());
|
|
axle[i] || (axle[i] = new Vec3());
|
|
}
|
|
for (var i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
var groundObject = wheel.raycastResult.body;
|
|
if (groundObject) {
|
|
var axlei = axle[i];
|
|
var wheelTrans = this.getWheelTransformWorld(i);
|
|
wheelTrans.vectorToWorldFrame(directions[this.indexRightAxis], axlei);
|
|
var surfNormalWS = wheel.raycastResult.hitNormalWorld;
|
|
var proj = axlei.dot(surfNormalWS);
|
|
surfNormalWS.scale(proj, surfNormalWS_scaled_proj);
|
|
axlei.vsub(surfNormalWS_scaled_proj, axlei);
|
|
axlei.normalize();
|
|
surfNormalWS.cross(axlei, forwardWS[i]);
|
|
forwardWS[i].normalize();
|
|
wheel.sideImpulse = resolveSingleBilateral(chassisBody, wheel.raycastResult.hitPointWorld, groundObject, wheel.raycastResult.hitPointWorld, axlei);
|
|
wheel.sideImpulse *= sideFrictionStiffness2;
|
|
}
|
|
}
|
|
var sideFactor = 1;
|
|
var fwdFactor = .5;
|
|
this.sliding = false;
|
|
for (var i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
var groundObject = wheel.raycastResult.body;
|
|
var rollingFriction = 0;
|
|
wheel.slipInfo = 1;
|
|
if (groundObject) {
|
|
var defaultRollingFrictionImpulse = 0;
|
|
var maxImpulse = wheel.brake ? wheel.brake : defaultRollingFrictionImpulse;
|
|
rollingFriction = calcRollingFriction(chassisBody, groundObject, wheel.raycastResult.hitPointWorld, forwardWS[i], maxImpulse);
|
|
rollingFriction += wheel.engineForce * timeStep;
|
|
var factor = maxImpulse / rollingFriction;
|
|
wheel.slipInfo *= factor;
|
|
}
|
|
wheel.forwardImpulse = 0;
|
|
wheel.skidInfo = 1;
|
|
if (groundObject) {
|
|
wheel.skidInfo = 1;
|
|
var maximp = wheel.suspensionForce * timeStep * wheel.frictionSlip;
|
|
var maximpSide = maximp;
|
|
var maximpSquared = maximp * maximpSide;
|
|
wheel.forwardImpulse = rollingFriction;
|
|
var x = wheel.forwardImpulse * fwdFactor;
|
|
var y = wheel.sideImpulse * sideFactor;
|
|
var impulseSquared = x * x + y * y;
|
|
wheel.sliding = false;
|
|
if (impulseSquared > maximpSquared) {
|
|
this.sliding = true;
|
|
wheel.sliding = true;
|
|
var factor = maximp / Math.sqrt(impulseSquared);
|
|
wheel.skidInfo *= factor;
|
|
}
|
|
}
|
|
}
|
|
if (this.sliding) for (var i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
if (0 !== wheel.sideImpulse && wheel.skidInfo < 1) {
|
|
wheel.forwardImpulse *= wheel.skidInfo;
|
|
wheel.sideImpulse *= wheel.skidInfo;
|
|
}
|
|
}
|
|
for (var i = 0; i < numWheels; i++) {
|
|
var wheel = wheelInfos[i];
|
|
var rel_pos = new Vec3();
|
|
wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, rel_pos);
|
|
if (0 !== wheel.forwardImpulse) {
|
|
var impulse = new Vec3();
|
|
forwardWS[i].scale(wheel.forwardImpulse, impulse);
|
|
chassisBody.applyImpulse(impulse, rel_pos);
|
|
}
|
|
if (0 !== wheel.sideImpulse) {
|
|
var groundObject = wheel.raycastResult.body;
|
|
var rel_pos2 = new Vec3();
|
|
wheel.raycastResult.hitPointWorld.vsub(groundObject.position, rel_pos2);
|
|
var sideImp = new Vec3();
|
|
axle[i].scale(wheel.sideImpulse, sideImp);
|
|
chassisBody.vectorToLocalFrame(rel_pos, rel_pos);
|
|
rel_pos["xyz"[this.indexUpAxis]] *= wheel.rollInfluence;
|
|
chassisBody.vectorToWorldFrame(rel_pos, rel_pos);
|
|
chassisBody.applyImpulse(sideImp, rel_pos);
|
|
sideImp.scale(-1, sideImp);
|
|
groundObject.applyImpulse(sideImp, rel_pos2);
|
|
}
|
|
}
|
|
};
|
|
var calcRollingFriction_vel1 = new Vec3();
|
|
var calcRollingFriction_vel2 = new Vec3();
|
|
var calcRollingFriction_vel = new Vec3();
|
|
function calcRollingFriction(body0, body1, frictionPosWorld, frictionDirectionWorld, maxImpulse) {
|
|
var j1 = 0;
|
|
var contactPosWorld = frictionPosWorld;
|
|
var vel1 = calcRollingFriction_vel1;
|
|
var vel2 = calcRollingFriction_vel2;
|
|
var vel = calcRollingFriction_vel;
|
|
body0.getVelocityAtWorldPoint(contactPosWorld, vel1);
|
|
body1.getVelocityAtWorldPoint(contactPosWorld, vel2);
|
|
vel1.vsub(vel2, vel);
|
|
var vrel = frictionDirectionWorld.dot(vel);
|
|
var denom0 = computeImpulseDenominator(body0, frictionPosWorld, frictionDirectionWorld);
|
|
var denom1 = computeImpulseDenominator(body1, frictionPosWorld, frictionDirectionWorld);
|
|
var relaxation = 1;
|
|
var jacDiagABInv = relaxation / (denom0 + denom1);
|
|
j1 = -vrel * jacDiagABInv;
|
|
maxImpulse < j1 && (j1 = maxImpulse);
|
|
j1 < -maxImpulse && (j1 = -maxImpulse);
|
|
return j1;
|
|
}
|
|
var computeImpulseDenominator_r0 = new Vec3();
|
|
var computeImpulseDenominator_c0 = new Vec3();
|
|
var computeImpulseDenominator_vec = new Vec3();
|
|
var computeImpulseDenominator_m = new Vec3();
|
|
function computeImpulseDenominator(body, pos, normal) {
|
|
var r0 = computeImpulseDenominator_r0;
|
|
var c0 = computeImpulseDenominator_c0;
|
|
var vec = computeImpulseDenominator_vec;
|
|
var m = computeImpulseDenominator_m;
|
|
pos.vsub(body.position, r0);
|
|
r0.cross(normal, c0);
|
|
body.invInertiaWorld.vmult(c0, m);
|
|
m.cross(r0, vec);
|
|
return body.invMass + normal.dot(vec);
|
|
}
|
|
var resolveSingleBilateral_vel1 = new Vec3();
|
|
var resolveSingleBilateral_vel2 = new Vec3();
|
|
var resolveSingleBilateral_vel = new Vec3();
|
|
function resolveSingleBilateral(body1, pos1, body2, pos2, normal, impulse) {
|
|
var normalLenSqr = normal.norm2();
|
|
if (normalLenSqr > 1.1) return 0;
|
|
var vel1 = resolveSingleBilateral_vel1;
|
|
var vel2 = resolveSingleBilateral_vel2;
|
|
var vel = resolveSingleBilateral_vel;
|
|
body1.getVelocityAtWorldPoint(pos1, vel1);
|
|
body2.getVelocityAtWorldPoint(pos2, vel2);
|
|
vel1.vsub(vel2, vel);
|
|
var rel_vel = normal.dot(vel);
|
|
var contactDamping = .2;
|
|
var massTerm = 1 / (body1.invMass + body2.invMass);
|
|
var impulse = -contactDamping * rel_vel * massTerm;
|
|
return impulse;
|
|
}
|
|
}, {
|
|
"../collision/Ray": 10,
|
|
"../collision/RaycastResult": 11,
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../objects/WheelInfo": 38,
|
|
"./Body": 33
|
|
} ],
|
|
35: [ function(_dereq_, module, exports) {
|
|
var Body = _dereq_("./Body");
|
|
var Sphere = _dereq_("../shapes/Sphere");
|
|
var Box = _dereq_("../shapes/Box");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var HingeConstraint = _dereq_("../constraints/HingeConstraint");
|
|
var CMath = _dereq_("../math/CMath");
|
|
module.exports = RigidVehicle;
|
|
function RigidVehicle(options) {
|
|
this.wheelBodies = [];
|
|
this.coordinateSystem = "undefined" === typeof options.coordinateSystem ? new Vec3(1, 2, 3) : options.coordinateSystem.clone();
|
|
this.chassisBody = options.chassisBody;
|
|
if (!this.chassisBody) {
|
|
var chassisShape = new Box(new Vec3(5, 2, .5));
|
|
this.chassisBody = new Body(1, chassisShape);
|
|
}
|
|
this.constraints = [];
|
|
this.wheelAxes = [];
|
|
this.wheelForces = [];
|
|
}
|
|
RigidVehicle.prototype.addWheel = function(options) {
|
|
options = options || {};
|
|
var wheelBody = options.body;
|
|
wheelBody || (wheelBody = new Body(1, new Sphere(1.2)));
|
|
this.wheelBodies.push(wheelBody);
|
|
this.wheelForces.push(0);
|
|
var zero = new Vec3();
|
|
var position = "undefined" !== typeof options.position ? options.position.clone() : new Vec3();
|
|
var worldPosition = new Vec3();
|
|
this.chassisBody.pointToWorldFrame(position, worldPosition);
|
|
wheelBody.position.set(worldPosition.x, worldPosition.y, worldPosition.z);
|
|
var axis = "undefined" !== typeof options.axis ? options.axis.clone() : new Vec3(0, 1, 0);
|
|
this.wheelAxes.push(axis);
|
|
var hingeConstraint = new HingeConstraint(this.chassisBody, wheelBody, {
|
|
pivotA: position,
|
|
axisA: axis,
|
|
pivotB: Vec3.ZERO,
|
|
axisB: axis,
|
|
collideConnected: false
|
|
});
|
|
this.constraints.push(hingeConstraint);
|
|
return this.wheelBodies.length - 1;
|
|
};
|
|
RigidVehicle.prototype.setSteeringValue = function(value, wheelIndex) {
|
|
var axis = this.wheelAxes[wheelIndex];
|
|
var c = CMath.cos(value), s = CMath.sin(value), x = axis.x, y = axis.y;
|
|
this.constraints[wheelIndex].axisA.set(c * x - s * y, s * x + c * y, 0);
|
|
};
|
|
RigidVehicle.prototype.setMotorSpeed = function(value, wheelIndex) {
|
|
var hingeConstraint = this.constraints[wheelIndex];
|
|
hingeConstraint.enableMotor();
|
|
hingeConstraint.motorTargetVelocity = value;
|
|
};
|
|
RigidVehicle.prototype.disableMotor = function(wheelIndex) {
|
|
var hingeConstraint = this.constraints[wheelIndex];
|
|
hingeConstraint.disableMotor();
|
|
};
|
|
var torque = new Vec3();
|
|
RigidVehicle.prototype.setWheelForce = function(value, wheelIndex) {
|
|
this.wheelForces[wheelIndex] = value;
|
|
};
|
|
RigidVehicle.prototype.applyWheelForce = function(value, wheelIndex) {
|
|
var axis = this.wheelAxes[wheelIndex];
|
|
var wheelBody = this.wheelBodies[wheelIndex];
|
|
var bodyTorque = wheelBody.torque;
|
|
axis.scale(value, torque);
|
|
wheelBody.vectorToWorldFrame(torque, torque);
|
|
bodyTorque.vadd(torque, bodyTorque);
|
|
};
|
|
RigidVehicle.prototype.addToWorld = function(world) {
|
|
var constraints = this.constraints;
|
|
var bodies = this.wheelBodies.concat([ this.chassisBody ]);
|
|
for (var i = 0; i < bodies.length; i++) world.addBody(bodies[i]);
|
|
for (var i = 0; i < constraints.length; i++) world.addConstraint(constraints[i]);
|
|
world.addEventListener("preStep", this._update.bind(this));
|
|
};
|
|
RigidVehicle.prototype._update = function() {
|
|
var wheelForces = this.wheelForces;
|
|
for (var i = 0; i < wheelForces.length; i++) this.applyWheelForce(wheelForces[i], i);
|
|
};
|
|
RigidVehicle.prototype.removeFromWorld = function(world) {
|
|
var constraints = this.constraints;
|
|
var bodies = this.wheelBodies.concat([ this.chassisBody ]);
|
|
for (var i = 0; i < bodies.length; i++) world.remove(bodies[i]);
|
|
for (var i = 0; i < constraints.length; i++) world.removeConstraint(constraints[i]);
|
|
};
|
|
var worldAxis = new Vec3();
|
|
RigidVehicle.prototype.getWheelSpeed = function(wheelIndex) {
|
|
var axis = this.wheelAxes[wheelIndex];
|
|
var wheelBody = this.wheelBodies[wheelIndex];
|
|
var w = wheelBody.angularVelocity;
|
|
this.chassisBody.vectorToWorldFrame(axis, worldAxis);
|
|
return w.dot(worldAxis);
|
|
};
|
|
}, {
|
|
"../constraints/HingeConstraint": 16,
|
|
"../math/CMath": 27,
|
|
"../math/Vec3": 32,
|
|
"../shapes/Box": 39,
|
|
"../shapes/Sphere": 46,
|
|
"./Body": 33
|
|
} ],
|
|
36: [ function(_dereq_, module, exports) {
|
|
module.exports = SPHSystem;
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Particle = _dereq_("../shapes/Particle");
|
|
var Body = _dereq_("../objects/Body");
|
|
var Material = _dereq_("../material/Material");
|
|
function SPHSystem() {
|
|
this.particles = [];
|
|
this.density = 1;
|
|
this.smoothingRadius = 1;
|
|
this.speedOfSound = 1;
|
|
this.viscosity = .01;
|
|
this.eps = 1e-6;
|
|
this.pressures = [];
|
|
this.densities = [];
|
|
this.neighbors = [];
|
|
}
|
|
SPHSystem.prototype.add = function(particle) {
|
|
this.particles.push(particle);
|
|
this.neighbors.length < this.particles.length && this.neighbors.push([]);
|
|
};
|
|
SPHSystem.prototype.remove = function(particle) {
|
|
var idx = this.particles.indexOf(particle);
|
|
if (-1 !== idx) {
|
|
this.particles.splice(idx, 1);
|
|
this.neighbors.length > this.particles.length && this.neighbors.pop();
|
|
}
|
|
};
|
|
var SPHSystem_getNeighbors_dist = new Vec3();
|
|
SPHSystem.prototype.getNeighbors = function(particle, neighbors) {
|
|
var N = this.particles.length, id = particle.id, R2 = this.smoothingRadius * this.smoothingRadius, dist = SPHSystem_getNeighbors_dist;
|
|
for (var i = 0; i !== N; i++) {
|
|
var p = this.particles[i];
|
|
p.position.vsub(particle.position, dist);
|
|
id !== p.id && dist.norm2() < R2 && neighbors.push(p);
|
|
}
|
|
};
|
|
var SPHSystem_update_dist = new Vec3(), SPHSystem_update_a_pressure = new Vec3(), SPHSystem_update_a_visc = new Vec3(), SPHSystem_update_gradW = new Vec3(), SPHSystem_update_r_vec = new Vec3(), SPHSystem_update_u = new Vec3();
|
|
SPHSystem.prototype.update = function() {
|
|
var N = this.particles.length, dist = SPHSystem_update_dist, cs = this.speedOfSound, eps = this.eps;
|
|
for (var i = 0; i !== N; i++) {
|
|
var p = this.particles[i];
|
|
var neighbors = this.neighbors[i];
|
|
neighbors.length = 0;
|
|
this.getNeighbors(p, neighbors);
|
|
neighbors.push(this.particles[i]);
|
|
var numNeighbors = neighbors.length;
|
|
var sum = 0;
|
|
for (var j = 0; j !== numNeighbors; j++) {
|
|
p.position.vsub(neighbors[j].position, dist);
|
|
var len = dist.norm();
|
|
var weight = this.w(len);
|
|
sum += neighbors[j].mass * weight;
|
|
}
|
|
this.densities[i] = sum;
|
|
this.pressures[i] = cs * cs * (this.densities[i] - this.density);
|
|
}
|
|
var a_pressure = SPHSystem_update_a_pressure;
|
|
var a_visc = SPHSystem_update_a_visc;
|
|
var gradW = SPHSystem_update_gradW;
|
|
var r_vec = SPHSystem_update_r_vec;
|
|
var u = SPHSystem_update_u;
|
|
for (var i = 0; i !== N; i++) {
|
|
var particle = this.particles[i];
|
|
a_pressure.set(0, 0, 0);
|
|
a_visc.set(0, 0, 0);
|
|
var Pij;
|
|
var nabla;
|
|
var Vij;
|
|
var neighbors = this.neighbors[i];
|
|
var numNeighbors = neighbors.length;
|
|
for (var j = 0; j !== numNeighbors; j++) {
|
|
var neighbor = neighbors[j];
|
|
particle.position.vsub(neighbor.position, r_vec);
|
|
var r = r_vec.norm();
|
|
Pij = -neighbor.mass * (this.pressures[i] / (this.densities[i] * this.densities[i] + eps) + this.pressures[j] / (this.densities[j] * this.densities[j] + eps));
|
|
this.gradw(r_vec, gradW);
|
|
gradW.mult(Pij, gradW);
|
|
a_pressure.vadd(gradW, a_pressure);
|
|
neighbor.velocity.vsub(particle.velocity, u);
|
|
u.mult(1 / (1e-4 + this.densities[i] * this.densities[j]) * this.viscosity * neighbor.mass, u);
|
|
nabla = this.nablaw(r);
|
|
u.mult(nabla, u);
|
|
a_visc.vadd(u, a_visc);
|
|
}
|
|
a_visc.mult(particle.mass, a_visc);
|
|
a_pressure.mult(particle.mass, a_pressure);
|
|
particle.force.vadd(a_visc, particle.force);
|
|
particle.force.vadd(a_pressure, particle.force);
|
|
}
|
|
};
|
|
SPHSystem.prototype.w = function(r) {
|
|
var h = this.smoothingRadius;
|
|
return 315 / (64 * Math.PI * Math.pow(h, 9)) * Math.pow(h * h - r * r, 3);
|
|
};
|
|
SPHSystem.prototype.gradw = function(rVec, resultVec) {
|
|
var r = rVec.norm(), h = this.smoothingRadius;
|
|
rVec.mult(945 / (32 * Math.PI * Math.pow(h, 9)) * Math.pow(h * h - r * r, 2), resultVec);
|
|
};
|
|
SPHSystem.prototype.nablaw = function(r) {
|
|
var h = this.smoothingRadius;
|
|
var nabla = 945 / (32 * Math.PI * Math.pow(h, 9)) * (h * h - r * r) * (7 * r * r - 3 * h * h);
|
|
return nabla;
|
|
};
|
|
}, {
|
|
"../material/Material": 26,
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../objects/Body": 33,
|
|
"../shapes/Particle": 43,
|
|
"../shapes/Shape": 45
|
|
} ],
|
|
37: [ function(_dereq_, module, exports) {
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
module.exports = Spring;
|
|
function Spring(bodyA, bodyB, options) {
|
|
options = options || {};
|
|
this.restLength = "number" === typeof options.restLength ? options.restLength : 1;
|
|
this.stiffness = options.stiffness || 100;
|
|
this.damping = options.damping || 1;
|
|
this.bodyA = bodyA;
|
|
this.bodyB = bodyB;
|
|
this.localAnchorA = new Vec3();
|
|
this.localAnchorB = new Vec3();
|
|
options.localAnchorA && this.localAnchorA.copy(options.localAnchorA);
|
|
options.localAnchorB && this.localAnchorB.copy(options.localAnchorB);
|
|
options.worldAnchorA && this.setWorldAnchorA(options.worldAnchorA);
|
|
options.worldAnchorB && this.setWorldAnchorB(options.worldAnchorB);
|
|
}
|
|
Spring.prototype.setWorldAnchorA = function(worldAnchorA) {
|
|
this.bodyA.pointToLocalFrame(worldAnchorA, this.localAnchorA);
|
|
};
|
|
Spring.prototype.setWorldAnchorB = function(worldAnchorB) {
|
|
this.bodyB.pointToLocalFrame(worldAnchorB, this.localAnchorB);
|
|
};
|
|
Spring.prototype.getWorldAnchorA = function(result) {
|
|
this.bodyA.pointToWorldFrame(this.localAnchorA, result);
|
|
};
|
|
Spring.prototype.getWorldAnchorB = function(result) {
|
|
this.bodyB.pointToWorldFrame(this.localAnchorB, result);
|
|
};
|
|
var applyForce_r = new Vec3(), applyForce_r_unit = new Vec3(), applyForce_u = new Vec3(), applyForce_f = new Vec3(), applyForce_worldAnchorA = new Vec3(), applyForce_worldAnchorB = new Vec3(), applyForce_ri = new Vec3(), applyForce_rj = new Vec3(), applyForce_ri_x_f = new Vec3(), applyForce_rj_x_f = new Vec3(), applyForce_tmp = new Vec3();
|
|
Spring.prototype.applyForce = function() {
|
|
var k = this.stiffness, d = this.damping, l = this.restLength, bodyA = this.bodyA, bodyB = this.bodyB, r = applyForce_r, r_unit = applyForce_r_unit, u = applyForce_u, f = applyForce_f, tmp = applyForce_tmp;
|
|
var worldAnchorA = applyForce_worldAnchorA, worldAnchorB = applyForce_worldAnchorB, ri = applyForce_ri, rj = applyForce_rj, ri_x_f = applyForce_ri_x_f, rj_x_f = applyForce_rj_x_f;
|
|
this.getWorldAnchorA(worldAnchorA);
|
|
this.getWorldAnchorB(worldAnchorB);
|
|
worldAnchorA.vsub(bodyA.position, ri);
|
|
worldAnchorB.vsub(bodyB.position, rj);
|
|
worldAnchorB.vsub(worldAnchorA, r);
|
|
var rlen = r.norm();
|
|
r_unit.copy(r);
|
|
r_unit.normalize();
|
|
bodyB.velocity.vsub(bodyA.velocity, u);
|
|
bodyB.angularVelocity.cross(rj, tmp);
|
|
u.vadd(tmp, u);
|
|
bodyA.angularVelocity.cross(ri, tmp);
|
|
u.vsub(tmp, u);
|
|
r_unit.mult(-k * (rlen - l) - d * u.dot(r_unit), f);
|
|
bodyA.force.vsub(f, bodyA.force);
|
|
bodyB.force.vadd(f, bodyB.force);
|
|
ri.cross(f, ri_x_f);
|
|
rj.cross(f, rj_x_f);
|
|
bodyA.torque.vsub(ri_x_f, bodyA.torque);
|
|
bodyB.torque.vadd(rj_x_f, bodyB.torque);
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32
|
|
} ],
|
|
38: [ function(_dereq_, module, exports) {
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Transform = _dereq_("../math/Transform");
|
|
var RaycastResult = _dereq_("../collision/RaycastResult");
|
|
var Utils = _dereq_("../utils/Utils");
|
|
module.exports = WheelInfo;
|
|
function WheelInfo(options) {
|
|
options = Utils.defaults(options, {
|
|
chassisConnectionPointLocal: new Vec3(),
|
|
chassisConnectionPointWorld: new Vec3(),
|
|
directionLocal: new Vec3(),
|
|
directionWorld: new Vec3(),
|
|
axleLocal: new Vec3(),
|
|
axleWorld: new Vec3(),
|
|
suspensionRestLength: 1,
|
|
suspensionMaxLength: 2,
|
|
radius: 1,
|
|
suspensionStiffness: 100,
|
|
dampingCompression: 10,
|
|
dampingRelaxation: 10,
|
|
frictionSlip: 1e4,
|
|
steering: 0,
|
|
rotation: 0,
|
|
deltaRotation: 0,
|
|
rollInfluence: .01,
|
|
maxSuspensionForce: Number.MAX_VALUE,
|
|
isFrontWheel: true,
|
|
clippedInvContactDotSuspension: 1,
|
|
suspensionRelativeVelocity: 0,
|
|
suspensionForce: 0,
|
|
skidInfo: 0,
|
|
suspensionLength: 0,
|
|
maxSuspensionTravel: 1,
|
|
useCustomSlidingRotationalSpeed: false,
|
|
customSlidingRotationalSpeed: -.1
|
|
});
|
|
this.maxSuspensionTravel = options.maxSuspensionTravel;
|
|
this.customSlidingRotationalSpeed = options.customSlidingRotationalSpeed;
|
|
this.useCustomSlidingRotationalSpeed = options.useCustomSlidingRotationalSpeed;
|
|
this.sliding = false;
|
|
this.chassisConnectionPointLocal = options.chassisConnectionPointLocal.clone();
|
|
this.chassisConnectionPointWorld = options.chassisConnectionPointWorld.clone();
|
|
this.directionLocal = options.directionLocal.clone();
|
|
this.directionWorld = options.directionWorld.clone();
|
|
this.axleLocal = options.axleLocal.clone();
|
|
this.axleWorld = options.axleWorld.clone();
|
|
this.suspensionRestLength = options.suspensionRestLength;
|
|
this.suspensionMaxLength = options.suspensionMaxLength;
|
|
this.radius = options.radius;
|
|
this.suspensionStiffness = options.suspensionStiffness;
|
|
this.dampingCompression = options.dampingCompression;
|
|
this.dampingRelaxation = options.dampingRelaxation;
|
|
this.frictionSlip = options.frictionSlip;
|
|
this.steering = 0;
|
|
this.rotation = 0;
|
|
this.deltaRotation = 0;
|
|
this.rollInfluence = options.rollInfluence;
|
|
this.maxSuspensionForce = options.maxSuspensionForce;
|
|
this.engineForce = 0;
|
|
this.brake = 0;
|
|
this.isFrontWheel = options.isFrontWheel;
|
|
this.clippedInvContactDotSuspension = 1;
|
|
this.suspensionRelativeVelocity = 0;
|
|
this.suspensionForce = 0;
|
|
this.skidInfo = 0;
|
|
this.suspensionLength = 0;
|
|
this.sideImpulse = 0;
|
|
this.forwardImpulse = 0;
|
|
this.raycastResult = new RaycastResult();
|
|
this.worldTransform = new Transform();
|
|
this.isInContact = false;
|
|
}
|
|
var chassis_velocity_at_contactPoint = new Vec3();
|
|
var relpos = new Vec3();
|
|
var chassis_velocity_at_contactPoint = new Vec3();
|
|
WheelInfo.prototype.updateWheel = function(chassis) {
|
|
var raycastResult = this.raycastResult;
|
|
if (this.isInContact) {
|
|
var project = raycastResult.hitNormalWorld.dot(raycastResult.directionWorld);
|
|
raycastResult.hitPointWorld.vsub(chassis.position, relpos);
|
|
chassis.getVelocityAtWorldPoint(relpos, chassis_velocity_at_contactPoint);
|
|
var projVel = raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint);
|
|
if (project >= -.1) {
|
|
this.suspensionRelativeVelocity = 0;
|
|
this.clippedInvContactDotSuspension = 10;
|
|
} else {
|
|
var inv = -1 / project;
|
|
this.suspensionRelativeVelocity = projVel * inv;
|
|
this.clippedInvContactDotSuspension = inv;
|
|
}
|
|
} else {
|
|
raycastResult.suspensionLength = this.suspensionRestLength;
|
|
this.suspensionRelativeVelocity = 0;
|
|
raycastResult.directionWorld.scale(-1, raycastResult.hitNormalWorld);
|
|
this.clippedInvContactDotSuspension = 1;
|
|
}
|
|
};
|
|
}, {
|
|
"../collision/RaycastResult": 11,
|
|
"../math/Transform": 31,
|
|
"../math/Vec3": 32,
|
|
"../utils/Utils": 55
|
|
} ],
|
|
39: [ function(_dereq_, module, exports) {
|
|
module.exports = Box;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var ConvexPolyhedron = _dereq_("./ConvexPolyhedron");
|
|
function Box(halfExtents) {
|
|
Shape.call(this, {
|
|
type: Shape.types.BOX
|
|
});
|
|
this.halfExtents = halfExtents;
|
|
this.convexPolyhedronRepresentation = null;
|
|
this.updateConvexPolyhedronRepresentation();
|
|
this.updateBoundingSphereRadius();
|
|
}
|
|
Box.prototype = new Shape();
|
|
Box.prototype.constructor = Box;
|
|
Box.prototype.updateConvexPolyhedronRepresentation = function() {
|
|
var sx = this.halfExtents.x;
|
|
var sy = this.halfExtents.y;
|
|
var sz = this.halfExtents.z;
|
|
var V = Vec3;
|
|
var vertices = [ new V(-sx, -sy, -sz), new V(sx, -sy, -sz), new V(sx, sy, -sz), new V(-sx, sy, -sz), new V(-sx, -sy, sz), new V(sx, -sy, sz), new V(sx, sy, sz), new V(-sx, sy, sz) ];
|
|
var indices = [ [ 3, 2, 1, 0 ], [ 4, 5, 6, 7 ], [ 5, 4, 0, 1 ], [ 2, 3, 7, 6 ], [ 0, 4, 7, 3 ], [ 1, 2, 6, 5 ] ];
|
|
var axes = [ new V(0, 0, 1), new V(0, 1, 0), new V(1, 0, 0) ];
|
|
var h = new ConvexPolyhedron(vertices, indices);
|
|
this.convexPolyhedronRepresentation = h;
|
|
h.material = this.material;
|
|
};
|
|
Box.prototype.calculateLocalInertia = function(mass, target) {
|
|
target = target || new Vec3();
|
|
Box.calculateInertia(this.halfExtents, mass, target);
|
|
return target;
|
|
};
|
|
Box.calculateInertia = function(halfExtents, mass, target) {
|
|
var e = halfExtents;
|
|
if (e.isZero()) {
|
|
target.x = 2 / 12 * mass;
|
|
target.y = 2 / 12 * mass;
|
|
target.z = 2 / 12 * mass;
|
|
} else {
|
|
target.x = 1 / 12 * mass * (2 * e.y * 2 * e.y + 2 * e.z * 2 * e.z);
|
|
target.y = 1 / 12 * mass * (2 * e.x * 2 * e.x + 2 * e.z * 2 * e.z);
|
|
target.z = 1 / 12 * mass * (2 * e.y * 2 * e.y + 2 * e.x * 2 * e.x);
|
|
}
|
|
};
|
|
Box.prototype.getSideNormals = function(sixTargetVectors, quat) {
|
|
var sides = sixTargetVectors;
|
|
var ex = this.halfExtents;
|
|
sides[0].set(ex.x, 0, 0);
|
|
sides[1].set(0, ex.y, 0);
|
|
sides[2].set(0, 0, ex.z);
|
|
sides[3].set(-ex.x, 0, 0);
|
|
sides[4].set(0, -ex.y, 0);
|
|
sides[5].set(0, 0, -ex.z);
|
|
if (void 0 !== quat) for (var i = 0; i !== sides.length; i++) quat.vmult(sides[i], sides[i]);
|
|
return sides;
|
|
};
|
|
Box.prototype.volume = function() {
|
|
return 8 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z;
|
|
};
|
|
Box.prototype.updateBoundingSphereRadius = function() {
|
|
this.boundingSphereRadius = this.halfExtents.norm();
|
|
};
|
|
var worldCornerTempPos = new Vec3();
|
|
var worldCornerTempNeg = new Vec3();
|
|
Box.prototype.forEachWorldCorner = function(pos, quat, callback) {
|
|
var e = this.halfExtents;
|
|
var corners = [ [ e.x, e.y, e.z ], [ -e.x, e.y, e.z ], [ -e.x, -e.y, e.z ], [ -e.x, -e.y, -e.z ], [ e.x, -e.y, -e.z ], [ e.x, e.y, -e.z ], [ -e.x, e.y, -e.z ], [ e.x, -e.y, e.z ] ];
|
|
for (var i = 0; i < corners.length; i++) {
|
|
worldCornerTempPos.set(corners[i][0], corners[i][1], corners[i][2]);
|
|
quat.vmult(worldCornerTempPos, worldCornerTempPos);
|
|
pos.vadd(worldCornerTempPos, worldCornerTempPos);
|
|
callback(worldCornerTempPos.x, worldCornerTempPos.y, worldCornerTempPos.z);
|
|
}
|
|
};
|
|
var worldCornersTemp = [ new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3() ];
|
|
Box.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
var e = this.halfExtents;
|
|
worldCornersTemp[0].set(e.x, e.y, e.z);
|
|
worldCornersTemp[1].set(-e.x, e.y, e.z);
|
|
worldCornersTemp[2].set(-e.x, -e.y, e.z);
|
|
worldCornersTemp[3].set(-e.x, -e.y, -e.z);
|
|
worldCornersTemp[4].set(e.x, -e.y, -e.z);
|
|
worldCornersTemp[5].set(e.x, e.y, -e.z);
|
|
worldCornersTemp[6].set(-e.x, e.y, -e.z);
|
|
worldCornersTemp[7].set(e.x, -e.y, e.z);
|
|
var wc = worldCornersTemp[0];
|
|
quat.vmult(wc, wc);
|
|
pos.vadd(wc, wc);
|
|
max.copy(wc);
|
|
min.copy(wc);
|
|
for (var i = 1; i < 8; i++) {
|
|
var wc = worldCornersTemp[i];
|
|
quat.vmult(wc, wc);
|
|
pos.vadd(wc, wc);
|
|
var x = wc.x;
|
|
var y = wc.y;
|
|
var z = wc.z;
|
|
x > max.x && (max.x = x);
|
|
y > max.y && (max.y = y);
|
|
z > max.z && (max.z = z);
|
|
x < min.x && (min.x = x);
|
|
y < min.y && (min.y = y);
|
|
z < min.z && (min.z = z);
|
|
}
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"./ConvexPolyhedron": 40,
|
|
"./Shape": 45
|
|
} ],
|
|
40: [ function(_dereq_, module, exports) {
|
|
module.exports = ConvexPolyhedron;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Transform = _dereq_("../math/Transform");
|
|
function ConvexPolyhedron(points, faces, uniqueAxes) {
|
|
Shape.call(this, {
|
|
type: Shape.types.CONVEXPOLYHEDRON
|
|
});
|
|
this.vertices = points || [];
|
|
this.worldVertices = [];
|
|
this.worldVerticesNeedsUpdate = true;
|
|
this.faces = faces || [];
|
|
this.faceNormals = [];
|
|
this.computeNormals();
|
|
this.worldFaceNormalsNeedsUpdate = true;
|
|
this.worldFaceNormals = [];
|
|
this.uniqueEdges = [];
|
|
this.uniqueAxes = uniqueAxes ? uniqueAxes.slice() : null;
|
|
this.computeEdges();
|
|
this.updateBoundingSphereRadius();
|
|
}
|
|
ConvexPolyhedron.prototype = new Shape();
|
|
ConvexPolyhedron.prototype.constructor = ConvexPolyhedron;
|
|
var computeEdges_tmpEdge = new Vec3();
|
|
ConvexPolyhedron.prototype.computeEdges = function() {
|
|
var faces = this.faces;
|
|
var vertices = this.vertices;
|
|
var nv = vertices.length;
|
|
var edges = this.uniqueEdges;
|
|
edges.length = 0;
|
|
var edge = computeEdges_tmpEdge;
|
|
for (var i = 0; i !== faces.length; i++) {
|
|
var face = faces[i];
|
|
var numVertices = face.length;
|
|
for (var j = 0; j !== numVertices; j++) {
|
|
var k = (j + 1) % numVertices;
|
|
vertices[face[j]].vsub(vertices[face[k]], edge);
|
|
edge.normalize();
|
|
var found = false;
|
|
for (var p = 0; p !== edges.length; p++) if (edges[p].almostEquals(edge) || edges[p].almostEquals(edge)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
found || edges.push(edge.clone());
|
|
}
|
|
}
|
|
};
|
|
ConvexPolyhedron.prototype.computeNormals = function() {
|
|
this.faceNormals.length = this.faces.length;
|
|
for (var i = 0; i < this.faces.length; i++) {
|
|
for (var j = 0; j < this.faces[i].length; j++) if (!this.vertices[this.faces[i][j]]) throw new Error("Vertex " + this.faces[i][j] + " not found!");
|
|
var n = this.faceNormals[i] || new Vec3();
|
|
this.getFaceNormal(i, n);
|
|
n.negate(n);
|
|
this.faceNormals[i] = n;
|
|
var vertex = this.vertices[this.faces[i][0]];
|
|
if (n.dot(vertex) < 0) {
|
|
console.error(".faceNormals[" + i + "] = Vec3(" + n.toString() + ") looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule.");
|
|
for (var j = 0; j < this.faces[i].length; j++) console.warn(".vertices[" + this.faces[i][j] + "] = Vec3(" + this.vertices[this.faces[i][j]].toString() + ")");
|
|
}
|
|
}
|
|
};
|
|
var cb = new Vec3();
|
|
var ab = new Vec3();
|
|
ConvexPolyhedron.computeNormal = function(va, vb, vc, target) {
|
|
vb.vsub(va, ab);
|
|
vc.vsub(vb, cb);
|
|
cb.cross(ab, target);
|
|
target.isZero() || target.normalize();
|
|
};
|
|
ConvexPolyhedron.prototype.getFaceNormal = function(i, target) {
|
|
var f = this.faces[i];
|
|
var va = this.vertices[f[0]];
|
|
var vb = this.vertices[f[1]];
|
|
var vc = this.vertices[f[2]];
|
|
return ConvexPolyhedron.computeNormal(va, vb, vc, target);
|
|
};
|
|
var cah_WorldNormal = new Vec3();
|
|
ConvexPolyhedron.prototype.clipAgainstHull = function(posA, quatA, hullB, posB, quatB, separatingNormal, minDist, maxDist, result) {
|
|
var WorldNormal = cah_WorldNormal;
|
|
var hullA = this;
|
|
var curMaxDist = maxDist;
|
|
var closestFaceB = -1;
|
|
var dmax = -Number.MAX_VALUE;
|
|
for (var face = 0; face < hullB.faces.length; face++) {
|
|
WorldNormal.copy(hullB.faceNormals[face]);
|
|
quatB.vmult(WorldNormal, WorldNormal);
|
|
var d = WorldNormal.dot(separatingNormal);
|
|
if (d > dmax) {
|
|
dmax = d;
|
|
closestFaceB = face;
|
|
}
|
|
}
|
|
var worldVertsB1 = [];
|
|
var polyB = hullB.faces[closestFaceB];
|
|
var numVertices = polyB.length;
|
|
for (var e0 = 0; e0 < numVertices; e0++) {
|
|
var b = hullB.vertices[polyB[e0]];
|
|
var worldb = new Vec3();
|
|
worldb.copy(b);
|
|
quatB.vmult(worldb, worldb);
|
|
posB.vadd(worldb, worldb);
|
|
worldVertsB1.push(worldb);
|
|
}
|
|
closestFaceB >= 0 && this.clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result);
|
|
};
|
|
var fsa_faceANormalWS3 = new Vec3(), fsa_Worldnormal1 = new Vec3(), fsa_deltaC = new Vec3(), fsa_worldEdge0 = new Vec3(), fsa_worldEdge1 = new Vec3(), fsa_Cross = new Vec3();
|
|
ConvexPolyhedron.prototype.findSeparatingAxis = function(hullB, posA, quatA, posB, quatB, target, faceListA, faceListB) {
|
|
var faceANormalWS3 = fsa_faceANormalWS3, Worldnormal1 = fsa_Worldnormal1, deltaC = fsa_deltaC, worldEdge0 = fsa_worldEdge0, worldEdge1 = fsa_worldEdge1, Cross = fsa_Cross;
|
|
var dmin = Number.MAX_VALUE;
|
|
var hullA = this;
|
|
var curPlaneTests = 0;
|
|
if (hullA.uniqueAxes) for (var i = 0; i !== hullA.uniqueAxes.length; i++) {
|
|
quatA.vmult(hullA.uniqueAxes[i], faceANormalWS3);
|
|
var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
|
|
if (false === d) return false;
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(faceANormalWS3);
|
|
}
|
|
} else {
|
|
var numFacesA = faceListA ? faceListA.length : hullA.faces.length;
|
|
for (var i = 0; i < numFacesA; i++) {
|
|
var fi = faceListA ? faceListA[i] : i;
|
|
faceANormalWS3.copy(hullA.faceNormals[fi]);
|
|
quatA.vmult(faceANormalWS3, faceANormalWS3);
|
|
var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
|
|
if (false === d) return false;
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(faceANormalWS3);
|
|
}
|
|
}
|
|
}
|
|
if (hullB.uniqueAxes) for (var i = 0; i !== hullB.uniqueAxes.length; i++) {
|
|
quatB.vmult(hullB.uniqueAxes[i], Worldnormal1);
|
|
curPlaneTests++;
|
|
var d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB);
|
|
if (false === d) return false;
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(Worldnormal1);
|
|
}
|
|
} else {
|
|
var numFacesB = faceListB ? faceListB.length : hullB.faces.length;
|
|
for (var i = 0; i < numFacesB; i++) {
|
|
var fi = faceListB ? faceListB[i] : i;
|
|
Worldnormal1.copy(hullB.faceNormals[fi]);
|
|
quatB.vmult(Worldnormal1, Worldnormal1);
|
|
curPlaneTests++;
|
|
var d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB);
|
|
if (false === d) return false;
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
target.copy(Worldnormal1);
|
|
}
|
|
}
|
|
}
|
|
for (var e0 = 0; e0 !== hullA.uniqueEdges.length; e0++) {
|
|
quatA.vmult(hullA.uniqueEdges[e0], worldEdge0);
|
|
for (var e1 = 0; e1 !== hullB.uniqueEdges.length; e1++) {
|
|
quatB.vmult(hullB.uniqueEdges[e1], worldEdge1);
|
|
worldEdge0.cross(worldEdge1, Cross);
|
|
if (!Cross.almostZero()) {
|
|
Cross.normalize();
|
|
var dist = hullA.testSepAxis(Cross, hullB, posA, quatA, posB, quatB);
|
|
if (false === dist) return false;
|
|
if (dist < dmin) {
|
|
dmin = dist;
|
|
target.copy(Cross);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
posB.vsub(posA, deltaC);
|
|
deltaC.dot(target) > 0 && target.negate(target);
|
|
return true;
|
|
};
|
|
var maxminA = [], maxminB = [];
|
|
ConvexPolyhedron.prototype.testSepAxis = function(axis, hullB, posA, quatA, posB, quatB) {
|
|
var hullA = this;
|
|
ConvexPolyhedron.project(hullA, axis, posA, quatA, maxminA);
|
|
ConvexPolyhedron.project(hullB, axis, posB, quatB, maxminB);
|
|
var maxA = maxminA[0];
|
|
var minA = maxminA[1];
|
|
var maxB = maxminB[0];
|
|
var minB = maxminB[1];
|
|
if (maxA < minB || maxB < minA) return false;
|
|
var d0 = maxA - minB;
|
|
var d1 = maxB - minA;
|
|
var depth = d0 < d1 ? d0 : d1;
|
|
return depth;
|
|
};
|
|
var cli_aabbmin = new Vec3(), cli_aabbmax = new Vec3();
|
|
ConvexPolyhedron.prototype.calculateLocalInertia = function(mass, target) {
|
|
this.computeLocalAABB(cli_aabbmin, cli_aabbmax);
|
|
var x = cli_aabbmax.x - cli_aabbmin.x, y = cli_aabbmax.y - cli_aabbmin.y, z = cli_aabbmax.z - cli_aabbmin.z;
|
|
target.x = 1 / 12 * mass * (2 * y * 2 * y + 2 * z * 2 * z);
|
|
target.y = 1 / 12 * mass * (2 * x * 2 * x + 2 * z * 2 * z);
|
|
target.z = 1 / 12 * mass * (2 * y * 2 * y + 2 * x * 2 * x);
|
|
};
|
|
ConvexPolyhedron.prototype.getPlaneConstantOfFace = function(face_i) {
|
|
var f = this.faces[face_i];
|
|
var n = this.faceNormals[face_i];
|
|
var v = this.vertices[f[0]];
|
|
var c = -n.dot(v);
|
|
return c;
|
|
};
|
|
var cfah_faceANormalWS = new Vec3(), cfah_edge0 = new Vec3(), cfah_WorldEdge0 = new Vec3(), cfah_worldPlaneAnormal1 = new Vec3(), cfah_planeNormalWS1 = new Vec3(), cfah_worldA1 = new Vec3(), cfah_localPlaneNormal = new Vec3(), cfah_planeNormalWS = new Vec3();
|
|
ConvexPolyhedron.prototype.clipFaceAgainstHull = function(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result) {
|
|
var faceANormalWS = cfah_faceANormalWS, edge0 = cfah_edge0, WorldEdge0 = cfah_WorldEdge0, worldPlaneAnormal1 = cfah_worldPlaneAnormal1, planeNormalWS1 = cfah_planeNormalWS1, worldA1 = cfah_worldA1, localPlaneNormal = cfah_localPlaneNormal, planeNormalWS = cfah_planeNormalWS;
|
|
var hullA = this;
|
|
var worldVertsB2 = [];
|
|
var pVtxIn = worldVertsB1;
|
|
var pVtxOut = worldVertsB2;
|
|
var closestFaceA = -1;
|
|
var dmin = Number.MAX_VALUE;
|
|
for (var face = 0; face < hullA.faces.length; face++) {
|
|
faceANormalWS.copy(hullA.faceNormals[face]);
|
|
quatA.vmult(faceANormalWS, faceANormalWS);
|
|
var d = faceANormalWS.dot(separatingNormal);
|
|
if (d < dmin) {
|
|
dmin = d;
|
|
closestFaceA = face;
|
|
}
|
|
}
|
|
if (closestFaceA < 0) return;
|
|
var polyA = hullA.faces[closestFaceA];
|
|
polyA.connectedFaces = [];
|
|
for (var i = 0; i < hullA.faces.length; i++) for (var j = 0; j < hullA.faces[i].length; j++) -1 !== polyA.indexOf(hullA.faces[i][j]) && i !== closestFaceA && -1 === polyA.connectedFaces.indexOf(i) && polyA.connectedFaces.push(i);
|
|
var numContacts = pVtxIn.length;
|
|
var numVerticesA = polyA.length;
|
|
var res = [];
|
|
for (var e0 = 0; e0 < numVerticesA; e0++) {
|
|
var a = hullA.vertices[polyA[e0]];
|
|
var b = hullA.vertices[polyA[(e0 + 1) % numVerticesA]];
|
|
a.vsub(b, edge0);
|
|
WorldEdge0.copy(edge0);
|
|
quatA.vmult(WorldEdge0, WorldEdge0);
|
|
posA.vadd(WorldEdge0, WorldEdge0);
|
|
worldPlaneAnormal1.copy(this.faceNormals[closestFaceA]);
|
|
quatA.vmult(worldPlaneAnormal1, worldPlaneAnormal1);
|
|
posA.vadd(worldPlaneAnormal1, worldPlaneAnormal1);
|
|
WorldEdge0.cross(worldPlaneAnormal1, planeNormalWS1);
|
|
planeNormalWS1.negate(planeNormalWS1);
|
|
worldA1.copy(a);
|
|
quatA.vmult(worldA1, worldA1);
|
|
posA.vadd(worldA1, worldA1);
|
|
var planeEqWS1 = -worldA1.dot(planeNormalWS1);
|
|
var planeEqWS;
|
|
true;
|
|
var otherFace = polyA.connectedFaces[e0];
|
|
localPlaneNormal.copy(this.faceNormals[otherFace]);
|
|
var localPlaneEq = this.getPlaneConstantOfFace(otherFace);
|
|
planeNormalWS.copy(localPlaneNormal);
|
|
quatA.vmult(planeNormalWS, planeNormalWS);
|
|
var planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
|
|
this.clipFaceAgainstPlane(pVtxIn, pVtxOut, planeNormalWS, planeEqWS);
|
|
while (pVtxIn.length) pVtxIn.shift();
|
|
while (pVtxOut.length) pVtxIn.push(pVtxOut.shift());
|
|
}
|
|
localPlaneNormal.copy(this.faceNormals[closestFaceA]);
|
|
var localPlaneEq = this.getPlaneConstantOfFace(closestFaceA);
|
|
planeNormalWS.copy(localPlaneNormal);
|
|
quatA.vmult(planeNormalWS, planeNormalWS);
|
|
var planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
|
|
for (var i = 0; i < pVtxIn.length; i++) {
|
|
var depth = planeNormalWS.dot(pVtxIn[i]) + planeEqWS;
|
|
depth <= minDist && (depth = minDist);
|
|
if (depth <= maxDist) {
|
|
var point = pVtxIn[i];
|
|
if (depth <= 0) {
|
|
var p = {
|
|
point: point,
|
|
normal: planeNormalWS,
|
|
depth: depth
|
|
};
|
|
result.push(p);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
ConvexPolyhedron.prototype.clipFaceAgainstPlane = function(inVertices, outVertices, planeNormal, planeConstant) {
|
|
var n_dot_first, n_dot_last;
|
|
var numVerts = inVertices.length;
|
|
if (numVerts < 2) return outVertices;
|
|
var firstVertex = inVertices[inVertices.length - 1], lastVertex = inVertices[0];
|
|
n_dot_first = planeNormal.dot(firstVertex) + planeConstant;
|
|
for (var vi = 0; vi < numVerts; vi++) {
|
|
lastVertex = inVertices[vi];
|
|
n_dot_last = planeNormal.dot(lastVertex) + planeConstant;
|
|
if (n_dot_first < 0) if (n_dot_last < 0) {
|
|
var newv = new Vec3();
|
|
newv.copy(lastVertex);
|
|
outVertices.push(newv);
|
|
} else {
|
|
var newv = new Vec3();
|
|
firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv);
|
|
outVertices.push(newv);
|
|
} else if (n_dot_last < 0) {
|
|
var newv = new Vec3();
|
|
firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv);
|
|
outVertices.push(newv);
|
|
outVertices.push(lastVertex);
|
|
}
|
|
firstVertex = lastVertex;
|
|
n_dot_first = n_dot_last;
|
|
}
|
|
return outVertices;
|
|
};
|
|
ConvexPolyhedron.prototype.computeWorldVertices = function(position, quat) {
|
|
var N = this.vertices.length;
|
|
while (this.worldVertices.length < N) this.worldVertices.push(new Vec3());
|
|
var verts = this.vertices, worldVerts = this.worldVertices;
|
|
for (var i = 0; i !== N; i++) {
|
|
quat.vmult(verts[i], worldVerts[i]);
|
|
position.vadd(worldVerts[i], worldVerts[i]);
|
|
}
|
|
this.worldVerticesNeedsUpdate = false;
|
|
};
|
|
var computeLocalAABB_worldVert = new Vec3();
|
|
ConvexPolyhedron.prototype.computeLocalAABB = function(aabbmin, aabbmax) {
|
|
var n = this.vertices.length, vertices = this.vertices, worldVert = computeLocalAABB_worldVert;
|
|
aabbmin.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
|
|
aabbmax.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
|
|
for (var i = 0; i < n; i++) {
|
|
var v = vertices[i];
|
|
v.x < aabbmin.x ? aabbmin.x = v.x : v.x > aabbmax.x && (aabbmax.x = v.x);
|
|
v.y < aabbmin.y ? aabbmin.y = v.y : v.y > aabbmax.y && (aabbmax.y = v.y);
|
|
v.z < aabbmin.z ? aabbmin.z = v.z : v.z > aabbmax.z && (aabbmax.z = v.z);
|
|
}
|
|
};
|
|
ConvexPolyhedron.prototype.computeWorldFaceNormals = function(quat) {
|
|
var N = this.faceNormals.length;
|
|
while (this.worldFaceNormals.length < N) this.worldFaceNormals.push(new Vec3());
|
|
var normals = this.faceNormals, worldNormals = this.worldFaceNormals;
|
|
for (var i = 0; i !== N; i++) quat.vmult(normals[i], worldNormals[i]);
|
|
this.worldFaceNormalsNeedsUpdate = false;
|
|
};
|
|
ConvexPolyhedron.prototype.updateBoundingSphereRadius = function() {
|
|
var max2 = 0;
|
|
var verts = this.vertices;
|
|
for (var i = 0, N = verts.length; i !== N; i++) {
|
|
var norm2 = verts[i].norm2();
|
|
norm2 > max2 && (max2 = norm2);
|
|
}
|
|
this.boundingSphereRadius = Math.sqrt(max2);
|
|
};
|
|
var tempWorldVertex = new Vec3();
|
|
ConvexPolyhedron.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
var n = this.vertices.length, verts = this.vertices;
|
|
var minx, miny, minz, maxx, maxy, maxz;
|
|
for (var i = 0; i < n; i++) {
|
|
tempWorldVertex.copy(verts[i]);
|
|
quat.vmult(tempWorldVertex, tempWorldVertex);
|
|
pos.vadd(tempWorldVertex, tempWorldVertex);
|
|
var v = tempWorldVertex;
|
|
(v.x < minx || void 0 === minx) && (minx = v.x);
|
|
(v.x > maxx || void 0 === maxx) && (maxx = v.x);
|
|
(v.y < miny || void 0 === miny) && (miny = v.y);
|
|
(v.y > maxy || void 0 === maxy) && (maxy = v.y);
|
|
(v.z < minz || void 0 === minz) && (minz = v.z);
|
|
(v.z > maxz || void 0 === maxz) && (maxz = v.z);
|
|
}
|
|
min.set(minx, miny, minz);
|
|
max.set(maxx, maxy, maxz);
|
|
};
|
|
ConvexPolyhedron.prototype.volume = function() {
|
|
return 4 * Math.PI * this.boundingSphereRadius / 3;
|
|
};
|
|
ConvexPolyhedron.prototype.getAveragePointLocal = function(target) {
|
|
target = target || new Vec3();
|
|
var n = this.vertices.length, verts = this.vertices;
|
|
for (var i = 0; i < n; i++) target.vadd(verts[i], target);
|
|
target.mult(1 / n, target);
|
|
return target;
|
|
};
|
|
ConvexPolyhedron.prototype.transformAllPoints = function(offset, quat) {
|
|
var n = this.vertices.length, verts = this.vertices;
|
|
if (quat) {
|
|
for (var i = 0; i < n; i++) {
|
|
var v = verts[i];
|
|
quat.vmult(v, v);
|
|
}
|
|
for (var i = 0; i < this.faceNormals.length; i++) {
|
|
var v = this.faceNormals[i];
|
|
quat.vmult(v, v);
|
|
}
|
|
}
|
|
if (offset) for (var i = 0; i < n; i++) {
|
|
var v = verts[i];
|
|
v.vadd(offset, v);
|
|
}
|
|
};
|
|
var ConvexPolyhedron_pointIsInside = new Vec3();
|
|
var ConvexPolyhedron_vToP = new Vec3();
|
|
var ConvexPolyhedron_vToPointInside = new Vec3();
|
|
ConvexPolyhedron.prototype.pointIsInside = function(p) {
|
|
var n = this.vertices.length, verts = this.vertices, faces = this.faces, normals = this.faceNormals;
|
|
var positiveResult = null;
|
|
var N = this.faces.length;
|
|
var pointInside = ConvexPolyhedron_pointIsInside;
|
|
this.getAveragePointLocal(pointInside);
|
|
for (var i = 0; i < N; i++) {
|
|
var numVertices = this.faces[i].length;
|
|
var n = normals[i];
|
|
var v = verts[faces[i][0]];
|
|
var vToP = ConvexPolyhedron_vToP;
|
|
p.vsub(v, vToP);
|
|
var r1 = n.dot(vToP);
|
|
var vToPointInside = ConvexPolyhedron_vToPointInside;
|
|
pointInside.vsub(v, vToPointInside);
|
|
var r2 = n.dot(vToPointInside);
|
|
if (r1 < 0 && r2 > 0 || r1 > 0 && r2 < 0) return false;
|
|
}
|
|
return positiveResult ? 1 : -1;
|
|
};
|
|
var project_worldVertex = new Vec3();
|
|
var project_localAxis = new Vec3();
|
|
var project_localOrigin = new Vec3();
|
|
ConvexPolyhedron.project = function(hull, axis, pos, quat, result) {
|
|
var n = hull.vertices.length, worldVertex = project_worldVertex, localAxis = project_localAxis, max = 0, min = 0, localOrigin = project_localOrigin, vs = hull.vertices;
|
|
localOrigin.setZero();
|
|
Transform.vectorToLocalFrame(pos, quat, axis, localAxis);
|
|
Transform.pointToLocalFrame(pos, quat, localOrigin, localOrigin);
|
|
var add = localOrigin.dot(localAxis);
|
|
min = max = vs[0].dot(localAxis);
|
|
for (var i = 1; i < n; i++) {
|
|
var val = vs[i].dot(localAxis);
|
|
val > max && (max = val);
|
|
val < min && (min = val);
|
|
}
|
|
min -= add;
|
|
max -= add;
|
|
if (min > max) {
|
|
var temp = min;
|
|
min = max;
|
|
max = temp;
|
|
}
|
|
result[0] = max;
|
|
result[1] = min;
|
|
};
|
|
}, {
|
|
"../math/Quaternion": 30,
|
|
"../math/Transform": 31,
|
|
"../math/Vec3": 32,
|
|
"./Shape": 45
|
|
} ],
|
|
41: [ function(_dereq_, module, exports) {
|
|
module.exports = Cylinder;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var ConvexPolyhedron = _dereq_("./ConvexPolyhedron");
|
|
var CMath = _dereq_("../math/CMath");
|
|
function Cylinder(radiusTop, radiusBottom, height, numSegments, isDirY) {
|
|
if (isDirY) {
|
|
var N = numSegments, cos = CMath.cos, sin = CMath.sin;
|
|
var halfH = height / 2;
|
|
var vertices = [];
|
|
var indices = [];
|
|
var tf = [ 0 ];
|
|
var bf = [ 1 ];
|
|
var axes = [];
|
|
var theta = 2 * Math.PI / N;
|
|
for (var i = 0; i < N; i++) {
|
|
vertices.push(new Vec3(radiusTop * cos(theta * i), halfH, radiusTop * sin(theta * i)));
|
|
vertices.push(new Vec3(radiusTop * cos(theta * i), -halfH, radiusTop * sin(theta * i)));
|
|
if (i < N - 1) {
|
|
indices.push([ 2 * i + 2, 2 * i + 3, 2 * i + 1, 2 * i ]);
|
|
tf.push(2 * i + 2);
|
|
bf.push(2 * i + 3);
|
|
} else indices.push([ 0, 1, 2 * i + 1, 2 * i ]);
|
|
(N % 2 === 1 || i < N / 2) && axes.push(new Vec3(cos(theta * (i + .5)), 0, sin(theta * (i + .5))));
|
|
}
|
|
indices.push(bf);
|
|
var temp = [];
|
|
for (var i = 0; i < tf.length; i++) temp.push(tf[tf.length - i - 1]);
|
|
indices.push(temp);
|
|
axes.push(new Vec3(0, 1, 0));
|
|
ConvexPolyhedron.call(this, vertices, indices, axes);
|
|
return;
|
|
}
|
|
var N = numSegments, verts = [], axes = [], faces = [], bottomface = [], topface = [], cos = CMath.cos, sin = CMath.sin;
|
|
verts.push(new Vec3(radiusBottom * cos(0), radiusBottom * sin(0), .5 * -height));
|
|
bottomface.push(0);
|
|
verts.push(new Vec3(radiusTop * cos(0), radiusTop * sin(0), .5 * height));
|
|
topface.push(1);
|
|
for (var i = 0; i < N; i++) {
|
|
var theta = 2 * Math.PI / N * (i + 1);
|
|
var thetaN = 2 * Math.PI / N * (i + .5);
|
|
if (i < N - 1) {
|
|
verts.push(new Vec3(radiusBottom * cos(theta), radiusBottom * sin(theta), .5 * -height));
|
|
bottomface.push(2 * i + 2);
|
|
verts.push(new Vec3(radiusTop * cos(theta), radiusTop * sin(theta), .5 * height));
|
|
topface.push(2 * i + 3);
|
|
faces.push([ 2 * i + 2, 2 * i + 3, 2 * i + 1, 2 * i ]);
|
|
} else faces.push([ 0, 1, 2 * i + 1, 2 * i ]);
|
|
(N % 2 === 1 || i < N / 2) && axes.push(new Vec3(cos(thetaN), sin(thetaN), 0));
|
|
}
|
|
faces.push(topface);
|
|
axes.push(new Vec3(0, 0, 1));
|
|
var temp = [];
|
|
for (var i = 0; i < bottomface.length; i++) temp.push(bottomface[bottomface.length - i - 1]);
|
|
faces.push(temp);
|
|
ConvexPolyhedron.call(this, verts, faces, axes);
|
|
}
|
|
Cylinder.prototype = new ConvexPolyhedron();
|
|
}, {
|
|
"../math/CMath": 27,
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"./ConvexPolyhedron": 40,
|
|
"./Shape": 45
|
|
} ],
|
|
42: [ function(_dereq_, module, exports) {
|
|
var Shape = _dereq_("./Shape");
|
|
var ConvexPolyhedron = _dereq_("./ConvexPolyhedron");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Utils = _dereq_("../utils/Utils");
|
|
module.exports = Heightfield;
|
|
function Heightfield(data, options) {
|
|
options = Utils.defaults(options, {
|
|
maxValue: null,
|
|
minValue: null,
|
|
elementSize: 1
|
|
});
|
|
this.data = data;
|
|
this.maxValue = options.maxValue;
|
|
this.minValue = options.minValue;
|
|
this.elementSize = options.elementSize;
|
|
null === options.minValue && this.updateMinValue();
|
|
null === options.maxValue && this.updateMaxValue();
|
|
this.cacheEnabled = true;
|
|
Shape.call(this, {
|
|
type: Shape.types.HEIGHTFIELD
|
|
});
|
|
this.pillarConvex = new ConvexPolyhedron();
|
|
this.pillarOffset = new Vec3();
|
|
this.updateBoundingSphereRadius();
|
|
this._cachedPillars = {};
|
|
}
|
|
Heightfield.prototype = new Shape();
|
|
Heightfield.prototype.update = function() {
|
|
this._cachedPillars = {};
|
|
};
|
|
Heightfield.prototype.updateMinValue = function() {
|
|
var data = this.data;
|
|
var minValue = data[0][0];
|
|
for (var i = 0; i !== data.length; i++) for (var j = 0; j !== data[i].length; j++) {
|
|
var v = data[i][j];
|
|
v < minValue && (minValue = v);
|
|
}
|
|
this.minValue = minValue;
|
|
};
|
|
Heightfield.prototype.updateMaxValue = function() {
|
|
var data = this.data;
|
|
var maxValue = data[0][0];
|
|
for (var i = 0; i !== data.length; i++) for (var j = 0; j !== data[i].length; j++) {
|
|
var v = data[i][j];
|
|
v > maxValue && (maxValue = v);
|
|
}
|
|
this.maxValue = maxValue;
|
|
};
|
|
Heightfield.prototype.setHeightValueAtIndex = function(xi, yi, value) {
|
|
var data = this.data;
|
|
data[xi][yi] = value;
|
|
this.clearCachedConvexTrianglePillar(xi, yi, false);
|
|
if (xi > 0) {
|
|
this.clearCachedConvexTrianglePillar(xi - 1, yi, true);
|
|
this.clearCachedConvexTrianglePillar(xi - 1, yi, false);
|
|
}
|
|
if (yi > 0) {
|
|
this.clearCachedConvexTrianglePillar(xi, yi - 1, true);
|
|
this.clearCachedConvexTrianglePillar(xi, yi - 1, false);
|
|
}
|
|
yi > 0 && xi > 0 && this.clearCachedConvexTrianglePillar(xi - 1, yi - 1, true);
|
|
};
|
|
Heightfield.prototype.getRectMinMax = function(iMinX, iMinY, iMaxX, iMaxY, result) {
|
|
result = result || [];
|
|
var data = this.data, max = this.minValue;
|
|
for (var i = iMinX; i <= iMaxX; i++) for (var j = iMinY; j <= iMaxY; j++) {
|
|
var height = data[i][j];
|
|
height > max && (max = height);
|
|
}
|
|
result[0] = this.minValue;
|
|
result[1] = max;
|
|
};
|
|
Heightfield.prototype.getIndexOfPosition = function(x, y, result, clamp) {
|
|
var w = this.elementSize;
|
|
var data = this.data;
|
|
var xi = Math.floor(x / w);
|
|
var yi = Math.floor(y / w);
|
|
result[0] = xi;
|
|
result[1] = yi;
|
|
if (clamp) {
|
|
xi < 0 && (xi = 0);
|
|
yi < 0 && (yi = 0);
|
|
xi >= data.length - 1 && (xi = data.length - 1);
|
|
yi >= data[0].length - 1 && (yi = data[0].length - 1);
|
|
}
|
|
if (xi < 0 || yi < 0 || xi >= data.length - 1 || yi >= data[0].length - 1) return false;
|
|
return true;
|
|
};
|
|
var getHeightAt_idx = [];
|
|
var getHeightAt_weights = new Vec3();
|
|
var getHeightAt_a = new Vec3();
|
|
var getHeightAt_b = new Vec3();
|
|
var getHeightAt_c = new Vec3();
|
|
Heightfield.prototype.getTriangleAt = function(x, y, edgeClamp, a, b, c) {
|
|
var idx = getHeightAt_idx;
|
|
this.getIndexOfPosition(x, y, idx, edgeClamp);
|
|
var xi = idx[0];
|
|
var yi = idx[1];
|
|
var data = this.data;
|
|
if (edgeClamp) {
|
|
xi = Math.min(data.length - 2, Math.max(0, xi));
|
|
yi = Math.min(data[0].length - 2, Math.max(0, yi));
|
|
}
|
|
var elementSize = this.elementSize;
|
|
var lowerDist2 = Math.pow(x / elementSize - xi, 2) + Math.pow(y / elementSize - yi, 2);
|
|
var upperDist2 = Math.pow(x / elementSize - (xi + 1), 2) + Math.pow(y / elementSize - (yi + 1), 2);
|
|
var upper = lowerDist2 > upperDist2;
|
|
this.getTriangle(xi, yi, upper, a, b, c);
|
|
return upper;
|
|
};
|
|
var getNormalAt_a = new Vec3();
|
|
var getNormalAt_b = new Vec3();
|
|
var getNormalAt_c = new Vec3();
|
|
var getNormalAt_e0 = new Vec3();
|
|
var getNormalAt_e1 = new Vec3();
|
|
Heightfield.prototype.getNormalAt = function(x, y, edgeClamp, result) {
|
|
var a = getNormalAt_a;
|
|
var b = getNormalAt_b;
|
|
var c = getNormalAt_c;
|
|
var e0 = getNormalAt_e0;
|
|
var e1 = getNormalAt_e1;
|
|
this.getTriangleAt(x, y, edgeClamp, a, b, c);
|
|
b.vsub(a, e0);
|
|
c.vsub(a, e1);
|
|
e0.cross(e1, result);
|
|
result.normalize();
|
|
};
|
|
Heightfield.prototype.getAabbAtIndex = function(xi, yi, result) {
|
|
var data = this.data;
|
|
var elementSize = this.elementSize;
|
|
result.lowerBound.set(xi * elementSize, yi * elementSize, data[xi][yi]);
|
|
result.upperBound.set((xi + 1) * elementSize, (yi + 1) * elementSize, data[xi + 1][yi + 1]);
|
|
};
|
|
Heightfield.prototype.getHeightAt = function(x, y, edgeClamp) {
|
|
var data = this.data;
|
|
var a = getHeightAt_a;
|
|
var b = getHeightAt_b;
|
|
var c = getHeightAt_c;
|
|
var idx = getHeightAt_idx;
|
|
this.getIndexOfPosition(x, y, idx, edgeClamp);
|
|
var xi = idx[0];
|
|
var yi = idx[1];
|
|
if (edgeClamp) {
|
|
xi = Math.min(data.length - 2, Math.max(0, xi));
|
|
yi = Math.min(data[0].length - 2, Math.max(0, yi));
|
|
}
|
|
var upper = this.getTriangleAt(x, y, edgeClamp, a, b, c);
|
|
barycentricWeights(x, y, a.x, a.y, b.x, b.y, c.x, c.y, getHeightAt_weights);
|
|
var w = getHeightAt_weights;
|
|
return upper ? data[xi + 1][yi + 1] * w.x + data[xi][yi + 1] * w.y + data[xi + 1][yi] * w.z : data[xi][yi] * w.x + data[xi + 1][yi] * w.y + data[xi][yi + 1] * w.z;
|
|
};
|
|
function barycentricWeights(x, y, ax, ay, bx, by, cx, cy, result) {
|
|
result.x = ((by - cy) * (x - cx) + (cx - bx) * (y - cy)) / ((by - cy) * (ax - cx) + (cx - bx) * (ay - cy));
|
|
result.y = ((cy - ay) * (x - cx) + (ax - cx) * (y - cy)) / ((by - cy) * (ax - cx) + (cx - bx) * (ay - cy));
|
|
result.z = 1 - result.x - result.y;
|
|
}
|
|
Heightfield.prototype.getCacheConvexTrianglePillarKey = function(xi, yi, getUpperTriangle) {
|
|
return xi + "_" + yi + "_" + (getUpperTriangle ? 1 : 0);
|
|
};
|
|
Heightfield.prototype.getCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle) {
|
|
return this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)];
|
|
};
|
|
Heightfield.prototype.setCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle, convex, offset) {
|
|
this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)] = {
|
|
convex: convex,
|
|
offset: offset
|
|
};
|
|
};
|
|
Heightfield.prototype.clearCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle) {
|
|
delete this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)];
|
|
};
|
|
Heightfield.prototype.getTriangle = function(xi, yi, upper, a, b, c) {
|
|
var data = this.data;
|
|
var elementSize = this.elementSize;
|
|
if (upper) {
|
|
a.set((xi + 1) * elementSize, (yi + 1) * elementSize, data[xi + 1][yi + 1]);
|
|
b.set(xi * elementSize, (yi + 1) * elementSize, data[xi][yi + 1]);
|
|
c.set((xi + 1) * elementSize, yi * elementSize, data[xi + 1][yi]);
|
|
} else {
|
|
a.set(xi * elementSize, yi * elementSize, data[xi][yi]);
|
|
b.set((xi + 1) * elementSize, yi * elementSize, data[xi + 1][yi]);
|
|
c.set(xi * elementSize, (yi + 1) * elementSize, data[xi][yi + 1]);
|
|
}
|
|
};
|
|
Heightfield.prototype.getConvexTrianglePillar = function(xi, yi, getUpperTriangle) {
|
|
var result = this.pillarConvex;
|
|
var offsetResult = this.pillarOffset;
|
|
if (this.cacheEnabled) {
|
|
var data = this.getCachedConvexTrianglePillar(xi, yi, getUpperTriangle);
|
|
if (data) {
|
|
this.pillarConvex = data.convex;
|
|
this.pillarOffset = data.offset;
|
|
return;
|
|
}
|
|
result = new ConvexPolyhedron();
|
|
offsetResult = new Vec3();
|
|
this.pillarConvex = result;
|
|
this.pillarOffset = offsetResult;
|
|
}
|
|
var data = this.data;
|
|
var elementSize = this.elementSize;
|
|
var faces = result.faces;
|
|
result.vertices.length = 6;
|
|
for (var i = 0; i < 6; i++) result.vertices[i] || (result.vertices[i] = new Vec3());
|
|
faces.length = 5;
|
|
for (var i = 0; i < 5; i++) faces[i] || (faces[i] = []);
|
|
var verts = result.vertices;
|
|
var h = (Math.min(data[xi][yi], data[xi + 1][yi], data[xi][yi + 1], data[xi + 1][yi + 1]) - this.minValue) / 2 + this.minValue;
|
|
if (getUpperTriangle) {
|
|
offsetResult.set((xi + .75) * elementSize, (yi + .75) * elementSize, h);
|
|
verts[0].set(.25 * elementSize, .25 * elementSize, data[xi + 1][yi + 1] - h);
|
|
verts[1].set(-.75 * elementSize, .25 * elementSize, data[xi][yi + 1] - h);
|
|
verts[2].set(.25 * elementSize, -.75 * elementSize, data[xi + 1][yi] - h);
|
|
verts[3].set(.25 * elementSize, .25 * elementSize, -h - 1);
|
|
verts[4].set(-.75 * elementSize, .25 * elementSize, -h - 1);
|
|
verts[5].set(.25 * elementSize, -.75 * elementSize, -h - 1);
|
|
faces[0][0] = 0;
|
|
faces[0][1] = 1;
|
|
faces[0][2] = 2;
|
|
faces[1][0] = 5;
|
|
faces[1][1] = 4;
|
|
faces[1][2] = 3;
|
|
faces[2][0] = 2;
|
|
faces[2][1] = 5;
|
|
faces[2][2] = 3;
|
|
faces[2][3] = 0;
|
|
faces[3][0] = 3;
|
|
faces[3][1] = 4;
|
|
faces[3][2] = 1;
|
|
faces[3][3] = 0;
|
|
faces[4][0] = 1;
|
|
faces[4][1] = 4;
|
|
faces[4][2] = 5;
|
|
faces[4][3] = 2;
|
|
} else {
|
|
offsetResult.set((xi + .25) * elementSize, (yi + .25) * elementSize, h);
|
|
verts[0].set(-.25 * elementSize, -.25 * elementSize, data[xi][yi] - h);
|
|
verts[1].set(.75 * elementSize, -.25 * elementSize, data[xi + 1][yi] - h);
|
|
verts[2].set(-.25 * elementSize, .75 * elementSize, data[xi][yi + 1] - h);
|
|
verts[3].set(-.25 * elementSize, -.25 * elementSize, -h - 1);
|
|
verts[4].set(.75 * elementSize, -.25 * elementSize, -h - 1);
|
|
verts[5].set(-.25 * elementSize, .75 * elementSize, -h - 1);
|
|
faces[0][0] = 0;
|
|
faces[0][1] = 1;
|
|
faces[0][2] = 2;
|
|
faces[1][0] = 5;
|
|
faces[1][1] = 4;
|
|
faces[1][2] = 3;
|
|
faces[2][0] = 0;
|
|
faces[2][1] = 2;
|
|
faces[2][2] = 5;
|
|
faces[2][3] = 3;
|
|
faces[3][0] = 1;
|
|
faces[3][1] = 0;
|
|
faces[3][2] = 3;
|
|
faces[3][3] = 4;
|
|
faces[4][0] = 4;
|
|
faces[4][1] = 5;
|
|
faces[4][2] = 2;
|
|
faces[4][3] = 1;
|
|
}
|
|
result.computeNormals();
|
|
result.computeEdges();
|
|
result.updateBoundingSphereRadius();
|
|
this.setCachedConvexTrianglePillar(xi, yi, getUpperTriangle, result, offsetResult);
|
|
};
|
|
Heightfield.prototype.calculateLocalInertia = function(mass, target) {
|
|
target = target || new Vec3();
|
|
target.set(0, 0, 0);
|
|
return target;
|
|
};
|
|
Heightfield.prototype.volume = function() {
|
|
return Number.MAX_VALUE;
|
|
};
|
|
Heightfield.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
min.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
|
|
max.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
|
|
};
|
|
Heightfield.prototype.updateBoundingSphereRadius = function() {
|
|
var data = this.data, s = this.elementSize;
|
|
this.boundingSphereRadius = new Vec3(data.length * s, data[0].length * s, Math.max(Math.abs(this.maxValue), Math.abs(this.minValue))).norm();
|
|
};
|
|
Heightfield.prototype.setHeightsFromImage = function(image, scale) {
|
|
var canvas = document.createElement("canvas");
|
|
canvas.width = image.width;
|
|
canvas.height = image.height;
|
|
var context = canvas.getContext("2d");
|
|
context.drawImage(image, 0, 0);
|
|
var imageData = context.getImageData(0, 0, image.width, image.height);
|
|
var matrix = this.data;
|
|
matrix.length = 0;
|
|
this.elementSize = Math.abs(scale.x) / imageData.width;
|
|
for (var i = 0; i < imageData.height; i++) {
|
|
var row = [];
|
|
for (var j = 0; j < imageData.width; j++) {
|
|
var a = imageData.data[4 * (i * imageData.height + j)];
|
|
var b = imageData.data[4 * (i * imageData.height + j) + 1];
|
|
var c = imageData.data[4 * (i * imageData.height + j) + 2];
|
|
var height = (a + b + c) / 4 / 255 * scale.z;
|
|
scale.x < 0 ? row.push(height) : row.unshift(height);
|
|
}
|
|
scale.y < 0 ? matrix.unshift(row) : matrix.push(row);
|
|
}
|
|
this.updateMaxValue();
|
|
this.updateMinValue();
|
|
this.update();
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"../utils/Utils": 55,
|
|
"./ConvexPolyhedron": 40,
|
|
"./Shape": 45
|
|
} ],
|
|
43: [ function(_dereq_, module, exports) {
|
|
module.exports = Particle;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function Particle() {
|
|
Shape.call(this, {
|
|
type: Shape.types.PARTICLE
|
|
});
|
|
}
|
|
Particle.prototype = new Shape();
|
|
Particle.prototype.constructor = Particle;
|
|
Particle.prototype.calculateLocalInertia = function(mass, target) {
|
|
target = target || new Vec3();
|
|
target.set(0, 0, 0);
|
|
return target;
|
|
};
|
|
Particle.prototype.volume = function() {
|
|
return 0;
|
|
};
|
|
Particle.prototype.updateBoundingSphereRadius = function() {
|
|
this.boundingSphereRadius = 0;
|
|
};
|
|
Particle.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
min.copy(pos);
|
|
max.copy(pos);
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"./Shape": 45
|
|
} ],
|
|
44: [ function(_dereq_, module, exports) {
|
|
module.exports = Plane;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function Plane() {
|
|
Shape.call(this, {
|
|
type: Shape.types.PLANE
|
|
});
|
|
this.worldNormal = new Vec3();
|
|
this.worldNormalNeedsUpdate = true;
|
|
this.boundingSphereRadius = Number.MAX_VALUE;
|
|
}
|
|
Plane.prototype = new Shape();
|
|
Plane.prototype.constructor = Plane;
|
|
Plane.prototype.computeWorldNormal = function(quat) {
|
|
var n = this.worldNormal;
|
|
n.set(0, 0, 1);
|
|
quat.vmult(n, n);
|
|
this.worldNormalNeedsUpdate = false;
|
|
};
|
|
Plane.prototype.calculateLocalInertia = function(mass, target) {
|
|
target = target || new Vec3();
|
|
return target;
|
|
};
|
|
Plane.prototype.volume = function() {
|
|
return Number.MAX_VALUE;
|
|
};
|
|
var tempNormal = new Vec3();
|
|
Plane.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
tempNormal.set(0, 0, 1);
|
|
quat.vmult(tempNormal, tempNormal);
|
|
var maxVal = Number.MAX_VALUE;
|
|
min.set(-maxVal, -maxVal, -maxVal);
|
|
max.set(maxVal, maxVal, maxVal);
|
|
1 === tempNormal.x && (max.x = pos.x);
|
|
1 === tempNormal.y && (max.y = pos.y);
|
|
1 === tempNormal.z && (max.z = pos.z);
|
|
-1 === tempNormal.x && (min.x = pos.x);
|
|
-1 === tempNormal.y && (min.y = pos.y);
|
|
-1 === tempNormal.z && (min.z = pos.z);
|
|
};
|
|
Plane.prototype.updateBoundingSphereRadius = function() {
|
|
this.boundingSphereRadius = Number.MAX_VALUE;
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"./Shape": 45
|
|
} ],
|
|
45: [ function(_dereq_, module, exports) {
|
|
module.exports = Shape;
|
|
var EventTarget = _dereq_("../utils/EventTarget");
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Material = _dereq_("../material/Material");
|
|
function Shape(options) {
|
|
options = options || {};
|
|
EventTarget.apply(this);
|
|
this.id = Shape.idCounter++;
|
|
this.type = options.type || 0;
|
|
this.boundingSphereRadius = 0;
|
|
this.collisionResponse = !options.collisionResponse || options.collisionResponse;
|
|
this.collisionFilterGroup = void 0 !== options.collisionFilterGroup ? options.collisionFilterGroup : 1;
|
|
this.collisionFilterMask = void 0 !== options.collisionFilterMask ? options.collisionFilterMask : -1;
|
|
this.material = options.material ? options.material : null;
|
|
this.body = null;
|
|
}
|
|
Shape.prototype = new EventTarget();
|
|
Shape.prototype.constructor = Shape;
|
|
Shape.prototype.updateBoundingSphereRadius = function() {
|
|
throw "computeBoundingSphereRadius() not implemented for shape type " + this.type;
|
|
};
|
|
Shape.prototype.volume = function() {
|
|
throw "volume() not implemented for shape type " + this.type;
|
|
};
|
|
Shape.prototype.calculateLocalInertia = function(mass, target) {
|
|
throw "calculateLocalInertia() not implemented for shape type " + this.type;
|
|
};
|
|
Shape.idCounter = 0;
|
|
Shape.types = {
|
|
SPHERE: 1,
|
|
PLANE: 2,
|
|
BOX: 4,
|
|
COMPOUND: 8,
|
|
CONVEXPOLYHEDRON: 16,
|
|
HEIGHTFIELD: 32,
|
|
PARTICLE: 64,
|
|
CYLINDER: 128,
|
|
TRIMESH: 256
|
|
};
|
|
}, {
|
|
"../material/Material": 26,
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../utils/EventTarget": 51,
|
|
"./Shape": 45
|
|
} ],
|
|
46: [ function(_dereq_, module, exports) {
|
|
module.exports = Sphere;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
function Sphere(radius) {
|
|
Shape.call(this, {
|
|
type: Shape.types.SPHERE
|
|
});
|
|
this.radius = void 0 !== radius ? radius : 1;
|
|
if (this.radius < 0) throw new Error("The sphere radius cannot be negative.");
|
|
this.updateBoundingSphereRadius();
|
|
}
|
|
Sphere.prototype = new Shape();
|
|
Sphere.prototype.constructor = Sphere;
|
|
Sphere.prototype.calculateLocalInertia = function(mass, target) {
|
|
target = target || new Vec3();
|
|
var I = 2 * mass * this.radius * this.radius / 5;
|
|
target.x = I;
|
|
target.y = I;
|
|
target.z = I;
|
|
return target;
|
|
};
|
|
Sphere.prototype.volume = function() {
|
|
return 4 * Math.PI * this.radius / 3;
|
|
};
|
|
Sphere.prototype.updateBoundingSphereRadius = function() {
|
|
this.boundingSphereRadius = this.radius;
|
|
};
|
|
Sphere.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
var r = this.radius;
|
|
var axes = [ "x", "y", "z" ];
|
|
for (var i = 0; i < axes.length; i++) {
|
|
var ax = axes[i];
|
|
min[ax] = pos[ax] - r;
|
|
max[ax] = pos[ax] + r;
|
|
}
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"./Shape": 45
|
|
} ],
|
|
47: [ function(_dereq_, module, exports) {
|
|
module.exports = Trimesh;
|
|
var Shape = _dereq_("./Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Transform = _dereq_("../math/Transform");
|
|
var AABB = _dereq_("../collision/AABB");
|
|
var Octree = _dereq_("../utils/Octree");
|
|
var CMath = _dereq_("../math/CMath");
|
|
function Trimesh(vertices, indices) {
|
|
Shape.call(this, {
|
|
type: Shape.types.TRIMESH
|
|
});
|
|
this.vertices = new Float32Array(vertices);
|
|
this.indices = new Int16Array(indices);
|
|
this.normals = new Float32Array(indices.length);
|
|
this.aabb = new AABB();
|
|
this.edges = null;
|
|
this.scale = new Vec3(1, 1, 1);
|
|
this.tree = new Octree();
|
|
this.updateEdges();
|
|
this.updateNormals();
|
|
this.updateAABB();
|
|
this.updateBoundingSphereRadius();
|
|
this.updateTree();
|
|
}
|
|
Trimesh.prototype = new Shape();
|
|
Trimesh.prototype.constructor = Trimesh;
|
|
var computeNormals_n = new Vec3();
|
|
Trimesh.prototype.updateTree = function() {
|
|
var tree = this.tree;
|
|
tree.reset();
|
|
tree.aabb.copy(this.aabb);
|
|
var scale = this.scale;
|
|
tree.aabb.lowerBound.x *= 1 / scale.x;
|
|
tree.aabb.lowerBound.y *= 1 / scale.y;
|
|
tree.aabb.lowerBound.z *= 1 / scale.z;
|
|
tree.aabb.upperBound.x *= 1 / scale.x;
|
|
tree.aabb.upperBound.y *= 1 / scale.y;
|
|
tree.aabb.upperBound.z *= 1 / scale.z;
|
|
var triangleAABB = new AABB();
|
|
var a = new Vec3();
|
|
var b = new Vec3();
|
|
var c = new Vec3();
|
|
var points = [ a, b, c ];
|
|
for (var i = 0; i < this.indices.length / 3; i++) {
|
|
var i3 = 3 * i;
|
|
this._getUnscaledVertex(this.indices[i3], a);
|
|
this._getUnscaledVertex(this.indices[i3 + 1], b);
|
|
this._getUnscaledVertex(this.indices[i3 + 2], c);
|
|
triangleAABB.setFromPoints(points);
|
|
tree.insert(triangleAABB, i);
|
|
}
|
|
tree.removeEmptyNodes();
|
|
};
|
|
var unscaledAABB = new AABB();
|
|
Trimesh.prototype.getTrianglesInAABB = function(aabb, result) {
|
|
unscaledAABB.copy(aabb);
|
|
var scale = this.scale;
|
|
var isx = scale.x;
|
|
var isy = scale.y;
|
|
var isz = scale.z;
|
|
var l = unscaledAABB.lowerBound;
|
|
var u = unscaledAABB.upperBound;
|
|
l.x /= isx;
|
|
l.y /= isy;
|
|
l.z /= isz;
|
|
u.x /= isx;
|
|
u.y /= isy;
|
|
u.z /= isz;
|
|
return this.tree.aabbQuery(unscaledAABB, result);
|
|
};
|
|
Trimesh.prototype.setScale = function(scale) {
|
|
var wasUniform = this.scale.x === this.scale.y === this.scale.z;
|
|
var isUniform = scale.x === scale.y === scale.z;
|
|
wasUniform && isUniform || this.updateNormals();
|
|
this.scale.copy(scale);
|
|
this.updateAABB();
|
|
this.updateBoundingSphereRadius();
|
|
};
|
|
Trimesh.prototype.updateNormals = function() {
|
|
var n = computeNormals_n;
|
|
var normals = this.normals;
|
|
for (var i = 0; i < this.indices.length / 3; i++) {
|
|
var i3 = 3 * i;
|
|
var a = this.indices[i3], b = this.indices[i3 + 1], c = this.indices[i3 + 2];
|
|
this.getVertex(a, va);
|
|
this.getVertex(b, vb);
|
|
this.getVertex(c, vc);
|
|
Trimesh.computeNormal(vb, va, vc, n);
|
|
normals[i3] = n.x;
|
|
normals[i3 + 1] = n.y;
|
|
normals[i3 + 2] = n.z;
|
|
}
|
|
};
|
|
Trimesh.prototype.updateEdges = function() {
|
|
var edges = {};
|
|
var add = function add(indexA, indexB) {
|
|
var key = a < b ? a + "_" + b : b + "_" + a;
|
|
edges[key] = true;
|
|
};
|
|
for (var i = 0; i < this.indices.length / 3; i++) {
|
|
var i3 = 3 * i;
|
|
var a = this.indices[i3], b = this.indices[i3 + 1], c = this.indices[i3 + 2];
|
|
add(a, b);
|
|
add(b, c);
|
|
add(c, a);
|
|
}
|
|
var keys = Object.keys(edges);
|
|
this.edges = new Int16Array(2 * keys.length);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var indices = keys[i].split("_");
|
|
this.edges[2 * i] = parseInt(indices[0], 10);
|
|
this.edges[2 * i + 1] = parseInt(indices[1], 10);
|
|
}
|
|
};
|
|
Trimesh.prototype.getEdgeVertex = function(edgeIndex, firstOrSecond, vertexStore) {
|
|
var vertexIndex = this.edges[2 * edgeIndex + (firstOrSecond ? 1 : 0)];
|
|
this.getVertex(vertexIndex, vertexStore);
|
|
};
|
|
var getEdgeVector_va = new Vec3();
|
|
var getEdgeVector_vb = new Vec3();
|
|
Trimesh.prototype.getEdgeVector = function(edgeIndex, vectorStore) {
|
|
var va = getEdgeVector_va;
|
|
var vb = getEdgeVector_vb;
|
|
this.getEdgeVertex(edgeIndex, 0, va);
|
|
this.getEdgeVertex(edgeIndex, 1, vb);
|
|
vb.vsub(va, vectorStore);
|
|
};
|
|
var cb = new Vec3();
|
|
var ab = new Vec3();
|
|
Trimesh.computeNormal = function(va, vb, vc, target) {
|
|
vb.vsub(va, ab);
|
|
vc.vsub(vb, cb);
|
|
cb.cross(ab, target);
|
|
target.isZero() || target.normalize();
|
|
};
|
|
var va = new Vec3();
|
|
var vb = new Vec3();
|
|
var vc = new Vec3();
|
|
Trimesh.prototype.getVertex = function(i, out) {
|
|
var scale = this.scale;
|
|
this._getUnscaledVertex(i, out);
|
|
out.x *= scale.x;
|
|
out.y *= scale.y;
|
|
out.z *= scale.z;
|
|
return out;
|
|
};
|
|
Trimesh.prototype._getUnscaledVertex = function(i, out) {
|
|
var i3 = 3 * i;
|
|
var vertices = this.vertices;
|
|
return out.set(vertices[i3], vertices[i3 + 1], vertices[i3 + 2]);
|
|
};
|
|
Trimesh.prototype.getWorldVertex = function(i, pos, quat, out) {
|
|
this.getVertex(i, out);
|
|
Transform.pointToWorldFrame(pos, quat, out, out);
|
|
return out;
|
|
};
|
|
Trimesh.prototype.getTriangleVertices = function(i, a, b, c) {
|
|
var i3 = 3 * i;
|
|
this.getVertex(this.indices[i3], a);
|
|
this.getVertex(this.indices[i3 + 1], b);
|
|
this.getVertex(this.indices[i3 + 2], c);
|
|
};
|
|
Trimesh.prototype.getNormal = function(i, target) {
|
|
var i3 = 3 * i;
|
|
return target.set(this.normals[i3], this.normals[i3 + 1], this.normals[i3 + 2]);
|
|
};
|
|
var cli_aabb = new AABB();
|
|
Trimesh.prototype.calculateLocalInertia = function(mass, target) {
|
|
this.computeLocalAABB(cli_aabb);
|
|
var x = cli_aabb.upperBound.x - cli_aabb.lowerBound.x, y = cli_aabb.upperBound.y - cli_aabb.lowerBound.y, z = cli_aabb.upperBound.z - cli_aabb.lowerBound.z;
|
|
return target.set(1 / 12 * mass * (2 * y * 2 * y + 2 * z * 2 * z), 1 / 12 * mass * (2 * x * 2 * x + 2 * z * 2 * z), 1 / 12 * mass * (2 * y * 2 * y + 2 * x * 2 * x));
|
|
};
|
|
var computeLocalAABB_worldVert = new Vec3();
|
|
Trimesh.prototype.computeLocalAABB = function(aabb) {
|
|
var l = aabb.lowerBound, u = aabb.upperBound, n = this.vertices.length, vertices = this.vertices, v = computeLocalAABB_worldVert;
|
|
this.getVertex(0, v);
|
|
l.copy(v);
|
|
u.copy(v);
|
|
for (var i = 0; i !== n; i++) {
|
|
this.getVertex(i, v);
|
|
v.x < l.x ? l.x = v.x : v.x > u.x && (u.x = v.x);
|
|
v.y < l.y ? l.y = v.y : v.y > u.y && (u.y = v.y);
|
|
v.z < l.z ? l.z = v.z : v.z > u.z && (u.z = v.z);
|
|
}
|
|
};
|
|
Trimesh.prototype.updateAABB = function() {
|
|
this.computeLocalAABB(this.aabb);
|
|
};
|
|
Trimesh.prototype.updateBoundingSphereRadius = function() {
|
|
var max2 = 0;
|
|
var vertices = this.vertices;
|
|
var v = new Vec3();
|
|
for (var i = 0, N = vertices.length / 3; i !== N; i++) {
|
|
this.getVertex(i, v);
|
|
var norm2 = v.norm2();
|
|
norm2 > max2 && (max2 = norm2);
|
|
}
|
|
this.boundingSphereRadius = Math.sqrt(max2);
|
|
};
|
|
var tempWorldVertex = new Vec3();
|
|
var calculateWorldAABB_frame = new Transform();
|
|
var calculateWorldAABB_aabb = new AABB();
|
|
Trimesh.prototype.calculateWorldAABB = function(pos, quat, min, max) {
|
|
var frame = calculateWorldAABB_frame;
|
|
var result = calculateWorldAABB_aabb;
|
|
frame.position = pos;
|
|
frame.quaternion = quat;
|
|
this.aabb.toWorldFrame(frame, result);
|
|
min.copy(result.lowerBound);
|
|
max.copy(result.upperBound);
|
|
};
|
|
Trimesh.prototype.volume = function() {
|
|
return 4 * Math.PI * this.boundingSphereRadius / 3;
|
|
};
|
|
Trimesh.createTorus = function(radius, tube, radialSegments, tubularSegments, arc) {
|
|
radius = radius || 1;
|
|
tube = tube || .5;
|
|
radialSegments = radialSegments || 8;
|
|
tubularSegments = tubularSegments || 6;
|
|
arc = arc || 2 * Math.PI;
|
|
var vertices = [];
|
|
var indices = [];
|
|
for (var j = 0; j <= radialSegments; j++) for (var i = 0; i <= tubularSegments; i++) {
|
|
var u = i / tubularSegments * arc;
|
|
var v = j / radialSegments * Math.PI * 2;
|
|
var x = (radius + tube * CMath.cos(v)) * CMath.cos(u);
|
|
var y = (radius + tube * CMath.cos(v)) * CMath.sin(u);
|
|
var z = tube * CMath.sin(v);
|
|
vertices.push(x, y, z);
|
|
}
|
|
for (var j = 1; j <= radialSegments; j++) for (var i = 1; i <= tubularSegments; i++) {
|
|
var a = (tubularSegments + 1) * j + i - 1;
|
|
var b = (tubularSegments + 1) * (j - 1) + i - 1;
|
|
var c = (tubularSegments + 1) * (j - 1) + i;
|
|
var d = (tubularSegments + 1) * j + i;
|
|
indices.push(a, b, d);
|
|
indices.push(b, c, d);
|
|
}
|
|
return new Trimesh(vertices, indices);
|
|
};
|
|
}, {
|
|
"../collision/AABB": 3,
|
|
"../math/CMath": 27,
|
|
"../math/Quaternion": 30,
|
|
"../math/Transform": 31,
|
|
"../math/Vec3": 32,
|
|
"../utils/Octree": 52,
|
|
"./Shape": 45
|
|
} ],
|
|
48: [ function(_dereq_, module, exports) {
|
|
module.exports = GSSolver;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Solver = _dereq_("./Solver");
|
|
function GSSolver() {
|
|
Solver.call(this);
|
|
this.iterations = 10;
|
|
this.tolerance = 1e-7;
|
|
}
|
|
GSSolver.prototype = new Solver();
|
|
var GSSolver_solve_lambda = [];
|
|
var GSSolver_solve_invCs = [];
|
|
var GSSolver_solve_Bs = [];
|
|
GSSolver.prototype.solve = function(dt, world) {
|
|
var iter = 0, maxIter = this.iterations, tolSquared = this.tolerance * this.tolerance, equations = this.equations, Neq = equations.length, bodies = world.bodies, Nbodies = bodies.length, h = dt, q, B, invC, deltalambda, deltalambdaTot, GWlambda, lambdaj;
|
|
if (0 !== Neq) for (var i = 0; i !== Nbodies; i++) bodies[i].updateSolveMassProperties();
|
|
var invCs = GSSolver_solve_invCs, Bs = GSSolver_solve_Bs, lambda = GSSolver_solve_lambda;
|
|
invCs.length = Neq;
|
|
Bs.length = Neq;
|
|
lambda.length = Neq;
|
|
for (var i = 0; i !== Neq; i++) {
|
|
var c = equations[i];
|
|
lambda[i] = 0;
|
|
Bs[i] = c.computeB(h);
|
|
invCs[i] = 1 / c.computeC();
|
|
}
|
|
if (0 !== Neq) {
|
|
for (var i = 0; i !== Nbodies; i++) {
|
|
var b = bodies[i], vlambda = b.vlambda, wlambda = b.wlambda;
|
|
vlambda.set(0, 0, 0);
|
|
wlambda.set(0, 0, 0);
|
|
}
|
|
for (iter = 0; iter !== maxIter; iter++) {
|
|
deltalambdaTot = 0;
|
|
for (var j = 0; j !== Neq; j++) {
|
|
var c = equations[j];
|
|
B = Bs[j];
|
|
invC = invCs[j];
|
|
lambdaj = lambda[j];
|
|
GWlambda = c.computeGWlambda();
|
|
deltalambda = invC * (B - GWlambda - c.eps * lambdaj);
|
|
lambdaj + deltalambda < c.minForce ? deltalambda = c.minForce - lambdaj : lambdaj + deltalambda > c.maxForce && (deltalambda = c.maxForce - lambdaj);
|
|
lambda[j] += deltalambda;
|
|
deltalambdaTot += deltalambda > 0 ? deltalambda : -deltalambda;
|
|
c.addToWlambda(deltalambda);
|
|
}
|
|
if (deltalambdaTot * deltalambdaTot < tolSquared) break;
|
|
}
|
|
for (var i = 0; i !== Nbodies; i++) {
|
|
var b = bodies[i], v = b.velocity, w = b.angularVelocity;
|
|
b.vlambda.vmul(b.linearFactor, b.vlambda);
|
|
v.vadd(b.vlambda, v);
|
|
b.wlambda.vmul(b.angularFactor, b.wlambda);
|
|
w.vadd(b.wlambda, w);
|
|
}
|
|
var l = equations.length;
|
|
var invDt = 1 / h;
|
|
while (l--) equations[l].multiplier = lambda[l] * invDt;
|
|
}
|
|
return iter;
|
|
};
|
|
}, {
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"./Solver": 49
|
|
} ],
|
|
49: [ function(_dereq_, module, exports) {
|
|
module.exports = Solver;
|
|
function Solver() {
|
|
this.equations = [];
|
|
}
|
|
Solver.prototype.solve = function(dt, world) {
|
|
return 0;
|
|
};
|
|
Solver.prototype.addEquation = function(eq) {
|
|
eq.enabled && this.equations.push(eq);
|
|
};
|
|
Solver.prototype.removeEquation = function(eq) {
|
|
var eqs = this.equations;
|
|
var i = eqs.indexOf(eq);
|
|
-1 !== i && eqs.splice(i, 1);
|
|
};
|
|
Solver.prototype.removeAllEquations = function() {
|
|
this.equations.length = 0;
|
|
};
|
|
}, {} ],
|
|
50: [ function(_dereq_, module, exports) {
|
|
module.exports = SplitSolver;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Solver = _dereq_("./Solver");
|
|
var Body = _dereq_("../objects/Body");
|
|
function SplitSolver(subsolver) {
|
|
Solver.call(this);
|
|
this.iterations = 10;
|
|
this.tolerance = 1e-7;
|
|
this.subsolver = subsolver;
|
|
this.nodes = [];
|
|
this.nodePool = [];
|
|
while (this.nodePool.length < 128) this.nodePool.push(this.createNode());
|
|
}
|
|
SplitSolver.prototype = new Solver();
|
|
var SplitSolver_solve_nodes = [];
|
|
var SplitSolver_solve_nodePool = [];
|
|
var SplitSolver_solve_eqs = [];
|
|
var SplitSolver_solve_bds = [];
|
|
var SplitSolver_solve_dummyWorld = {
|
|
bodies: []
|
|
};
|
|
var STATIC = Body.STATIC;
|
|
function getUnvisitedNode(nodes) {
|
|
var Nnodes = nodes.length;
|
|
for (var i = 0; i !== Nnodes; i++) {
|
|
var node = nodes[i];
|
|
if (!node.visited && !(node.body.type & STATIC)) return node;
|
|
}
|
|
return false;
|
|
}
|
|
var queue = [];
|
|
function bfs(root, visitFunc, bds, eqs) {
|
|
queue.push(root);
|
|
root.visited = true;
|
|
visitFunc(root, bds, eqs);
|
|
while (queue.length) {
|
|
var node = queue.pop();
|
|
var child;
|
|
while (child = getUnvisitedNode(node.children)) {
|
|
child.visited = true;
|
|
visitFunc(child, bds, eqs);
|
|
queue.push(child);
|
|
}
|
|
}
|
|
}
|
|
function visitFunc(node, bds, eqs) {
|
|
bds.push(node.body);
|
|
var Neqs = node.eqs.length;
|
|
for (var i = 0; i !== Neqs; i++) {
|
|
var eq = node.eqs[i];
|
|
-1 === eqs.indexOf(eq) && eqs.push(eq);
|
|
}
|
|
}
|
|
SplitSolver.prototype.createNode = function() {
|
|
return {
|
|
body: null,
|
|
children: [],
|
|
eqs: [],
|
|
visited: false
|
|
};
|
|
};
|
|
SplitSolver.prototype.solve = function(dt, world) {
|
|
var nodes = SplitSolver_solve_nodes, nodePool = this.nodePool, bodies = world.bodies, equations = this.equations, Neq = equations.length, Nbodies = bodies.length, subsolver = this.subsolver;
|
|
while (nodePool.length < Nbodies) nodePool.push(this.createNode());
|
|
nodes.length = Nbodies;
|
|
for (var i = 0; i < Nbodies; i++) nodes[i] = nodePool[i];
|
|
for (var i = 0; i !== Nbodies; i++) {
|
|
var node = nodes[i];
|
|
node.body = bodies[i];
|
|
node.children.length = 0;
|
|
node.eqs.length = 0;
|
|
node.visited = false;
|
|
}
|
|
for (var k = 0; k !== Neq; k++) {
|
|
var eq = equations[k], i = bodies.indexOf(eq.bi), j = bodies.indexOf(eq.bj), ni = nodes[i], nj = nodes[j];
|
|
ni.children.push(nj);
|
|
ni.eqs.push(eq);
|
|
nj.children.push(ni);
|
|
nj.eqs.push(eq);
|
|
}
|
|
var child, n = 0, eqs = SplitSolver_solve_eqs;
|
|
subsolver.tolerance = this.tolerance;
|
|
subsolver.iterations = this.iterations;
|
|
var dummyWorld = SplitSolver_solve_dummyWorld;
|
|
while (child = getUnvisitedNode(nodes)) {
|
|
eqs.length = 0;
|
|
dummyWorld.bodies.length = 0;
|
|
bfs(child, visitFunc, dummyWorld.bodies, eqs);
|
|
var Neqs = eqs.length;
|
|
eqs = eqs.sort(sortById);
|
|
for (var i = 0; i !== Neqs; i++) subsolver.addEquation(eqs[i]);
|
|
var iter = subsolver.solve(dt, dummyWorld);
|
|
subsolver.removeAllEquations();
|
|
n++;
|
|
}
|
|
return n;
|
|
};
|
|
function sortById(a, b) {
|
|
return b.id - a.id;
|
|
}
|
|
}, {
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../objects/Body": 33,
|
|
"./Solver": 49
|
|
} ],
|
|
51: [ function(_dereq_, module, exports) {
|
|
var EventTarget = function EventTarget() {};
|
|
module.exports = EventTarget;
|
|
EventTarget.prototype = {
|
|
constructor: EventTarget,
|
|
addEventListener: function addEventListener(type, listener) {
|
|
void 0 === this._listeners && (this._listeners = {});
|
|
var listeners = this._listeners;
|
|
void 0 === listeners[type] && (listeners[type] = []);
|
|
-1 === listeners[type].indexOf(listener) && listeners[type].push(listener);
|
|
return this;
|
|
},
|
|
hasEventListener: function hasEventListener(type, listener) {
|
|
if (void 0 === this._listeners) return false;
|
|
var listeners = this._listeners;
|
|
if (void 0 !== listeners[type] && -1 !== listeners[type].indexOf(listener)) return true;
|
|
return false;
|
|
},
|
|
hasAnyEventListener: function hasAnyEventListener(type) {
|
|
if (void 0 === this._listeners) return false;
|
|
var listeners = this._listeners;
|
|
return void 0 !== listeners[type];
|
|
},
|
|
removeEventListener: function removeEventListener(type, listener) {
|
|
if (void 0 === this._listeners) return this;
|
|
var listeners = this._listeners;
|
|
if (void 0 === listeners[type]) return this;
|
|
var index = listeners[type].indexOf(listener);
|
|
-1 !== index && listeners[type].splice(index, 1);
|
|
return this;
|
|
},
|
|
dispatchEvent: function dispatchEvent(event) {
|
|
if (void 0 === this._listeners) return this;
|
|
var listeners = this._listeners;
|
|
var listenerArray = listeners[event.type];
|
|
if (void 0 !== listenerArray) {
|
|
event.target = this;
|
|
for (var i = 0, l = listenerArray.length; i < l; i++) listenerArray[i].call(this, event);
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
}, {} ],
|
|
52: [ function(_dereq_, module, exports) {
|
|
var AABB = _dereq_("../collision/AABB");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
module.exports = Octree;
|
|
function OctreeNode(options) {
|
|
options = options || {};
|
|
this.root = options.root || null;
|
|
this.aabb = options.aabb ? options.aabb.clone() : new AABB();
|
|
this.data = [];
|
|
this.children = [];
|
|
}
|
|
function Octree(aabb, options) {
|
|
options = options || {};
|
|
options.root = null;
|
|
options.aabb = aabb;
|
|
OctreeNode.call(this, options);
|
|
this.maxDepth = "undefined" !== typeof options.maxDepth ? options.maxDepth : 8;
|
|
}
|
|
Octree.prototype = new OctreeNode();
|
|
OctreeNode.prototype.reset = function(aabb, options) {
|
|
this.children.length = this.data.length = 0;
|
|
};
|
|
OctreeNode.prototype.insert = function(aabb, elementData, level) {
|
|
var nodeData = this.data;
|
|
level = level || 0;
|
|
if (!this.aabb.contains(aabb)) return false;
|
|
var children = this.children;
|
|
if (level < (this.maxDepth || this.root.maxDepth)) {
|
|
var subdivided = false;
|
|
if (!children.length) {
|
|
this.subdivide();
|
|
subdivided = true;
|
|
}
|
|
for (var i = 0; 8 !== i; i++) if (children[i].insert(aabb, elementData, level + 1)) return true;
|
|
subdivided && (children.length = 0);
|
|
}
|
|
nodeData.push(elementData);
|
|
return true;
|
|
};
|
|
var halfDiagonal = new Vec3();
|
|
OctreeNode.prototype.subdivide = function() {
|
|
var aabb = this.aabb;
|
|
var l = aabb.lowerBound;
|
|
var u = aabb.upperBound;
|
|
var children = this.children;
|
|
children.push(new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(0, 0, 0)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(1, 0, 0)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(1, 1, 0)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(1, 1, 1)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(0, 1, 1)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(0, 0, 1)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(1, 0, 1)
|
|
})
|
|
}), new OctreeNode({
|
|
aabb: new AABB({
|
|
lowerBound: new Vec3(0, 1, 0)
|
|
})
|
|
}));
|
|
u.vsub(l, halfDiagonal);
|
|
halfDiagonal.scale(.5, halfDiagonal);
|
|
var root = this.root || this;
|
|
for (var i = 0; 8 !== i; i++) {
|
|
var child = children[i];
|
|
child.root = root;
|
|
var lowerBound = child.aabb.lowerBound;
|
|
lowerBound.x *= halfDiagonal.x;
|
|
lowerBound.y *= halfDiagonal.y;
|
|
lowerBound.z *= halfDiagonal.z;
|
|
lowerBound.vadd(l, lowerBound);
|
|
lowerBound.vadd(halfDiagonal, child.aabb.upperBound);
|
|
}
|
|
};
|
|
OctreeNode.prototype.aabbQuery = function(aabb, result) {
|
|
var nodeData = this.data;
|
|
var children = this.children;
|
|
var queue = [ this ];
|
|
while (queue.length) {
|
|
var node = queue.pop();
|
|
node.aabb.overlaps(aabb) && Array.prototype.push.apply(result, node.data);
|
|
Array.prototype.push.apply(queue, node.children);
|
|
}
|
|
return result;
|
|
};
|
|
var tmpAABB = new AABB();
|
|
OctreeNode.prototype.rayQuery = function(ray, treeTransform, result) {
|
|
ray.getAABB(tmpAABB);
|
|
tmpAABB.toLocalFrame(treeTransform, tmpAABB);
|
|
this.aabbQuery(tmpAABB, result);
|
|
return result;
|
|
};
|
|
OctreeNode.prototype.removeEmptyNodes = function() {
|
|
for (var i = this.children.length - 1; i >= 0; i--) {
|
|
this.children[i].removeEmptyNodes();
|
|
this.children[i].children.length || this.children[i].data.length || this.children.splice(i, 1);
|
|
}
|
|
};
|
|
}, {
|
|
"../collision/AABB": 3,
|
|
"../math/Vec3": 32
|
|
} ],
|
|
53: [ function(_dereq_, module, exports) {
|
|
module.exports = Pool;
|
|
function Pool() {
|
|
this.objects = [];
|
|
this.type = Object;
|
|
}
|
|
Pool.prototype.release = function() {
|
|
var Nargs = arguments.length;
|
|
for (var i = 0; i !== Nargs; i++) this.objects.push(arguments[i]);
|
|
return this;
|
|
};
|
|
Pool.prototype.get = function() {
|
|
return 0 === this.objects.length ? this.constructObject() : this.objects.pop();
|
|
};
|
|
Pool.prototype.constructObject = function() {
|
|
throw new Error("constructObject() not implemented in this Pool subclass yet!");
|
|
};
|
|
Pool.prototype.resize = function(size) {
|
|
var objects = this.objects;
|
|
while (objects.length > size) objects.pop();
|
|
while (objects.length < size) objects.push(this.constructObject());
|
|
return this;
|
|
};
|
|
}, {} ],
|
|
54: [ function(_dereq_, module, exports) {
|
|
module.exports = TupleDictionary;
|
|
function TupleDictionary() {
|
|
this.data = {
|
|
keys: []
|
|
};
|
|
}
|
|
TupleDictionary.prototype.get = function(i, j) {
|
|
if (i > j) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
return this.data[i + "-" + j];
|
|
};
|
|
TupleDictionary.prototype.set = function(i, j, value) {
|
|
if (i > j) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
var key = i + "-" + j;
|
|
this.get(i, j) || this.data.keys.push(key);
|
|
this.data[key] = value;
|
|
return this.data[key];
|
|
};
|
|
TupleDictionary.prototype.del = function(i, j) {
|
|
if (i > j) {
|
|
var temp = j;
|
|
j = i;
|
|
i = temp;
|
|
}
|
|
var key = i + "-" + j;
|
|
var index = this.data.keys.indexOf(key);
|
|
if (index >= 0) {
|
|
this.data.keys.splice(index, 1);
|
|
delete this.data[key];
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
TupleDictionary.prototype.reset = function() {
|
|
this.data = {
|
|
keys: []
|
|
};
|
|
};
|
|
TupleDictionary.prototype.getLength = function() {
|
|
return this.data.keys.length;
|
|
};
|
|
TupleDictionary.prototype.getKeyByIndex = function(index) {
|
|
return this.data.keys[index];
|
|
};
|
|
TupleDictionary.prototype.getDataByKey = function(Key) {
|
|
return this.data[Key];
|
|
};
|
|
}, {} ],
|
|
55: [ function(_dereq_, module, exports) {
|
|
function Utils() {}
|
|
module.exports = Utils;
|
|
Utils.defaults = function(options, defaults) {
|
|
options = options || {};
|
|
for (var key in defaults) key in options || (options[key] = defaults[key]);
|
|
return options;
|
|
};
|
|
}, {} ],
|
|
56: [ function(_dereq_, module, exports) {
|
|
module.exports = Vec3Pool;
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Pool = _dereq_("./Pool");
|
|
function Vec3Pool() {
|
|
Pool.call(this);
|
|
this.type = Vec3;
|
|
}
|
|
Vec3Pool.prototype = new Pool();
|
|
Vec3Pool.prototype.constructObject = function() {
|
|
return new Vec3();
|
|
};
|
|
}, {
|
|
"../math/Vec3": 32,
|
|
"./Pool": 53
|
|
} ],
|
|
57: [ function(_dereq_, module, exports) {
|
|
module.exports = Narrowphase;
|
|
var AABB = _dereq_("../collision/AABB");
|
|
var Body = _dereq_("../objects/Body");
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var Ray = _dereq_("../collision/Ray");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Transform = _dereq_("../math/Transform");
|
|
var ConvexPolyhedron = _dereq_("../shapes/ConvexPolyhedron");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var Solver = _dereq_("../solver/Solver");
|
|
var Vec3Pool = _dereq_("../utils/Vec3Pool");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
var FrictionEquation = _dereq_("../equations/FrictionEquation");
|
|
function Narrowphase(world) {
|
|
this.contactPointPool = [];
|
|
this.frictionEquationPool = [];
|
|
this.result = [];
|
|
this.frictionResult = [];
|
|
this.v3pool = new Vec3Pool();
|
|
this.world = world;
|
|
this.currentContactMaterial = null;
|
|
this.enableFrictionReduction = false;
|
|
}
|
|
Narrowphase.prototype.createContactEquation = function(bi, bj, si, sj, overrideShapeA, overrideShapeB) {
|
|
var c;
|
|
if (this.contactPointPool.length) {
|
|
c = this.contactPointPool.pop();
|
|
c.bi = bi;
|
|
c.bj = bj;
|
|
} else c = new ContactEquation(bi, bj);
|
|
c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse;
|
|
var cm = this.currentContactMaterial;
|
|
c.restitution = cm.restitution;
|
|
c.setSpookParams(cm.contactEquationStiffness, cm.contactEquationRelaxation, this.world.dt);
|
|
var matA = si.material || bi.material;
|
|
var matB = sj.material || bj.material;
|
|
matA && matB && matA.restitution >= 0 && matB.restitution >= 0 && (c.restitution = matA.restitution * matB.restitution);
|
|
c.si = overrideShapeA || si;
|
|
c.sj = overrideShapeB || sj;
|
|
return c;
|
|
};
|
|
Narrowphase.prototype.createFrictionEquationsFromContact = function(contactEquation, outArray) {
|
|
var bodyA = contactEquation.bi;
|
|
var bodyB = contactEquation.bj;
|
|
var shapeA = contactEquation.si;
|
|
var shapeB = contactEquation.sj;
|
|
var world = this.world;
|
|
var cm = this.currentContactMaterial;
|
|
var friction = cm.friction;
|
|
var matA = shapeA.material || bodyA.material;
|
|
var matB = shapeB.material || bodyB.material;
|
|
matA && matB && matA.friction >= 0 && matB.friction >= 0 && (friction = matA.friction * matB.friction);
|
|
if (friction > 0) {
|
|
var mug = friction * world.gravity.length();
|
|
var reducedMass = bodyA.invMass + bodyB.invMass;
|
|
reducedMass > 0 && (reducedMass = 1 / reducedMass);
|
|
var pool = this.frictionEquationPool;
|
|
var c1 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass);
|
|
var c2 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass);
|
|
c1.bi = c2.bi = bodyA;
|
|
c1.bj = c2.bj = bodyB;
|
|
c1.minForce = c2.minForce = -mug * reducedMass;
|
|
c1.maxForce = c2.maxForce = mug * reducedMass;
|
|
c1.ri.copy(contactEquation.ri);
|
|
c1.rj.copy(contactEquation.rj);
|
|
c2.ri.copy(contactEquation.ri);
|
|
c2.rj.copy(contactEquation.rj);
|
|
contactEquation.ni.tangents(c1.t, c2.t);
|
|
c1.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
|
|
c2.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
|
|
c1.enabled = c2.enabled = contactEquation.enabled;
|
|
outArray.push(c1, c2);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
var averageNormal = new Vec3();
|
|
var averageContactPointA = new Vec3();
|
|
var averageContactPointB = new Vec3();
|
|
Narrowphase.prototype.createFrictionFromAverage = function(numContacts) {
|
|
var c = this.result[this.result.length - 1];
|
|
if (!this.createFrictionEquationsFromContact(c, this.frictionResult) || 1 === numContacts) return;
|
|
var f1 = this.frictionResult[this.frictionResult.length - 2];
|
|
var f2 = this.frictionResult[this.frictionResult.length - 1];
|
|
averageNormal.setZero();
|
|
averageContactPointA.setZero();
|
|
averageContactPointB.setZero();
|
|
var bodyA = c.bi;
|
|
var bodyB = c.bj;
|
|
for (var i = 0; i !== numContacts; i++) {
|
|
c = this.result[this.result.length - 1 - i];
|
|
if (c.bodyA !== bodyA) {
|
|
averageNormal.vadd(c.ni, averageNormal);
|
|
averageContactPointA.vadd(c.ri, averageContactPointA);
|
|
averageContactPointB.vadd(c.rj, averageContactPointB);
|
|
} else {
|
|
averageNormal.vsub(c.ni, averageNormal);
|
|
averageContactPointA.vadd(c.rj, averageContactPointA);
|
|
averageContactPointB.vadd(c.ri, averageContactPointB);
|
|
}
|
|
}
|
|
var invNumContacts = 1 / numContacts;
|
|
averageContactPointA.scale(invNumContacts, f1.ri);
|
|
averageContactPointB.scale(invNumContacts, f1.rj);
|
|
f2.ri.copy(f1.ri);
|
|
f2.rj.copy(f1.rj);
|
|
averageNormal.normalize();
|
|
averageNormal.tangents(f1.t, f2.t);
|
|
};
|
|
var tmpVec1 = new Vec3();
|
|
var tmpVec2 = new Vec3();
|
|
var tmpQuat1 = new Quaternion();
|
|
var tmpQuat2 = new Quaternion();
|
|
Narrowphase.prototype.getContacts = function(p1, p2, world, result, oldcontacts, frictionResult, frictionPool) {
|
|
this.contactPointPool = oldcontacts;
|
|
this.frictionEquationPool = frictionPool;
|
|
this.result = result;
|
|
this.frictionResult = frictionResult;
|
|
var qi = tmpQuat1;
|
|
var qj = tmpQuat2;
|
|
var xi = tmpVec1;
|
|
var xj = tmpVec2;
|
|
for (var k = 0, N = p1.length; k !== N; k++) {
|
|
var bi = p1[k], bj = p2[k];
|
|
var bodyContactMaterial = null;
|
|
bi.material && bj.material && (bodyContactMaterial = world.getContactMaterial(bi.material, bj.material) || null);
|
|
var justTest = false == bi.collisionResponse || false == bj.collisionResponse || bi.type & Body.KINEMATIC && bj.type & Body.STATIC || bi.type & Body.STATIC && bj.type & Body.KINEMATIC || bi.type & Body.KINEMATIC && bj.type & Body.KINEMATIC;
|
|
for (var i = 0; i < bi.shapes.length; i++) {
|
|
bi.quaternion.mult(bi.shapeOrientations[i], qi);
|
|
bi.quaternion.vmult(bi.shapeOffsets[i], xi);
|
|
xi.vadd(bi.position, xi);
|
|
var si = bi.shapes[i];
|
|
for (var j = 0; j < bj.shapes.length; j++) {
|
|
bj.quaternion.mult(bj.shapeOrientations[j], qj);
|
|
bj.quaternion.vmult(bj.shapeOffsets[j], xj);
|
|
xj.vadd(bj.position, xj);
|
|
var sj = bj.shapes[j];
|
|
if (!(si.collisionFilterMask & sj.collisionFilterGroup && sj.collisionFilterMask & si.collisionFilterGroup)) continue;
|
|
if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) continue;
|
|
justTest |= false == si.collisionResponse || false == sj.collisionResponse;
|
|
var shapeContactMaterial = null;
|
|
si.material && sj.material && (shapeContactMaterial = world.getContactMaterial(si.material, sj.material) || null);
|
|
this.currentContactMaterial = shapeContactMaterial || bodyContactMaterial || world.defaultContactMaterial;
|
|
var resolver = this[si.type | sj.type];
|
|
if (resolver) {
|
|
var retval = false;
|
|
retval = si.type < sj.type ? resolver.call(this, si, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest) : resolver.call(this, sj, si, xj, xi, qj, qi, bj, bi, si, sj, justTest);
|
|
if (retval && justTest) {
|
|
world.shapeOverlapKeeper.set(si.id, sj.id);
|
|
world.bodyOverlapKeeper.set(bi.id, bj.id);
|
|
var data = {
|
|
si: si,
|
|
sj: sj
|
|
};
|
|
world.triggerDic.set(si.id, sj.id, data);
|
|
world.oldTriggerDic.set(si.id, sj.id, data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var numWarnings = 0;
|
|
var maxWarnings = 10;
|
|
function warn(msg) {
|
|
if (numWarnings > maxWarnings) return;
|
|
numWarnings++;
|
|
console.warn(msg);
|
|
}
|
|
Narrowphase.prototype[Shape.types.BOX | Shape.types.BOX] = Narrowphase.prototype.boxBox = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
sj.convexPolyhedronRepresentation.material = sj.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
|
|
return this.convexConvex(si.convexPolyhedronRepresentation, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
};
|
|
Narrowphase.prototype[Shape.types.BOX | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.boxConvex = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
return this.convexConvex(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
};
|
|
Narrowphase.prototype[Shape.types.BOX | Shape.types.PARTICLE] = Narrowphase.prototype.boxParticle = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
return this.convexParticle(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
};
|
|
Narrowphase.prototype[Shape.types.SPHERE] = Narrowphase.prototype.sphereSphere = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
if (justTest) return xi.distanceSquared(xj) < Math.pow(si.radius + sj.radius, 2);
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
xj.vsub(xi, r.ni);
|
|
r.ni.normalize();
|
|
r.ri.copy(r.ni);
|
|
r.rj.copy(r.ni);
|
|
r.ri.mult(si.radius, r.ri);
|
|
r.rj.mult(-sj.radius, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
};
|
|
var planeTrimesh_normal = new Vec3();
|
|
var planeTrimesh_relpos = new Vec3();
|
|
var planeTrimesh_projected = new Vec3();
|
|
Narrowphase.prototype[Shape.types.PLANE | Shape.types.TRIMESH] = Narrowphase.prototype.planeTrimesh = function(planeShape, trimeshShape, planePos, trimeshPos, planeQuat, trimeshQuat, planeBody, trimeshBody, rsi, rsj, justTest) {
|
|
var v = new Vec3();
|
|
var normal = planeTrimesh_normal;
|
|
normal.set(0, 0, 1);
|
|
planeQuat.vmult(normal, normal);
|
|
for (var i = 0; i < trimeshShape.vertices.length / 3; i++) {
|
|
trimeshShape.getVertex(i, v);
|
|
var v2 = new Vec3();
|
|
v2.copy(v);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v);
|
|
var relpos = planeTrimesh_relpos;
|
|
v.vsub(planePos, relpos);
|
|
var dot = normal.dot(relpos);
|
|
if (dot <= 0) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(planeBody, trimeshBody, planeShape, trimeshShape, rsi, rsj);
|
|
r.ni.copy(normal);
|
|
var projected = planeTrimesh_projected;
|
|
normal.scale(relpos.dot(normal), projected);
|
|
v.vsub(projected, projected);
|
|
r.ri.copy(projected);
|
|
r.ri.vsub(planeBody.position, r.ri);
|
|
r.rj.copy(v);
|
|
r.rj.vsub(trimeshBody.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
};
|
|
var sphereTrimesh_normal = new Vec3();
|
|
var sphereTrimesh_relpos = new Vec3();
|
|
var sphereTrimesh_projected = new Vec3();
|
|
var sphereTrimesh_v = new Vec3();
|
|
var sphereTrimesh_v2 = new Vec3();
|
|
var sphereTrimesh_edgeVertexA = new Vec3();
|
|
var sphereTrimesh_edgeVertexB = new Vec3();
|
|
var sphereTrimesh_edgeVector = new Vec3();
|
|
var sphereTrimesh_edgeVectorUnit = new Vec3();
|
|
var sphereTrimesh_localSpherePos = new Vec3();
|
|
var sphereTrimesh_tmp = new Vec3();
|
|
var sphereTrimesh_va = new Vec3();
|
|
var sphereTrimesh_vb = new Vec3();
|
|
var sphereTrimesh_vc = new Vec3();
|
|
var sphereTrimesh_localSphereAABB = new AABB();
|
|
var sphereTrimesh_triangles = [];
|
|
Narrowphase.prototype[Shape.types.SPHERE | Shape.types.TRIMESH] = Narrowphase.prototype.sphereTrimesh = function(sphereShape, trimeshShape, spherePos, trimeshPos, sphereQuat, trimeshQuat, sphereBody, trimeshBody, rsi, rsj, justTest) {
|
|
var edgeVertexA = sphereTrimesh_edgeVertexA;
|
|
var edgeVertexB = sphereTrimesh_edgeVertexB;
|
|
var edgeVector = sphereTrimesh_edgeVector;
|
|
var edgeVectorUnit = sphereTrimesh_edgeVectorUnit;
|
|
var localSpherePos = sphereTrimesh_localSpherePos;
|
|
var tmp = sphereTrimesh_tmp;
|
|
var localSphereAABB = sphereTrimesh_localSphereAABB;
|
|
var v2 = sphereTrimesh_v2;
|
|
var relpos = sphereTrimesh_relpos;
|
|
var triangles = sphereTrimesh_triangles;
|
|
Transform.pointToLocalFrame(trimeshPos, trimeshQuat, spherePos, localSpherePos);
|
|
var sphereRadius = sphereShape.radius;
|
|
localSphereAABB.lowerBound.set(localSpherePos.x - sphereRadius, localSpherePos.y - sphereRadius, localSpherePos.z - sphereRadius);
|
|
localSphereAABB.upperBound.set(localSpherePos.x + sphereRadius, localSpherePos.y + sphereRadius, localSpherePos.z + sphereRadius);
|
|
trimeshShape.getTrianglesInAABB(localSphereAABB, triangles);
|
|
var v = sphereTrimesh_v;
|
|
var radiusSquared = sphereShape.radius * sphereShape.radius;
|
|
for (var i = 0; i < triangles.length; i++) for (var j = 0; j < 3; j++) {
|
|
trimeshShape.getVertex(trimeshShape.indices[3 * triangles[i] + j], v);
|
|
v.vsub(localSpherePos, relpos);
|
|
if (relpos.norm2() <= radiusSquared) {
|
|
v2.copy(v);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v);
|
|
v.vsub(spherePos, relpos);
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj);
|
|
r.ni.copy(relpos);
|
|
r.ni.normalize();
|
|
r.ri.copy(r.ni);
|
|
r.ri.scale(sphereShape.radius, r.ri);
|
|
r.ri.vadd(spherePos, r.ri);
|
|
r.ri.vsub(sphereBody.position, r.ri);
|
|
r.rj.copy(v);
|
|
r.rj.vsub(trimeshBody.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
for (var i = 0; i < triangles.length; i++) for (var j = 0; j < 3; j++) {
|
|
trimeshShape.getVertex(trimeshShape.indices[3 * triangles[i] + j], edgeVertexA);
|
|
trimeshShape.getVertex(trimeshShape.indices[3 * triangles[i] + (j + 1) % 3], edgeVertexB);
|
|
edgeVertexB.vsub(edgeVertexA, edgeVector);
|
|
localSpherePos.vsub(edgeVertexB, tmp);
|
|
var positionAlongEdgeB = tmp.dot(edgeVector);
|
|
localSpherePos.vsub(edgeVertexA, tmp);
|
|
var positionAlongEdgeA = tmp.dot(edgeVector);
|
|
if (positionAlongEdgeA > 0 && positionAlongEdgeB < 0) {
|
|
localSpherePos.vsub(edgeVertexA, tmp);
|
|
edgeVectorUnit.copy(edgeVector);
|
|
edgeVectorUnit.normalize();
|
|
positionAlongEdgeA = tmp.dot(edgeVectorUnit);
|
|
edgeVectorUnit.scale(positionAlongEdgeA, tmp);
|
|
tmp.vadd(edgeVertexA, tmp);
|
|
var dist = tmp.distanceTo(localSpherePos);
|
|
if (dist < sphereShape.radius) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj);
|
|
tmp.vsub(localSpherePos, r.ni);
|
|
r.ni.normalize();
|
|
r.ni.scale(sphereShape.radius, r.ri);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp);
|
|
tmp.vsub(trimeshBody.position, r.rj);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
}
|
|
var va = sphereTrimesh_va;
|
|
var vb = sphereTrimesh_vb;
|
|
var vc = sphereTrimesh_vc;
|
|
var normal = sphereTrimesh_normal;
|
|
for (var i = 0, N = triangles.length; i !== N; i++) {
|
|
trimeshShape.getTriangleVertices(triangles[i], va, vb, vc);
|
|
trimeshShape.getNormal(triangles[i], normal);
|
|
localSpherePos.vsub(va, tmp);
|
|
var dist = tmp.dot(normal);
|
|
normal.scale(dist, tmp);
|
|
localSpherePos.vsub(tmp, tmp);
|
|
dist = tmp.distanceTo(localSpherePos);
|
|
if (Ray.pointInTriangle(tmp, va, vb, vc) && dist < sphereShape.radius) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape, rsi, rsj);
|
|
tmp.vsub(localSpherePos, r.ni);
|
|
r.ni.normalize();
|
|
r.ni.scale(sphereShape.radius, r.ri);
|
|
Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp);
|
|
tmp.vsub(trimeshBody.position, r.rj);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
|
|
Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
triangles.length = 0;
|
|
};
|
|
var point_on_plane_to_sphere = new Vec3();
|
|
var plane_to_sphere_ortho = new Vec3();
|
|
var p_s_ni = new Vec3();
|
|
var p_s_ri = new Vec3();
|
|
var p_s_rj = new Vec3();
|
|
Narrowphase.prototype[Shape.types.SPHERE | Shape.types.PLANE] = Narrowphase.prototype.spherePlane = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
p_s_ni.set(0, 0, 1);
|
|
qj.vmult(p_s_ni, p_s_ni);
|
|
p_s_ni.negate(p_s_ni);
|
|
p_s_ni.normalize();
|
|
p_s_ni.mult(si.radius, p_s_ri);
|
|
xi.vsub(xj, point_on_plane_to_sphere);
|
|
p_s_ni.mult(p_s_ni.dot(point_on_plane_to_sphere), plane_to_sphere_ortho);
|
|
point_on_plane_to_sphere.vsub(plane_to_sphere_ortho, p_s_rj);
|
|
if (-point_on_plane_to_sphere.dot(p_s_ni) <= si.radius) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ni.copy(p_s_ni);
|
|
r.ri.copy(p_s_ri);
|
|
r.rj.copy(p_s_rj);
|
|
var ri = r.ri;
|
|
var rj = r.rj;
|
|
ri.vadd(xi, ri);
|
|
ri.vsub(bi.position, ri);
|
|
rj.vadd(xj, rj);
|
|
rj.vsub(bj.position, rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
return false;
|
|
};
|
|
var pointInPolygon_edge = new Vec3();
|
|
var pointInPolygon_edge_x_normal = new Vec3();
|
|
var pointInPolygon_vtp = new Vec3();
|
|
function pointInPolygon(verts, normal, p) {
|
|
var positiveResult = null;
|
|
var N = verts.length;
|
|
for (var i = 0; i !== N; i++) {
|
|
var v = verts[i];
|
|
var edge = pointInPolygon_edge;
|
|
verts[(i + 1) % N].vsub(v, edge);
|
|
var edge_x_normal = pointInPolygon_edge_x_normal;
|
|
edge.cross(normal, edge_x_normal);
|
|
var vertex_to_p = pointInPolygon_vtp;
|
|
p.vsub(v, vertex_to_p);
|
|
var r = edge_x_normal.dot(vertex_to_p);
|
|
if (null === positiveResult || r > 0 && true === positiveResult || r <= 0 && false === positiveResult) {
|
|
null === positiveResult && (positiveResult = r > 0);
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
var box_to_sphere = new Vec3();
|
|
var sphereBox_ns = new Vec3();
|
|
var sphereBox_ns1 = new Vec3();
|
|
var sphereBox_ns2 = new Vec3();
|
|
var sphereBox_sides = [ new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3() ];
|
|
var sphereBox_sphere_to_corner = new Vec3();
|
|
var sphereBox_side_ns = new Vec3();
|
|
var sphereBox_side_ns1 = new Vec3();
|
|
var sphereBox_side_ns2 = new Vec3();
|
|
Narrowphase.prototype[Shape.types.SPHERE | Shape.types.BOX] = Narrowphase.prototype.sphereBox = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
var v3pool = this.v3pool;
|
|
var sides = sphereBox_sides;
|
|
xi.vsub(xj, box_to_sphere);
|
|
sj.getSideNormals(sides, qj);
|
|
var R = si.radius;
|
|
var penetrating_sides = [];
|
|
var found = false;
|
|
var side_ns = sphereBox_side_ns;
|
|
var side_ns1 = sphereBox_side_ns1;
|
|
var side_ns2 = sphereBox_side_ns2;
|
|
var side_h = null;
|
|
var side_penetrations = 0;
|
|
var side_dot1 = 0;
|
|
var side_dot2 = 0;
|
|
var side_distance = null;
|
|
for (var idx = 0, nsides = sides.length; idx !== nsides && false === found; idx++) {
|
|
var ns = sphereBox_ns;
|
|
ns.copy(sides[idx]);
|
|
var h = ns.norm();
|
|
ns.normalize();
|
|
var dot = box_to_sphere.dot(ns);
|
|
if (dot < h + R && dot > 0) {
|
|
var ns1 = sphereBox_ns1;
|
|
var ns2 = sphereBox_ns2;
|
|
ns1.copy(sides[(idx + 1) % 3]);
|
|
ns2.copy(sides[(idx + 2) % 3]);
|
|
var h1 = ns1.norm();
|
|
var h2 = ns2.norm();
|
|
ns1.normalize();
|
|
ns2.normalize();
|
|
var dot1 = box_to_sphere.dot(ns1);
|
|
var dot2 = box_to_sphere.dot(ns2);
|
|
if (dot1 < h1 && dot1 > -h1 && dot2 < h2 && dot2 > -h2) {
|
|
var dist = Math.abs(dot - h - R);
|
|
if (null === side_distance || dist < side_distance) {
|
|
side_distance = dist;
|
|
side_dot1 = dot1;
|
|
side_dot2 = dot2;
|
|
side_h = h;
|
|
side_ns.copy(ns);
|
|
side_ns1.copy(ns1);
|
|
side_ns2.copy(ns2);
|
|
side_penetrations++;
|
|
if (justTest) return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (side_penetrations) {
|
|
found = true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
side_ns.mult(-R, r.ri);
|
|
r.ni.copy(side_ns);
|
|
r.ni.negate(r.ni);
|
|
side_ns.mult(side_h, side_ns);
|
|
side_ns1.mult(side_dot1, side_ns1);
|
|
side_ns.vadd(side_ns1, side_ns);
|
|
side_ns2.mult(side_dot2, side_ns2);
|
|
side_ns.vadd(side_ns2, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
var rj = v3pool.get();
|
|
var sphere_to_corner = sphereBox_sphere_to_corner;
|
|
for (var j = 0; 2 !== j && !found; j++) for (var k = 0; 2 !== k && !found; k++) for (var l = 0; 2 !== l && !found; l++) {
|
|
rj.set(0, 0, 0);
|
|
j ? rj.vadd(sides[0], rj) : rj.vsub(sides[0], rj);
|
|
k ? rj.vadd(sides[1], rj) : rj.vsub(sides[1], rj);
|
|
l ? rj.vadd(sides[2], rj) : rj.vsub(sides[2], rj);
|
|
xj.vadd(rj, sphere_to_corner);
|
|
sphere_to_corner.vsub(xi, sphere_to_corner);
|
|
if (sphere_to_corner.norm2() < R * R) {
|
|
if (justTest) return true;
|
|
found = true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ri.copy(sphere_to_corner);
|
|
r.ri.normalize();
|
|
r.ni.copy(r.ri);
|
|
r.ri.mult(R, r.ri);
|
|
r.rj.copy(rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
v3pool.release(rj);
|
|
rj = null;
|
|
var edgeTangent = v3pool.get();
|
|
var edgeCenter = v3pool.get();
|
|
var r = v3pool.get();
|
|
var orthogonal = v3pool.get();
|
|
var dist = v3pool.get();
|
|
var Nsides = sides.length;
|
|
for (var j = 0; j !== Nsides && !found; j++) for (var k = 0; k !== Nsides && !found; k++) if (j % 3 !== k % 3) {
|
|
sides[k].cross(sides[j], edgeTangent);
|
|
edgeTangent.normalize();
|
|
sides[j].vadd(sides[k], edgeCenter);
|
|
r.copy(xi);
|
|
r.vsub(edgeCenter, r);
|
|
r.vsub(xj, r);
|
|
var orthonorm = r.dot(edgeTangent);
|
|
edgeTangent.mult(orthonorm, orthogonal);
|
|
var l = 0;
|
|
while (l === j % 3 || l === k % 3) l++;
|
|
dist.copy(xi);
|
|
dist.vsub(orthogonal, dist);
|
|
dist.vsub(edgeCenter, dist);
|
|
dist.vsub(xj, dist);
|
|
var tdist = Math.abs(orthonorm);
|
|
var ndist = dist.norm();
|
|
if (tdist < sides[l].norm() && ndist < R) {
|
|
if (justTest) return true;
|
|
found = true;
|
|
var res = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
edgeCenter.vadd(orthogonal, res.rj);
|
|
res.rj.copy(res.rj);
|
|
dist.negate(res.ni);
|
|
res.ni.normalize();
|
|
res.ri.copy(res.rj);
|
|
res.ri.vadd(xj, res.ri);
|
|
res.ri.vsub(xi, res.ri);
|
|
res.ri.normalize();
|
|
res.ri.mult(R, res.ri);
|
|
res.ri.vadd(xi, res.ri);
|
|
res.ri.vsub(bi.position, res.ri);
|
|
res.rj.vadd(xj, res.rj);
|
|
res.rj.vsub(bj.position, res.rj);
|
|
this.result.push(res);
|
|
this.createFrictionEquationsFromContact(res, this.frictionResult);
|
|
}
|
|
}
|
|
v3pool.release(edgeTangent, edgeCenter, r, orthogonal, dist);
|
|
};
|
|
var convex_to_sphere = new Vec3();
|
|
var sphereConvex_edge = new Vec3();
|
|
var sphereConvex_edgeUnit = new Vec3();
|
|
var sphereConvex_sphereToCorner = new Vec3();
|
|
var sphereConvex_worldCorner = new Vec3();
|
|
var sphereConvex_worldNormal = new Vec3();
|
|
var sphereConvex_worldPoint = new Vec3();
|
|
var sphereConvex_worldSpherePointClosestToPlane = new Vec3();
|
|
var sphereConvex_penetrationVec = new Vec3();
|
|
var sphereConvex_sphereToWorldPoint = new Vec3();
|
|
Narrowphase.prototype[Shape.types.SPHERE | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.sphereConvex = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
var v3pool = this.v3pool;
|
|
xi.vsub(xj, convex_to_sphere);
|
|
var normals = sj.faceNormals;
|
|
var faces = sj.faces;
|
|
var verts = sj.vertices;
|
|
var R = si.radius;
|
|
var penetrating_sides = [];
|
|
for (var i = 0; i !== verts.length; i++) {
|
|
var v = verts[i];
|
|
var worldCorner = sphereConvex_worldCorner;
|
|
qj.vmult(v, worldCorner);
|
|
xj.vadd(worldCorner, worldCorner);
|
|
var sphere_to_corner = sphereConvex_sphereToCorner;
|
|
worldCorner.vsub(xi, sphere_to_corner);
|
|
if (sphere_to_corner.norm2() < R * R) {
|
|
if (justTest) return true;
|
|
found = true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ri.copy(sphere_to_corner);
|
|
r.ri.normalize();
|
|
r.ni.copy(r.ri);
|
|
r.ri.mult(R, r.ri);
|
|
worldCorner.vsub(xj, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
return;
|
|
}
|
|
}
|
|
var found = false;
|
|
for (var i = 0, nfaces = faces.length; i !== nfaces && false === found; i++) {
|
|
var normal = normals[i];
|
|
var face = faces[i];
|
|
var worldNormal = sphereConvex_worldNormal;
|
|
qj.vmult(normal, worldNormal);
|
|
var worldPoint = sphereConvex_worldPoint;
|
|
qj.vmult(verts[face[0]], worldPoint);
|
|
worldPoint.vadd(xj, worldPoint);
|
|
var worldSpherePointClosestToPlane = sphereConvex_worldSpherePointClosestToPlane;
|
|
worldNormal.mult(-R, worldSpherePointClosestToPlane);
|
|
xi.vadd(worldSpherePointClosestToPlane, worldSpherePointClosestToPlane);
|
|
var penetrationVec = sphereConvex_penetrationVec;
|
|
worldSpherePointClosestToPlane.vsub(worldPoint, penetrationVec);
|
|
var penetration = penetrationVec.dot(worldNormal);
|
|
var worldPointToSphere = sphereConvex_sphereToWorldPoint;
|
|
xi.vsub(worldPoint, worldPointToSphere);
|
|
if (penetration < 0 && worldPointToSphere.dot(worldNormal) > 0) {
|
|
var faceVerts = [];
|
|
for (var j = 0, Nverts = face.length; j !== Nverts; j++) {
|
|
var worldVertex = v3pool.get();
|
|
qj.vmult(verts[face[j]], worldVertex);
|
|
xj.vadd(worldVertex, worldVertex);
|
|
faceVerts.push(worldVertex);
|
|
}
|
|
if (pointInPolygon(faceVerts, worldNormal, xi)) {
|
|
if (justTest) return true;
|
|
found = true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
worldNormal.mult(-R, r.ri);
|
|
worldNormal.negate(r.ni);
|
|
var penetrationVec2 = v3pool.get();
|
|
worldNormal.mult(-penetration, penetrationVec2);
|
|
var penetrationSpherePoint = v3pool.get();
|
|
worldNormal.mult(-R, penetrationSpherePoint);
|
|
xi.vsub(xj, r.rj);
|
|
r.rj.vadd(penetrationSpherePoint, r.rj);
|
|
r.rj.vadd(penetrationVec2, r.rj);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
v3pool.release(penetrationVec2);
|
|
v3pool.release(penetrationSpherePoint);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
for (var j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) v3pool.release(faceVerts[j]);
|
|
return;
|
|
}
|
|
for (var j = 0; j !== face.length; j++) {
|
|
var v1 = v3pool.get();
|
|
var v2 = v3pool.get();
|
|
qj.vmult(verts[face[(j + 1) % face.length]], v1);
|
|
qj.vmult(verts[face[(j + 2) % face.length]], v2);
|
|
xj.vadd(v1, v1);
|
|
xj.vadd(v2, v2);
|
|
var edge = sphereConvex_edge;
|
|
v2.vsub(v1, edge);
|
|
var edgeUnit = sphereConvex_edgeUnit;
|
|
edge.unit(edgeUnit);
|
|
var p = v3pool.get();
|
|
var v1_to_xi = v3pool.get();
|
|
xi.vsub(v1, v1_to_xi);
|
|
var dot = v1_to_xi.dot(edgeUnit);
|
|
edgeUnit.mult(dot, p);
|
|
p.vadd(v1, p);
|
|
var xi_to_p = v3pool.get();
|
|
p.vsub(xi, xi_to_p);
|
|
if (dot > 0 && dot * dot < edge.norm2() && xi_to_p.norm2() < R * R) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
p.vsub(xj, r.rj);
|
|
p.vsub(xi, r.ni);
|
|
r.ni.normalize();
|
|
r.ni.mult(R, r.ri);
|
|
r.rj.vadd(xj, r.rj);
|
|
r.rj.vsub(bj.position, r.rj);
|
|
r.ri.vadd(xi, r.ri);
|
|
r.ri.vsub(bi.position, r.ri);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
for (var j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) v3pool.release(faceVerts[j]);
|
|
v3pool.release(v1);
|
|
v3pool.release(v2);
|
|
v3pool.release(p);
|
|
v3pool.release(xi_to_p);
|
|
v3pool.release(v1_to_xi);
|
|
return;
|
|
}
|
|
v3pool.release(v1);
|
|
v3pool.release(v2);
|
|
v3pool.release(p);
|
|
v3pool.release(xi_to_p);
|
|
v3pool.release(v1_to_xi);
|
|
}
|
|
for (var j = 0, Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) v3pool.release(faceVerts[j]);
|
|
}
|
|
}
|
|
};
|
|
var planeBox_normal = new Vec3();
|
|
var plane_to_corner = new Vec3();
|
|
Narrowphase.prototype[Shape.types.PLANE | Shape.types.BOX] = Narrowphase.prototype.planeBox = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
sj.convexPolyhedronRepresentation.material = sj.material;
|
|
sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
|
|
sj.convexPolyhedronRepresentation.id = sj.id;
|
|
return this.planeConvex(si, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
};
|
|
var planeConvex_v = new Vec3();
|
|
var planeConvex_normal = new Vec3();
|
|
var planeConvex_relpos = new Vec3();
|
|
var planeConvex_projected = new Vec3();
|
|
Narrowphase.prototype[Shape.types.PLANE | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.planeConvex = function(planeShape, convexShape, planePosition, convexPosition, planeQuat, convexQuat, planeBody, convexBody, si, sj, justTest) {
|
|
var worldVertex = planeConvex_v, worldNormal = planeConvex_normal;
|
|
worldNormal.set(0, 0, 1);
|
|
planeQuat.vmult(worldNormal, worldNormal);
|
|
var numContacts = 0;
|
|
var relpos = planeConvex_relpos;
|
|
for (var i = 0; i !== convexShape.vertices.length; i++) {
|
|
worldVertex.copy(convexShape.vertices[i]);
|
|
convexQuat.vmult(worldVertex, worldVertex);
|
|
convexPosition.vadd(worldVertex, worldVertex);
|
|
worldVertex.vsub(planePosition, relpos);
|
|
var dot = worldNormal.dot(relpos);
|
|
if (dot <= 0) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(planeBody, convexBody, planeShape, convexShape, si, sj);
|
|
var projected = planeConvex_projected;
|
|
worldNormal.mult(worldNormal.dot(relpos), projected);
|
|
worldVertex.vsub(projected, projected);
|
|
projected.vsub(planePosition, r.ri);
|
|
r.ni.copy(worldNormal);
|
|
worldVertex.vsub(convexPosition, r.rj);
|
|
r.ri.vadd(planePosition, r.ri);
|
|
r.ri.vsub(planeBody.position, r.ri);
|
|
r.rj.vadd(convexPosition, r.rj);
|
|
r.rj.vsub(convexBody.position, r.rj);
|
|
this.result.push(r);
|
|
numContacts++;
|
|
this.enableFrictionReduction || this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
}
|
|
this.enableFrictionReduction && numContacts && this.createFrictionFromAverage(numContacts);
|
|
};
|
|
var convexConvex_sepAxis = new Vec3();
|
|
var convexConvex_q = new Vec3();
|
|
Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.convexConvex = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest, faceListA, faceListB) {
|
|
var sepAxis = convexConvex_sepAxis;
|
|
if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) return;
|
|
if (si.findSeparatingAxis(sj, xi, qi, xj, qj, sepAxis, faceListA, faceListB)) {
|
|
var res = [];
|
|
var q = convexConvex_q;
|
|
si.clipAgainstHull(xi, qi, sj, xj, qj, sepAxis, -100, 100, res);
|
|
var numContacts = 0;
|
|
for (var j = 0; j !== res.length; j++) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj), ri = r.ri, rj = r.rj;
|
|
sepAxis.negate(r.ni);
|
|
res[j].normal.negate(q);
|
|
q.mult(res[j].depth, q);
|
|
res[j].point.vadd(q, ri);
|
|
rj.copy(res[j].point);
|
|
ri.vsub(xi, ri);
|
|
rj.vsub(xj, rj);
|
|
ri.vadd(xi, ri);
|
|
ri.vsub(bi.position, ri);
|
|
rj.vadd(xj, rj);
|
|
rj.vsub(bj.position, rj);
|
|
this.result.push(r);
|
|
numContacts++;
|
|
this.enableFrictionReduction || this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
this.enableFrictionReduction && numContacts && this.createFrictionFromAverage(numContacts);
|
|
}
|
|
};
|
|
var particlePlane_normal = new Vec3();
|
|
var particlePlane_relpos = new Vec3();
|
|
var particlePlane_projected = new Vec3();
|
|
Narrowphase.prototype[Shape.types.PLANE | Shape.types.PARTICLE] = Narrowphase.prototype.planeParticle = function(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) {
|
|
var normal = particlePlane_normal;
|
|
normal.set(0, 0, 1);
|
|
bj.quaternion.vmult(normal, normal);
|
|
var relpos = particlePlane_relpos;
|
|
xi.vsub(bj.position, relpos);
|
|
var dot = normal.dot(relpos);
|
|
if (dot <= 0) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
r.ni.copy(normal);
|
|
r.ni.negate(r.ni);
|
|
r.ri.set(0, 0, 0);
|
|
var projected = particlePlane_projected;
|
|
normal.mult(normal.dot(xi), projected);
|
|
xi.vsub(projected, projected);
|
|
r.rj.copy(projected);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
};
|
|
var particleSphere_normal = new Vec3();
|
|
Narrowphase.prototype[Shape.types.PARTICLE | Shape.types.SPHERE] = Narrowphase.prototype.sphereParticle = function(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) {
|
|
var normal = particleSphere_normal;
|
|
normal.set(0, 0, 1);
|
|
xi.vsub(xj, normal);
|
|
var lengthSquared = normal.norm2();
|
|
if (lengthSquared <= sj.radius * sj.radius) {
|
|
if (justTest) return true;
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
normal.normalize();
|
|
r.rj.copy(normal);
|
|
r.rj.mult(sj.radius, r.rj);
|
|
r.ni.copy(normal);
|
|
r.ni.negate(r.ni);
|
|
r.ri.set(0, 0, 0);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
}
|
|
};
|
|
var cqj = new Quaternion();
|
|
var convexParticle_local = new Vec3();
|
|
var convexParticle_normal = new Vec3();
|
|
var convexParticle_penetratedFaceNormal = new Vec3();
|
|
var convexParticle_vertexToParticle = new Vec3();
|
|
var convexParticle_worldPenetrationVec = new Vec3();
|
|
Narrowphase.prototype[Shape.types.PARTICLE | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.convexParticle = function(sj, si, xj, xi, qj, qi, bj, bi, rsi, rsj, justTest) {
|
|
var penetratedFaceIndex = -1;
|
|
var penetratedFaceNormal = convexParticle_penetratedFaceNormal;
|
|
var worldPenetrationVec = convexParticle_worldPenetrationVec;
|
|
var minPenetration = null;
|
|
var numDetectedFaces = 0;
|
|
var local = convexParticle_local;
|
|
local.copy(xi);
|
|
local.vsub(xj, local);
|
|
qj.conjugate(cqj);
|
|
cqj.vmult(local, local);
|
|
if (sj.pointIsInside(local)) {
|
|
sj.worldVerticesNeedsUpdate && sj.computeWorldVertices(xj, qj);
|
|
sj.worldFaceNormalsNeedsUpdate && sj.computeWorldFaceNormals(qj);
|
|
for (var i = 0, nfaces = sj.faces.length; i !== nfaces; i++) {
|
|
var verts = [ sj.worldVertices[sj.faces[i][0]] ];
|
|
var normal = sj.worldFaceNormals[i];
|
|
xi.vsub(verts[0], convexParticle_vertexToParticle);
|
|
var penetration = -normal.dot(convexParticle_vertexToParticle);
|
|
if (null === minPenetration || Math.abs(penetration) < Math.abs(minPenetration)) {
|
|
if (justTest) return true;
|
|
minPenetration = penetration;
|
|
penetratedFaceIndex = i;
|
|
penetratedFaceNormal.copy(normal);
|
|
numDetectedFaces++;
|
|
}
|
|
}
|
|
if (-1 !== penetratedFaceIndex) {
|
|
var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj);
|
|
penetratedFaceNormal.mult(minPenetration, worldPenetrationVec);
|
|
worldPenetrationVec.vadd(xi, worldPenetrationVec);
|
|
worldPenetrationVec.vsub(xj, worldPenetrationVec);
|
|
r.rj.copy(worldPenetrationVec);
|
|
penetratedFaceNormal.negate(r.ni);
|
|
r.ri.set(0, 0, 0);
|
|
var ri = r.ri, rj = r.rj;
|
|
ri.vadd(xi, ri);
|
|
ri.vsub(bi.position, ri);
|
|
rj.vadd(xj, rj);
|
|
rj.vsub(bj.position, rj);
|
|
this.result.push(r);
|
|
this.createFrictionEquationsFromContact(r, this.frictionResult);
|
|
} else console.warn("Point found inside convex, but did not find penetrating face!");
|
|
}
|
|
};
|
|
Narrowphase.prototype[Shape.types.BOX | Shape.types.HEIGHTFIELD] = Narrowphase.prototype.boxHeightfield = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, justTest) {
|
|
si.convexPolyhedronRepresentation.material = si.material;
|
|
si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
|
|
return this.convexHeightfield(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj, justTest);
|
|
};
|
|
var convexHeightfield_tmp1 = new Vec3();
|
|
var convexHeightfield_tmp2 = new Vec3();
|
|
var convexHeightfield_faceList = [ 0 ];
|
|
Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON | Shape.types.HEIGHTFIELD] = Narrowphase.prototype.convexHeightfield = function(convexShape, hfShape, convexPos, hfPos, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest) {
|
|
var data = hfShape.data, w = hfShape.elementSize, radius = convexShape.boundingSphereRadius, worldPillarOffset = convexHeightfield_tmp2, faceList = convexHeightfield_faceList;
|
|
var localConvexPos = convexHeightfield_tmp1;
|
|
Transform.pointToLocalFrame(hfPos, hfQuat, convexPos, localConvexPos);
|
|
var iMinX = Math.floor((localConvexPos.x - radius) / w) - 1, iMaxX = Math.ceil((localConvexPos.x + radius) / w) + 1, iMinY = Math.floor((localConvexPos.y - radius) / w) - 1, iMaxY = Math.ceil((localConvexPos.y + radius) / w) + 1;
|
|
if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) return;
|
|
iMinX < 0 && (iMinX = 0);
|
|
iMaxX < 0 && (iMaxX = 0);
|
|
iMinY < 0 && (iMinY = 0);
|
|
iMaxY < 0 && (iMaxY = 0);
|
|
iMinX >= data.length && (iMinX = data.length - 1);
|
|
iMaxX >= data.length && (iMaxX = data.length - 1);
|
|
iMaxY >= data[0].length && (iMaxY = data[0].length - 1);
|
|
iMinY >= data[0].length && (iMinY = data[0].length - 1);
|
|
var minMax = [];
|
|
hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
|
|
var min = minMax[0];
|
|
var max = minMax[1];
|
|
if (localConvexPos.z - radius > max || localConvexPos.z + radius < min) return;
|
|
for (var i = iMinX; i < iMaxX; i++) for (var j = iMinY; j < iMaxY; j++) {
|
|
var intersecting = false;
|
|
hfShape.getConvexTrianglePillar(i, j, false);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
|
|
convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius && (intersecting = this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest, faceList, null));
|
|
if (justTest && intersecting) return true;
|
|
hfShape.getConvexTrianglePillar(i, j, true);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
|
|
convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius && (intersecting = this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, rsi, rsj, justTest, faceList, null));
|
|
if (justTest && intersecting) return true;
|
|
}
|
|
};
|
|
var sphereHeightfield_tmp1 = new Vec3();
|
|
var sphereHeightfield_tmp2 = new Vec3();
|
|
Narrowphase.prototype[Shape.types.SPHERE | Shape.types.HEIGHTFIELD] = Narrowphase.prototype.sphereHeightfield = function(sphereShape, hfShape, spherePos, hfPos, sphereQuat, hfQuat, sphereBody, hfBody, rsi, rsj, justTest) {
|
|
var data = hfShape.data, radius = sphereShape.radius, w = hfShape.elementSize, worldPillarOffset = sphereHeightfield_tmp2;
|
|
var localSpherePos = sphereHeightfield_tmp1;
|
|
Transform.pointToLocalFrame(hfPos, hfQuat, spherePos, localSpherePos);
|
|
var iMinX = Math.floor((localSpherePos.x - radius) / w) - 1, iMaxX = Math.ceil((localSpherePos.x + radius) / w) + 1, iMinY = Math.floor((localSpherePos.y - radius) / w) - 1, iMaxY = Math.ceil((localSpherePos.y + radius) / w) + 1;
|
|
if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) return;
|
|
iMinX < 0 && (iMinX = 0);
|
|
iMaxX < 0 && (iMaxX = 0);
|
|
iMinY < 0 && (iMinY = 0);
|
|
iMaxY < 0 && (iMaxY = 0);
|
|
iMinX >= data.length && (iMinX = data.length - 1);
|
|
iMaxX >= data.length && (iMaxX = data.length - 1);
|
|
iMaxY >= data[0].length && (iMaxY = data[0].length - 1);
|
|
iMinY >= data[0].length && (iMinY = data[0].length - 1);
|
|
var minMax = [];
|
|
hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
|
|
var min = minMax[0];
|
|
var max = minMax[1];
|
|
if (localSpherePos.z - radius > max || localSpherePos.z + radius < min) return;
|
|
var result = this.result;
|
|
for (var i = iMinX; i < iMaxX; i++) for (var j = iMinY; j < iMaxY; j++) {
|
|
var numContactsBefore = result.length;
|
|
var intersecting = false;
|
|
hfShape.getConvexTrianglePillar(i, j, false);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
|
|
spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius && (intersecting = this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody, sphereShape, hfShape, justTest));
|
|
if (justTest && intersecting) return true;
|
|
hfShape.getConvexTrianglePillar(i, j, true);
|
|
Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
|
|
spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius && (intersecting = this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody, sphereShape, hfShape, justTest));
|
|
if (justTest && intersecting) return true;
|
|
var numContacts = result.length - numContactsBefore;
|
|
if (numContacts > 2) return;
|
|
}
|
|
};
|
|
}, {
|
|
"../collision/AABB": 3,
|
|
"../collision/Ray": 10,
|
|
"../equations/ContactEquation": 20,
|
|
"../equations/FrictionEquation": 22,
|
|
"../math/Quaternion": 30,
|
|
"../math/Transform": 31,
|
|
"../math/Vec3": 32,
|
|
"../objects/Body": 33,
|
|
"../shapes/ConvexPolyhedron": 40,
|
|
"../shapes/Shape": 45,
|
|
"../solver/Solver": 49,
|
|
"../utils/Vec3Pool": 56
|
|
} ],
|
|
58: [ function(_dereq_, module, exports) {
|
|
module.exports = World;
|
|
var Shape = _dereq_("../shapes/Shape");
|
|
var Vec3 = _dereq_("../math/Vec3");
|
|
var Quaternion = _dereq_("../math/Quaternion");
|
|
var GSSolver = _dereq_("../solver/GSSolver");
|
|
var ContactEquation = _dereq_("../equations/ContactEquation");
|
|
var FrictionEquation = _dereq_("../equations/FrictionEquation");
|
|
var Narrowphase = _dereq_("./Narrowphase");
|
|
var EventTarget = _dereq_("../utils/EventTarget");
|
|
var ArrayCollisionMatrix = _dereq_("../collision/ArrayCollisionMatrix");
|
|
var ObjectCollisionMatrix = _dereq_("../collision/ObjectCollisionMatrix");
|
|
var OverlapKeeper = _dereq_("../collision/OverlapKeeper");
|
|
var Material = _dereq_("../material/Material");
|
|
var ContactMaterial = _dereq_("../material/ContactMaterial");
|
|
var Body = _dereq_("../objects/Body");
|
|
var TupleDictionary = _dereq_("../utils/TupleDictionary");
|
|
var RaycastResult = _dereq_("../collision/RaycastResult");
|
|
var AABB = _dereq_("../collision/AABB");
|
|
var Ray = _dereq_("../collision/Ray");
|
|
var NaiveBroadphase = _dereq_("../collision/NaiveBroadphase");
|
|
function World(options) {
|
|
options = options || {};
|
|
EventTarget.apply(this);
|
|
this.dt = -1;
|
|
this.allowSleep = !!options.allowSleep;
|
|
this.contacts = [];
|
|
this.frictionEquations = [];
|
|
this.quatNormalizeSkip = void 0 !== options.quatNormalizeSkip ? options.quatNormalizeSkip : 0;
|
|
this.quatNormalizeFast = void 0 !== options.quatNormalizeFast && options.quatNormalizeFast;
|
|
this.time = 0;
|
|
this.timeFixed = 0;
|
|
this.stepnumber = 0;
|
|
this.default_dt = 1 / 60;
|
|
this.nextId = 0;
|
|
this.gravity = new Vec3();
|
|
options.gravity && this.gravity.copy(options.gravity);
|
|
this.broadphase = void 0 !== options.broadphase ? options.broadphase : new NaiveBroadphase();
|
|
this.bodies = [];
|
|
this.solver = void 0 !== options.solver ? options.solver : new GSSolver();
|
|
this.constraints = [];
|
|
this.narrowphase = new Narrowphase(this);
|
|
this.collisionMatrix = new ArrayCollisionMatrix();
|
|
this.collisionMatrixPrevious = new ArrayCollisionMatrix();
|
|
this.bodyOverlapKeeper = new OverlapKeeper();
|
|
this.shapeOverlapKeeper = new OverlapKeeper();
|
|
this.materials = [];
|
|
this.contactmaterials = [];
|
|
this.contactMaterialTable = new TupleDictionary();
|
|
this.defaultMaterial = new Material("default");
|
|
this.defaultContactMaterial = new ContactMaterial(this.defaultMaterial, this.defaultMaterial, {
|
|
friction: .3,
|
|
restitution: 0
|
|
});
|
|
this.doProfiling = false;
|
|
this.profile = {
|
|
solve: 0,
|
|
makeContactConstraints: 0,
|
|
broadphase: 0,
|
|
integrate: 0,
|
|
narrowphase: 0
|
|
};
|
|
this.accumulator = 0;
|
|
this.subsystems = [];
|
|
this.addBodyEvent = {
|
|
type: "addBody",
|
|
body: null
|
|
};
|
|
this.removeBodyEvent = {
|
|
type: "removeBody",
|
|
body: null
|
|
};
|
|
this.idToBodyMap = {};
|
|
this.broadphase.setWorld(this);
|
|
this.substeps = 0;
|
|
this.cm = new ObjectCollisionMatrix();
|
|
this.tm = new ObjectCollisionMatrix();
|
|
this.triggerDic = new TupleDictionary();
|
|
this.oldTriggerDic = new TupleDictionary();
|
|
this.contactsDic = new TupleDictionary();
|
|
this.oldContactsDic = new TupleDictionary();
|
|
}
|
|
World.idToBodyMap = {};
|
|
World.idToShapeMap = {};
|
|
World.prototype = new EventTarget();
|
|
var tmpAABB1 = new AABB();
|
|
var tmpArray1 = [];
|
|
var tmpRay = new Ray();
|
|
World.prototype.getContactMaterial = function(m1, m2) {
|
|
return this.contactMaterialTable.get(m1.id, m2.id);
|
|
};
|
|
World.prototype.numObjects = function() {
|
|
return this.bodies.length;
|
|
};
|
|
World.prototype.collisionMatrixTick = function() {
|
|
var temp = this.collisionMatrixPrevious;
|
|
this.collisionMatrixPrevious = this.collisionMatrix;
|
|
this.collisionMatrix = temp;
|
|
this.collisionMatrix.reset();
|
|
this.bodyOverlapKeeper.tick();
|
|
this.shapeOverlapKeeper.tick();
|
|
};
|
|
World.prototype.add = World.prototype.addBody = function(body) {
|
|
World.SLEEPING = false;
|
|
if (-1 !== this.bodies.indexOf(body)) return;
|
|
body.index = this.bodies.length;
|
|
this.bodies.push(body);
|
|
body.world = this;
|
|
body.initPosition.copy(body.position);
|
|
body.initVelocity.copy(body.velocity);
|
|
body.timeLastSleepy = this.time;
|
|
if (body instanceof Body) {
|
|
body.initAngularVelocity.copy(body.angularVelocity);
|
|
body.initQuaternion.copy(body.quaternion);
|
|
}
|
|
this.collisionMatrix.setNumObjects(this.bodies.length);
|
|
this.addBodyEvent.body = body;
|
|
this.cm.setNumObjects(this.bodies.length);
|
|
World.idToBodyMap[body.id] = body;
|
|
this.dispatchEvent(this.addBodyEvent);
|
|
};
|
|
World.prototype.addConstraint = function(c) {
|
|
World.SLEEPING = false;
|
|
this.constraints.push(c);
|
|
};
|
|
World.prototype.removeConstraint = function(c) {
|
|
World.SLEEPING = false;
|
|
var idx = this.constraints.indexOf(c);
|
|
-1 !== idx && this.constraints.splice(idx, 1);
|
|
};
|
|
World.prototype.rayTest = function(from, to, result) {
|
|
result instanceof RaycastResult ? this.raycastClosest(from, to, {
|
|
skipBackfaces: true
|
|
}, result) : this.raycastAll(from, to, {
|
|
skipBackfaces: true
|
|
}, result);
|
|
};
|
|
World.prototype.raycastAll = function(from, to, options, callback) {
|
|
options.mode = Ray.ALL;
|
|
options.from = from;
|
|
options.to = to;
|
|
options.callback = callback;
|
|
return tmpRay.intersectWorld(this, options);
|
|
};
|
|
World.prototype.raycastAny = function(from, to, options, result) {
|
|
options.mode = Ray.ANY;
|
|
options.from = from;
|
|
options.to = to;
|
|
options.result = result;
|
|
return tmpRay.intersectWorld(this, options);
|
|
};
|
|
World.prototype.raycastClosest = function(from, to, options, result) {
|
|
options.mode = Ray.CLOSEST;
|
|
options.from = from;
|
|
options.to = to;
|
|
options.result = result;
|
|
return tmpRay.intersectWorld(this, options);
|
|
};
|
|
World.prototype.remove = function(body) {
|
|
World.SLEEPING = false;
|
|
body.world = null;
|
|
var n = this.bodies.length - 1, bodies = this.bodies, idx = bodies.indexOf(body);
|
|
if (-1 !== idx) {
|
|
bodies.splice(idx, 1);
|
|
for (var i = 0; i !== bodies.length; i++) bodies[i].index = i;
|
|
this.collisionMatrix.setNumObjects(n);
|
|
this.removeBodyEvent.body = body;
|
|
delete World.idToBodyMap[body.id];
|
|
this.cm.setNumObjects(n);
|
|
this.dispatchEvent(this.removeBodyEvent);
|
|
}
|
|
};
|
|
World.prototype.removeBody = World.prototype.remove;
|
|
World.prototype.getBodyById = function(id) {
|
|
return World.idToBodyMap[id];
|
|
};
|
|
World.prototype.getShapeById = function(id) {
|
|
return World.idToShapeMap[id];
|
|
};
|
|
World.prototype.addMaterial = function(m) {
|
|
this.materials.push(m);
|
|
};
|
|
World.prototype.addContactMaterial = function(cmat) {
|
|
this.contactmaterials.push(cmat);
|
|
this.contactMaterialTable.set(cmat.materials[0].id, cmat.materials[1].id, cmat);
|
|
};
|
|
"undefined" === typeof performance && (performance = {});
|
|
if (!performance.now) {
|
|
var nowOffset = Date.now();
|
|
performance.timing && performance.timing.navigationStart && (nowOffset = performance.timing.navigationStart);
|
|
performance.now = function() {
|
|
return Date.now() - nowOffset;
|
|
};
|
|
}
|
|
var step_tmp1 = new Vec3();
|
|
World.prototype.step = function(dt, timeSinceLastCalled, maxSubSteps) {
|
|
maxSubSteps = maxSubSteps || 10;
|
|
timeSinceLastCalled = timeSinceLastCalled || 0;
|
|
if (0 === timeSinceLastCalled) {
|
|
this.internalStep(dt);
|
|
this.time += dt;
|
|
this.substeps = 1;
|
|
} else {
|
|
this.accumulator += timeSinceLastCalled;
|
|
this.substeps = 0;
|
|
while (this.accumulator >= dt && this.substeps < maxSubSteps) {
|
|
this.internalStep(dt);
|
|
this.accumulator -= dt;
|
|
this.substeps++;
|
|
}
|
|
var t = this.accumulator % dt / dt;
|
|
for (var j = 0; j !== this.bodies.length; j++) {
|
|
var b = this.bodies[j];
|
|
b.previousPosition.lerp(b.position, t, b.interpolatedPosition);
|
|
b.previousQuaternion.slerp(b.quaternion, t, b.interpolatedQuaternion);
|
|
b.previousQuaternion.normalize();
|
|
}
|
|
this.time += timeSinceLastCalled;
|
|
}
|
|
};
|
|
var World_step_postStepEvent = {
|
|
type: "postStep"
|
|
}, World_step_preStepEvent = {
|
|
type: "preStep"
|
|
}, World_step_collideEvent = {
|
|
type: "collide",
|
|
body: null,
|
|
contact: null
|
|
}, World_step_oldContacts = [], World_step_frictionEquationPool = [], World_step_p1 = [], World_step_p2 = [], World_step_gvec = new Vec3(), World_step_vi = new Vec3(), World_step_vj = new Vec3(), World_step_wi = new Vec3(), World_step_wj = new Vec3(), World_step_t1 = new Vec3(), World_step_t2 = new Vec3(), World_step_rixn = new Vec3(), World_step_rjxn = new Vec3(), World_step_step_q = new Quaternion(), World_step_step_w = new Quaternion(), World_step_step_wq = new Quaternion(), invI_tau_dt = new Vec3();
|
|
World.prototype.internalStep = function(dt) {
|
|
this.dt = dt;
|
|
var world = this, that = this, contacts = this.contacts, p1 = World_step_p1, p2 = World_step_p2, N = this.numObjects(), bodies = this.bodies, solver = this.solver, gravity = this.gravity, doProfiling = this.doProfiling, profile = this.profile, DYNAMIC = Body.DYNAMIC, profilingStart, constraints = this.constraints, frictionEquationPool = World_step_frictionEquationPool, gnorm = gravity.norm(), gx = gravity.x, gy = gravity.y, gz = gravity.z, i = 0;
|
|
doProfiling && (profilingStart = performance.now());
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
if (bi.useGravity && bi.type === DYNAMIC) {
|
|
var f = bi.force, m = bi.mass;
|
|
f.x += m * gx;
|
|
f.y += m * gy;
|
|
f.z += m * gz;
|
|
}
|
|
}
|
|
for (var i = 0, Nsubsystems = this.subsystems.length; i !== Nsubsystems; i++) this.subsystems[i].update();
|
|
doProfiling && (profilingStart = performance.now());
|
|
p1.length = 0;
|
|
p2.length = 0;
|
|
this.broadphase.collisionPairs(this, p1, p2);
|
|
doProfiling && (profile.broadphase = performance.now() - profilingStart);
|
|
var Nconstraints = constraints.length;
|
|
for (i = 0; i !== Nconstraints; i++) {
|
|
var c = constraints[i];
|
|
if (!c.collideConnected) for (var j = p1.length - 1; j >= 0; j -= 1) if (c.bodyA === p1[j] && c.bodyB === p2[j] || c.bodyB === p1[j] && c.bodyA === p2[j]) {
|
|
p1.splice(j, 1);
|
|
p2.splice(j, 1);
|
|
}
|
|
}
|
|
this.collisionMatrixTick();
|
|
doProfiling && (profilingStart = performance.now());
|
|
var oldcontacts = World_step_oldContacts;
|
|
var NoldContacts = contacts.length;
|
|
for (i = 0; i !== NoldContacts; i++) oldcontacts.push(contacts[i]);
|
|
contacts.length = 0;
|
|
var NoldFrictionEquations = this.frictionEquations.length;
|
|
for (i = 0; i !== NoldFrictionEquations; i++) frictionEquationPool.push(this.frictionEquations[i]);
|
|
this.frictionEquations.length = 0;
|
|
this.narrowphase.getContacts(p1, p2, this, contacts, oldcontacts, this.frictionEquations, frictionEquationPool);
|
|
if (0 == contacts.length && World.SLEEPING) return;
|
|
doProfiling && (profile.narrowphase = performance.now() - profilingStart);
|
|
doProfiling && (profilingStart = performance.now());
|
|
for (var i = 0; i < this.frictionEquations.length; i++) solver.addEquation(this.frictionEquations[i]);
|
|
var ncontacts = contacts.length;
|
|
for (var k = 0; k !== ncontacts; k++) {
|
|
var c = contacts[k];
|
|
var bi = c.bi, bj = c.bj, si = c.si, sj = c.sj;
|
|
si.material && sj.material ? si.material.restitution >= 0 && sj.material.restitution >= 0 && (c.restitution = si.material.restitution * sj.material.restitution) : bi.material && bj.material && bi.material.restitution >= 0 && bj.material.restitution >= 0 && (c.restitution = bi.material.restitution * bj.material.restitution);
|
|
solver.addEquation(c);
|
|
if (bi.allowSleep && bi.type === Body.DYNAMIC && bi.sleepState === Body.SLEEPING && bj.sleepState === Body.AWAKE && bj.type !== Body.STATIC) {
|
|
var speedSquaredB = bj.velocity.norm2() + bj.angularVelocity.norm2();
|
|
var speedLimitSquaredB = Math.pow(bj.sleepSpeedLimit, 2);
|
|
speedSquaredB >= 2 * speedLimitSquaredB && (bi._wakeUpAfterNarrowphase = true);
|
|
}
|
|
if (bj.allowSleep && bj.type === Body.DYNAMIC && bj.sleepState === Body.SLEEPING && bi.sleepState === Body.AWAKE && bi.type !== Body.STATIC) {
|
|
var speedSquaredA = bi.velocity.norm2() + bi.angularVelocity.norm2();
|
|
var speedLimitSquaredA = Math.pow(bi.sleepSpeedLimit, 2);
|
|
speedSquaredA >= 2 * speedLimitSquaredA && (bj._wakeUpAfterNarrowphase = true);
|
|
}
|
|
this.collisionMatrix.set(bi, bj, true);
|
|
if (!this.collisionMatrixPrevious.get(bi, bj)) {
|
|
World_step_collideEvent.body = bj;
|
|
World_step_collideEvent.contact = c;
|
|
bi.dispatchEvent(World_step_collideEvent);
|
|
World_step_collideEvent.body = bi;
|
|
bj.dispatchEvent(World_step_collideEvent);
|
|
}
|
|
this.bodyOverlapKeeper.set(bi.id, bj.id);
|
|
this.shapeOverlapKeeper.set(si.id, sj.id);
|
|
}
|
|
this.emitContactEvents();
|
|
if (doProfiling) {
|
|
profile.makeContactConstraints = performance.now() - profilingStart;
|
|
profilingStart = performance.now();
|
|
}
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
if (bi._wakeUpAfterNarrowphase) {
|
|
bi.wakeUp();
|
|
bi._wakeUpAfterNarrowphase = false;
|
|
}
|
|
}
|
|
var Nconstraints = constraints.length;
|
|
for (i = 0; i !== Nconstraints; i++) {
|
|
var c = constraints[i];
|
|
c.update();
|
|
for (var j = 0, Neq = c.equations.length; j !== Neq; j++) {
|
|
var eq = c.equations[j];
|
|
solver.addEquation(eq);
|
|
}
|
|
}
|
|
solver.solve(dt, this);
|
|
doProfiling && (profile.solve = performance.now() - profilingStart);
|
|
solver.removeAllEquations();
|
|
var pow = Math.pow;
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
if (bi.type & DYNAMIC) {
|
|
var ld = pow(1 - bi.linearDamping, dt);
|
|
var v = bi.velocity;
|
|
v.mult(ld, v);
|
|
var av = bi.angularVelocity;
|
|
if (av) {
|
|
var ad = pow(1 - bi.angularDamping, dt);
|
|
av.mult(ad, av);
|
|
}
|
|
}
|
|
}
|
|
this.dispatchEvent(World_step_preStepEvent);
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
bi.preStep && bi.preStep.call(bi);
|
|
}
|
|
doProfiling && (profilingStart = performance.now());
|
|
var stepnumber = this.stepnumber;
|
|
var quatNormalize = stepnumber % (this.quatNormalizeSkip + 1) === 0;
|
|
var quatNormalizeFast = this.quatNormalizeFast;
|
|
for (i = 0; i !== N; i++) bodies[i].integrate(dt, quatNormalize, quatNormalizeFast);
|
|
this.clearForces();
|
|
this.broadphase.dirty = true;
|
|
doProfiling && (profile.integrate = performance.now() - profilingStart);
|
|
this.time += dt;
|
|
this.timeFixed += dt;
|
|
this.stepnumber += 1;
|
|
this.dispatchEvent(World_step_postStepEvent);
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
var postStep = bi.postStep;
|
|
postStep && postStep.call(bi);
|
|
}
|
|
if (this.allowSleep) {
|
|
for (i = 0; i !== N; i++) bodies[i].sleepTick(this.time);
|
|
World.SLEEPING = true;
|
|
for (i = 0; i !== N; i++) {
|
|
var bi = bodies[i];
|
|
if (bi.type != Body.STATIC && !bi.isSleeping()) {
|
|
World.SLEEPING = false;
|
|
break;
|
|
}
|
|
}
|
|
} else World.SLEEPING = false;
|
|
};
|
|
World.prototype.emitContactEvents = function() {
|
|
var additions = [];
|
|
var removals = [];
|
|
var beginContactEvent = {
|
|
type: "beginContact",
|
|
bodyA: null,
|
|
bodyB: null
|
|
};
|
|
var endContactEvent = {
|
|
type: "endContact",
|
|
bodyA: null,
|
|
bodyB: null
|
|
};
|
|
var beginShapeContactEvent = {
|
|
type: "beginShapeContact",
|
|
bodyA: null,
|
|
bodyB: null,
|
|
shapeA: null,
|
|
shapeB: null
|
|
};
|
|
var endShapeContactEvent = {
|
|
type: "endShapeContact",
|
|
bodyA: null,
|
|
bodyB: null,
|
|
shapeA: null,
|
|
shapeB: null
|
|
};
|
|
return function() {
|
|
var hasBeginContact = this.hasAnyEventListener("beginContact");
|
|
var hasEndContact = this.hasAnyEventListener("endContact");
|
|
(hasBeginContact || hasEndContact) && this.bodyOverlapKeeper.getDiff(additions, removals);
|
|
if (hasBeginContact) {
|
|
for (var i = 0, l = additions.length; i < l; i += 2) {
|
|
beginContactEvent.bodyA = this.getBodyById(additions[i]);
|
|
beginContactEvent.bodyB = this.getBodyById(additions[i + 1]);
|
|
this.dispatchEvent(beginContactEvent);
|
|
}
|
|
beginContactEvent.bodyA = beginContactEvent.bodyB = null;
|
|
}
|
|
if (hasEndContact) {
|
|
for (var i = 0, l = removals.length; i < l; i += 2) {
|
|
endContactEvent.bodyA = this.getBodyById(removals[i]);
|
|
endContactEvent.bodyB = this.getBodyById(removals[i + 1]);
|
|
this.dispatchEvent(endContactEvent);
|
|
}
|
|
endContactEvent.bodyA = endContactEvent.bodyB = null;
|
|
}
|
|
additions.length = removals.length = 0;
|
|
var hasBeginShapeContact = this.hasAnyEventListener("beginShapeContact");
|
|
var hasEndShapeContact = this.hasAnyEventListener("endShapeContact");
|
|
(hasBeginShapeContact || hasEndShapeContact) && this.shapeOverlapKeeper.getDiff(additions, removals);
|
|
if (hasBeginShapeContact) {
|
|
for (var i = 0, l = additions.length; i < l; i += 2) {
|
|
var shapeA = this.getShapeById(additions[i]);
|
|
var shapeB = this.getShapeById(additions[i + 1]);
|
|
beginShapeContactEvent.shapeA = shapeA;
|
|
beginShapeContactEvent.shapeB = shapeB;
|
|
beginShapeContactEvent.bodyA = shapeA.body;
|
|
beginShapeContactEvent.bodyB = shapeB.body;
|
|
this.dispatchEvent(beginShapeContactEvent);
|
|
}
|
|
beginShapeContactEvent.bodyA = beginShapeContactEvent.bodyB = beginShapeContactEvent.shapeA = beginShapeContactEvent.shapeB = null;
|
|
}
|
|
if (hasEndShapeContact) {
|
|
for (var i = 0, l = removals.length; i < l; i += 2) {
|
|
var shapeA = this.getShapeById(removals[i]);
|
|
var shapeB = this.getShapeById(removals[i + 1]);
|
|
endShapeContactEvent.shapeA = shapeA;
|
|
endShapeContactEvent.shapeB = shapeB;
|
|
endShapeContactEvent.bodyA = shapeA.body;
|
|
endShapeContactEvent.bodyB = shapeB.body;
|
|
this.dispatchEvent(endShapeContactEvent);
|
|
}
|
|
endShapeContactEvent.bodyA = endShapeContactEvent.bodyB = endShapeContactEvent.shapeA = endShapeContactEvent.shapeB = null;
|
|
}
|
|
};
|
|
}();
|
|
World.prototype.clearForces = function() {
|
|
var bodies = this.bodies;
|
|
var N = bodies.length;
|
|
for (var i = 0; i !== N; i++) {
|
|
var b = bodies[i], force = b.force, tau = b.torque;
|
|
b.force.set(0, 0, 0);
|
|
b.torque.set(0, 0, 0);
|
|
}
|
|
};
|
|
var cc_trigger = {
|
|
type: "cc-trigger",
|
|
event: "",
|
|
selfBody: null,
|
|
otherBody: null,
|
|
selfShape: null,
|
|
otherShape: null
|
|
};
|
|
var cc_collide = {
|
|
type: "cc-collide",
|
|
event: "",
|
|
body: null,
|
|
selfShape: null,
|
|
otherShape: null,
|
|
contacts: null
|
|
};
|
|
var cc_oldContacts = [];
|
|
World.prototype.emitTriggeredEvents = function() {
|
|
if (0 == this.substeps) return;
|
|
var key;
|
|
var data;
|
|
var i = this.triggerDic.getLength();
|
|
while (i--) {
|
|
key = this.triggerDic.getKeyByIndex(i);
|
|
data = this.triggerDic.getDataByKey(key);
|
|
if (null == data) continue;
|
|
var shapeA = data.si;
|
|
var shapeB = data.sj;
|
|
if (this.tm.get(shapeA, shapeB)) cc_trigger.event = "onTriggerStay"; else {
|
|
this.tm.set(shapeA, shapeB, true);
|
|
cc_trigger.event = "onTriggerEnter";
|
|
}
|
|
cc_trigger.selfShape = shapeA;
|
|
cc_trigger.otherShape = shapeB;
|
|
cc_trigger.selfBody = shapeA.body;
|
|
cc_trigger.otherBody = shapeB.body;
|
|
shapeA.dispatchEvent(cc_trigger);
|
|
cc_trigger.selfShape = shapeB;
|
|
cc_trigger.otherShape = shapeA;
|
|
cc_trigger.selfBody = shapeB.body;
|
|
cc_trigger.otherBody = shapeA.body;
|
|
shapeB.dispatchEvent(cc_trigger);
|
|
}
|
|
i = this.oldTriggerDic.getLength();
|
|
while (i > 0) {
|
|
i--;
|
|
key = this.oldTriggerDic.getKeyByIndex(i);
|
|
if (null != this.triggerDic.getDataByKey(key)) continue;
|
|
data = this.oldTriggerDic.getDataByKey(key);
|
|
if (null == data) continue;
|
|
var shapeA = data.si;
|
|
var shapeB = data.sj;
|
|
this.tm.set(shapeA, shapeB, false);
|
|
this.oldTriggerDic.del(shapeA.id, shapeB.id) && i--;
|
|
cc_trigger.event = "onTriggerExit";
|
|
cc_trigger.selfShape = shapeA;
|
|
cc_trigger.otherShape = shapeB;
|
|
cc_trigger.selfBody = shapeA.body;
|
|
cc_trigger.otherBody = shapeB.body;
|
|
shapeA.dispatchEvent(cc_trigger);
|
|
cc_trigger.selfShape = shapeB;
|
|
cc_trigger.otherShape = shapeA;
|
|
cc_trigger.selfBody = shapeB.body;
|
|
cc_trigger.otherBody = shapeA.body;
|
|
shapeB.dispatchEvent(cc_trigger);
|
|
}
|
|
this.triggerDic.reset();
|
|
};
|
|
World.prototype.emitCollisionEvents = function() {
|
|
if (0 == this.substeps) return;
|
|
var contacts = this.contacts;
|
|
var i = this.contacts.length;
|
|
while (i--) {
|
|
var c = contacts[i];
|
|
var si = c.si;
|
|
var sj = c.sj;
|
|
var item = this.contactsDic.get(si.id, sj.id);
|
|
null == item && (item = this.contactsDic.set(si.id, sj.id, []));
|
|
item.push(c);
|
|
}
|
|
var key;
|
|
var data;
|
|
var i = this.contactsDic.getLength();
|
|
while (i--) {
|
|
key = this.contactsDic.getKeyByIndex(i);
|
|
data = this.contactsDic.getDataByKey(key);
|
|
if (null == data) continue;
|
|
var si = data[0].si;
|
|
var sj = data[0].sj;
|
|
var bi = si.body;
|
|
var bj = sj.body;
|
|
if (this.cm.get(bi, bj)) cc_collide.event = "onCollisionStay"; else {
|
|
this.cm.set(bi, bj, true);
|
|
cc_collide.event = "onCollisionEnter";
|
|
}
|
|
cc_collide.bi = bi;
|
|
cc_collide.contact = data[0];
|
|
cc_collide.contacts = data;
|
|
cc_collide.body = bj;
|
|
cc_collide.selfShape = si;
|
|
cc_collide.otherShape = sj;
|
|
bi.dispatchEvent(cc_collide);
|
|
cc_collide.body = bi;
|
|
cc_collide.selfShape = sj;
|
|
cc_collide.otherShape = si;
|
|
bj.dispatchEvent(cc_collide);
|
|
}
|
|
var oldcontacts = cc_oldContacts;
|
|
for (i = oldcontacts.length; i--; ) {
|
|
var c = oldcontacts[i];
|
|
var si = c.si;
|
|
var sj = c.sj;
|
|
null == this.oldContactsDic.get(si.id, sj.id) && this.oldContactsDic.set(si.id, sj.id, c);
|
|
}
|
|
i = this.oldContactsDic.getLength();
|
|
while (i--) {
|
|
key = this.oldContactsDic.getKeyByIndex(i);
|
|
if (null == this.contactsDic.getDataByKey(key)) {
|
|
data = this.oldContactsDic.getDataByKey(key);
|
|
var si = data.si;
|
|
var sj = data.sj;
|
|
var bi = si.body;
|
|
var bj = sj.body;
|
|
if (this.cm.get(bi, bj) && (!bi.isSleeping() || !bj.isSleeping())) {
|
|
this.cm.set(bi, bj, false);
|
|
cc_collide.bi = bi;
|
|
cc_collide.contact = data;
|
|
cc_collide.event = "onCollisionExit";
|
|
cc_collide.body = bj;
|
|
cc_collide.selfShape = si;
|
|
cc_collide.otherShape = sj;
|
|
cc_collide.contacts.length = 0;
|
|
cc_collide.contacts.push(data);
|
|
bi.dispatchEvent(cc_collide);
|
|
cc_collide.body = bi;
|
|
cc_collide.selfShape = sj;
|
|
cc_collide.otherShape = si;
|
|
bj.dispatchEvent(cc_collide);
|
|
}
|
|
}
|
|
}
|
|
this.contactsDic.reset();
|
|
this.oldContactsDic.reset();
|
|
World_step_oldContacts = cc_oldContacts;
|
|
cc_oldContacts = this.contacts.slice();
|
|
this.contacts.length = 0;
|
|
};
|
|
}, {
|
|
"../collision/AABB": 3,
|
|
"../collision/ArrayCollisionMatrix": 4,
|
|
"../collision/NaiveBroadphase": 7,
|
|
"../collision/ObjectCollisionMatrix": 8,
|
|
"../collision/OverlapKeeper": 9,
|
|
"../collision/Ray": 10,
|
|
"../collision/RaycastResult": 11,
|
|
"../equations/ContactEquation": 20,
|
|
"../equations/FrictionEquation": 22,
|
|
"../material/ContactMaterial": 25,
|
|
"../material/Material": 26,
|
|
"../math/Quaternion": 30,
|
|
"../math/Vec3": 32,
|
|
"../objects/Body": 33,
|
|
"../shapes/Shape": 45,
|
|
"../solver/GSSolver": 48,
|
|
"../utils/EventTarget": 51,
|
|
"../utils/TupleDictionary": 54,
|
|
"./Narrowphase": 57
|
|
} ]
|
|
}, {}, [ 2 ])(2);
|
|
});
|
|
}).call(this, "undefined" !== typeof global ? global : "undefined" !== typeof self ? self : "undefined" !== typeof window ? window : {});
|
|
}, {} ]
|
|
}, {}, [ 10, 9 ]); |