|
@@ -15725,7 +15725,7 @@ var BABYLON;
|
|
|
* * A base64 string of in-line texture data, e.g. 'data:image/jpg;base64,/...'
|
|
|
* * An indicator that data being passed using the buffer parameter, e.g. 'data:mytexture.jpg'
|
|
|
* @param noMipmap defines a boolean indicating that no mipmaps shall be generated. Ignored for compressed textures. They must be in the file
|
|
|
- * @param invertY when true, image is flipped when loaded. You probably want true. Ignored for compressed textures. Must be flipped in the file
|
|
|
+ * @param invertY when true, image is flipped when loaded. You probably want true. Certain compressed textures may invert this if their default is inverted (eg. ktx)
|
|
|
* @param scene needed for loading to the correct scene
|
|
|
* @param samplingMode mode with should be used sample / access the texture (Default: BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
|
|
|
* @param onLoad optional callback to be called upon successful completion
|
|
@@ -15796,7 +15796,7 @@ var BABYLON;
|
|
|
customFallback = true;
|
|
|
excludeLoaders.push(loader);
|
|
|
BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
|
|
|
- _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
|
|
|
+ _this.createTexture(urlArg, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -15805,7 +15805,7 @@ var BABYLON;
|
|
|
texture.onLoadedObservable.remove(onLoadObserver);
|
|
|
}
|
|
|
if (BABYLON.Tools.UseFallbackTexture) {
|
|
|
- _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture);
|
|
|
+ _this.createTexture(BABYLON.Tools.fallbackTexture, noMipmap, texture.invertY, scene, samplingMode, null, onError, buffer, texture);
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -15821,7 +15821,7 @@ var BABYLON;
|
|
|
onInternalError("TextureLoader failed to load data");
|
|
|
}
|
|
|
else {
|
|
|
- _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
|
|
|
+ _this._prepareWebGLTexture(texture, scene, width, height, texture.invertY, !loadMipmap, isCompressed, function () {
|
|
|
done();
|
|
|
return false;
|
|
|
}, samplingMode);
|
|
@@ -15844,7 +15844,7 @@ var BABYLON;
|
|
|
// in case of a webgl context lost
|
|
|
texture._buffer = img;
|
|
|
}
|
|
|
- _this._prepareWebGLTexture(texture, scene, img.width, img.height, invertY, noMipmap, false, function (potWidth, potHeight, continuationCallback) {
|
|
|
+ _this._prepareWebGLTexture(texture, scene, img.width, img.height, texture.invertY, noMipmap, false, function (potWidth, potHeight, continuationCallback) {
|
|
|
var gl = _this._gl;
|
|
|
var isPot = (img.width === potWidth && img.height === potHeight);
|
|
|
var internalFormat = format ? _this._getInternalFormat(format) : ((extension === ".jpg") ? gl.RGB : gl.RGBA);
|
|
@@ -31398,6 +31398,8 @@ var BABYLON;
|
|
|
this.next = null;
|
|
|
// Private
|
|
|
/** @hidden */
|
|
|
+ this._invertVScale = false;
|
|
|
+ /** @hidden */
|
|
|
this._initialSlot = -1;
|
|
|
/** @hidden */
|
|
|
this._designatedSlot = -1;
|
|
@@ -32480,6 +32482,9 @@ var BABYLON;
|
|
|
}
|
|
|
scene.getEngine().onBeforeTextureInitObservable.notifyObservers(_this);
|
|
|
var load = function () {
|
|
|
+ if (_this._texture && _this._texture._invertVScale) {
|
|
|
+ _this.vScale *= -1;
|
|
|
+ }
|
|
|
if (_this.onLoadObservable.hasObservers()) {
|
|
|
_this.onLoadObservable.notifyObservers(_this);
|
|
|
}
|
|
@@ -97727,6 +97732,7 @@ var BABYLON;
|
|
|
this._bodyUpdateRequired = false;
|
|
|
this._onBeforePhysicsStepCallbacks = new Array();
|
|
|
this._onAfterPhysicsStepCallbacks = new Array();
|
|
|
+ /** @hidden */
|
|
|
this._onPhysicsCollideCallbacks = [];
|
|
|
this._deltaPosition = BABYLON.Vector3.Zero();
|
|
|
this._isDisposed = false;
|
|
@@ -99884,6 +99890,632 @@ var BABYLON;
|
|
|
|
|
|
var BABYLON;
|
|
|
(function (BABYLON) {
|
|
|
+ /**
|
|
|
+ * AmmoJS Physics plugin
|
|
|
+ * @see https://doc.babylonjs.com/how_to/using_the_physics_engine
|
|
|
+ * @see https://github.com/kripken/ammo.js/
|
|
|
+ */
|
|
|
+ var AmmoJSPlugin = /** @class */ (function () {
|
|
|
+ /**
|
|
|
+ * Initializes the ammoJS plugin
|
|
|
+ * @param _useDeltaForWorldStep if the time between frames should be used when calculating physics steps (Default: true)
|
|
|
+ */
|
|
|
+ function AmmoJSPlugin(_useDeltaForWorldStep) {
|
|
|
+ if (_useDeltaForWorldStep === void 0) { _useDeltaForWorldStep = true; }
|
|
|
+ var _this = this;
|
|
|
+ this._useDeltaForWorldStep = _useDeltaForWorldStep;
|
|
|
+ /**
|
|
|
+ * Name of the plugin
|
|
|
+ */
|
|
|
+ this.name = "AmmoJSPlugin";
|
|
|
+ this._timeStep = 1 / 60;
|
|
|
+ this._maxSteps = 5;
|
|
|
+ this._tmpQuaternion = new BABYLON.Quaternion();
|
|
|
+ this._tmpContactCallbackResult = false;
|
|
|
+ if (typeof Ammo === "function") {
|
|
|
+ Ammo();
|
|
|
+ }
|
|
|
+ this.bjsAMMO = Ammo;
|
|
|
+ if (!this.isSupported()) {
|
|
|
+ BABYLON.Tools.Error("AmmoJS is not available. Please make sure you included the js file.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // Initialize the physics world
|
|
|
+ this._collisionConfiguration = new this.bjsAMMO.btDefaultCollisionConfiguration();
|
|
|
+ this._dispatcher = new this.bjsAMMO.btCollisionDispatcher(this._collisionConfiguration);
|
|
|
+ this._overlappingPairCache = new this.bjsAMMO.btDbvtBroadphase();
|
|
|
+ this._solver = new this.bjsAMMO.btSequentialImpulseConstraintSolver();
|
|
|
+ this.world = new this.bjsAMMO.btDiscreteDynamicsWorld(this._dispatcher, this._overlappingPairCache, this._solver, this._collisionConfiguration);
|
|
|
+ this._tmpAmmoConcreteContactResultCallback = new this.bjsAMMO.ConcreteContactResultCallback();
|
|
|
+ this._tmpAmmoConcreteContactResultCallback.addSingleResult = function () { _this._tmpContactCallbackResult = true; };
|
|
|
+ // Create temp ammo variables
|
|
|
+ this._tmpAmmoTransform = new this.bjsAMMO.btTransform();
|
|
|
+ this._tmpAmmoTransform.setIdentity();
|
|
|
+ this._tmpAmmoQuaternion = new this.bjsAMMO.btQuaternion(0, 0, 0, 1);
|
|
|
+ this._tmpAmmoVectorA = new this.bjsAMMO.btVector3(0, 0, 0);
|
|
|
+ this._tmpAmmoVectorB = new this.bjsAMMO.btVector3(0, 0, 0);
|
|
|
+ this._tmpAmmoVectorC = new this.bjsAMMO.btVector3(0, 0, 0);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Sets the gravity of the physics world (m/(s^2))
|
|
|
+ * @param gravity Gravity to set
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setGravity = function (gravity) {
|
|
|
+ this._tmpAmmoVectorA.setValue(gravity.x, gravity.y, gravity.z);
|
|
|
+ this.world.setGravity(this._tmpAmmoVectorA);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Amount of time to step forward on each frame (only used if useDeltaForWorldStep is false in the constructor)
|
|
|
+ * @param timeStep timestep to use in seconds
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setTimeStep = function (timeStep) {
|
|
|
+ this._timeStep = timeStep;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Gets the current timestep (only used if useDeltaForWorldStep is false in the constructor)
|
|
|
+ * @returns the current timestep in seconds
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getTimeStep = function () {
|
|
|
+ return this._timeStep;
|
|
|
+ };
|
|
|
+ // Ammo's contactTest and contactPairTest take a callback that runs synchronously, wrap them so that they are easier to consume
|
|
|
+ AmmoJSPlugin.prototype._isImpostorInContact = function (impostor) {
|
|
|
+ this._tmpContactCallbackResult = false;
|
|
|
+ this.world.contactTest(impostor.physicsBody, this._tmpAmmoConcreteContactResultCallback);
|
|
|
+ return this._tmpContactCallbackResult;
|
|
|
+ };
|
|
|
+ // Ammo's collision events have some weird quirks
|
|
|
+ // contactPairTest fires too many events as it fires events even when objects are close together but contactTest does not
|
|
|
+ // so only fire event if both contactTest and contactPairTest have a hit
|
|
|
+ AmmoJSPlugin.prototype._isImpostorPairInContact = function (impostorA, impostorB) {
|
|
|
+ this._tmpContactCallbackResult = false;
|
|
|
+ this.world.contactPairTest(impostorA.physicsBody, impostorB.physicsBody, this._tmpAmmoConcreteContactResultCallback);
|
|
|
+ return this._tmpContactCallbackResult;
|
|
|
+ };
|
|
|
+ // Ammo's behavior when maxSteps > 0 does not behave as described in docs
|
|
|
+ // @see http://www.bulletphysics.org/mediawiki-1.5.8/index.php/Stepping_The_World
|
|
|
+ //
|
|
|
+ // When maxSteps is 0 do the entire simulation in one step
|
|
|
+ // When maxSteps is > 0, run up to maxStep times, if on the last step the (remaining step - fixedTimeStep) is < fixedTimeStep, the remainder will be used for the step. (eg. if remainder is 1.001 and fixedTimeStep is 1 the last step will be 1.001, if instead it did 2 steps (1, 0.001) issues occuered when having a tiny step in ammo)
|
|
|
+ // Note: To get deterministic physics, timeStep would always need to be divisible by fixedTimeStep
|
|
|
+ AmmoJSPlugin.prototype._stepSimulation = function (timeStep, maxSteps, fixedTimeStep) {
|
|
|
+ if (timeStep === void 0) { timeStep = 1 / 60; }
|
|
|
+ if (maxSteps === void 0) { maxSteps = 10; }
|
|
|
+ if (fixedTimeStep === void 0) { fixedTimeStep = 1 / 60; }
|
|
|
+ if (maxSteps == 0) {
|
|
|
+ this.world.stepSimulation(timeStep, 0);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ while (maxSteps > 0 && timeStep > 0) {
|
|
|
+ if (timeStep - fixedTimeStep < fixedTimeStep) {
|
|
|
+ this.world.stepSimulation(timeStep, 0);
|
|
|
+ timeStep = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ timeStep -= fixedTimeStep;
|
|
|
+ this.world.stepSimulation(fixedTimeStep, 0);
|
|
|
+ }
|
|
|
+ maxSteps--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Moves the physics simulation forward delta seconds and updates the given physics imposters
|
|
|
+ * Prior to the step the imposters physics location is set to the position of the babylon meshes
|
|
|
+ * After the step the babylon meshes are set to the position of the physics imposters
|
|
|
+ * @param delta amount of time to step forward
|
|
|
+ * @param impostors array of imposters to update before/after the step
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.executeStep = function (delta, impostors) {
|
|
|
+ for (var _i = 0, impostors_1 = impostors; _i < impostors_1.length; _i++) {
|
|
|
+ var impostor = impostors_1[_i];
|
|
|
+ // Update physics world objects to match babylon world
|
|
|
+ impostor.beforeStep();
|
|
|
+ }
|
|
|
+ this._stepSimulation(this._useDeltaForWorldStep ? delta : this._timeStep, this._maxSteps);
|
|
|
+ for (var _a = 0, impostors_2 = impostors; _a < impostors_2.length; _a++) {
|
|
|
+ var mainImpostor = impostors_2[_a];
|
|
|
+ // After physics update make babylon world objects match physics world objects
|
|
|
+ mainImpostor.afterStep();
|
|
|
+ // Handle collision event
|
|
|
+ if (mainImpostor._onPhysicsCollideCallbacks.length > 0) {
|
|
|
+ if (this._isImpostorInContact(mainImpostor)) {
|
|
|
+ for (var _b = 0, _c = mainImpostor._onPhysicsCollideCallbacks; _b < _c.length; _b++) {
|
|
|
+ var collideCallback = _c[_b];
|
|
|
+ for (var _d = 0, _e = collideCallback.otherImpostors; _d < _e.length; _d++) {
|
|
|
+ var otherImpostor = _e[_d];
|
|
|
+ if (mainImpostor.physicsBody.isActive() || otherImpostor.physicsBody.isActive()) {
|
|
|
+ if (this._isImpostorPairInContact(mainImpostor, otherImpostor)) {
|
|
|
+ mainImpostor.onCollide({ body: otherImpostor.physicsBody });
|
|
|
+ otherImpostor.onCollide({ body: mainImpostor.physicsBody });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Applies an implulse on the imposter
|
|
|
+ * @param impostor imposter to apply impulse
|
|
|
+ * @param force amount of force to be applied to the imposter
|
|
|
+ * @param contactPoint the location to apply the impulse on the imposter
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.applyImpulse = function (impostor, force, contactPoint) {
|
|
|
+ var worldPoint = this._tmpAmmoVectorA;
|
|
|
+ var impulse = this._tmpAmmoVectorB;
|
|
|
+ worldPoint.setValue(contactPoint.x, contactPoint.y, contactPoint.z);
|
|
|
+ impulse.setValue(force.x, force.y, force.z);
|
|
|
+ impostor.physicsBody.applyImpulse(impulse, worldPoint);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Applies a force on the imposter
|
|
|
+ * @param impostor imposter to apply force
|
|
|
+ * @param force amount of force to be applied to the imposter
|
|
|
+ * @param contactPoint the location to apply the force on the imposter
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.applyForce = function (impostor, force, contactPoint) {
|
|
|
+ var worldPoint = this._tmpAmmoVectorA;
|
|
|
+ var impulse = this._tmpAmmoVectorB;
|
|
|
+ worldPoint.setValue(contactPoint.x, contactPoint.y, contactPoint.z);
|
|
|
+ impulse.setValue(force.x, force.y, force.z);
|
|
|
+ impostor.physicsBody.applyForce(impulse, worldPoint);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Creates a physics body using the plugin
|
|
|
+ * @param impostor the imposter to create the physics body on
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.generatePhysicsBody = function (impostor) {
|
|
|
+ impostor._pluginData = { toDispose: [] };
|
|
|
+ //parent-child relationship
|
|
|
+ if (impostor.parent) {
|
|
|
+ if (impostor.physicsBody) {
|
|
|
+ this.removePhysicsBody(impostor);
|
|
|
+ impostor.forceUpdate();
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (impostor.isBodyInitRequired()) {
|
|
|
+ var colShape = this._createShape(impostor);
|
|
|
+ var mass = impostor.getParam("mass");
|
|
|
+ impostor._pluginData.mass = mass;
|
|
|
+ var localInertia = new Ammo.btVector3(0, 0, 0);
|
|
|
+ var startTransform = new Ammo.btTransform();
|
|
|
+ startTransform.setIdentity();
|
|
|
+ if (mass !== 0) {
|
|
|
+ colShape.calculateLocalInertia(mass, localInertia);
|
|
|
+ }
|
|
|
+ this._tmpAmmoVectorA.setValue(impostor.object.position.x, impostor.object.position.y, impostor.object.position.z);
|
|
|
+ this._tmpAmmoQuaternion.setValue(impostor.object.rotationQuaternion.x, impostor.object.rotationQuaternion.y, impostor.object.rotationQuaternion.z, impostor.object.rotationQuaternion.w);
|
|
|
+ startTransform.setOrigin(this._tmpAmmoVectorA);
|
|
|
+ startTransform.setRotation(this._tmpAmmoQuaternion);
|
|
|
+ var myMotionState = new Ammo.btDefaultMotionState(startTransform);
|
|
|
+ var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, myMotionState, colShape, localInertia);
|
|
|
+ var body = new Ammo.btRigidBody(rbInfo);
|
|
|
+ // Make objects kinematic if it's mass is 0
|
|
|
+ if (mass === 0) {
|
|
|
+ body.setCollisionFlags(body.getCollisionFlags() | AmmoJSPlugin.KINEMATIC_FLAG);
|
|
|
+ body.setActivationState(AmmoJSPlugin.DISABLE_DEACTIVATION_FLAG);
|
|
|
+ }
|
|
|
+ body.setRestitution(impostor.getParam("restitution"));
|
|
|
+ this.world.addRigidBody(body);
|
|
|
+ impostor.physicsBody = body;
|
|
|
+ impostor._pluginData.toDispose.concat([body, rbInfo, myMotionState, startTransform, localInertia, colShape]);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Removes the physics body from the imposter and disposes of the body's memory
|
|
|
+ * @param impostor imposter to remove the physics body from
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.removePhysicsBody = function (impostor) {
|
|
|
+ var _this = this;
|
|
|
+ if (this.world) {
|
|
|
+ this.world.removeRigidBody(impostor.physicsBody);
|
|
|
+ impostor._pluginData.toDispose.forEach(function (d) {
|
|
|
+ _this.bjsAMMO.destroy(d);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Generates a joint
|
|
|
+ * @param impostorJoint the imposter joint to create the joint with
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.generateJoint = function (impostorJoint) {
|
|
|
+ var mainBody = impostorJoint.mainImpostor.physicsBody;
|
|
|
+ var connectedBody = impostorJoint.connectedImpostor.physicsBody;
|
|
|
+ if (!mainBody || !connectedBody) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var jointData = impostorJoint.joint.jointData;
|
|
|
+ if (!jointData.mainPivot) {
|
|
|
+ jointData.mainPivot = new BABYLON.Vector3(0, 0, 0);
|
|
|
+ }
|
|
|
+ if (!jointData.connectedPivot) {
|
|
|
+ jointData.connectedPivot = new BABYLON.Vector3(0, 0, 0);
|
|
|
+ }
|
|
|
+ var joint;
|
|
|
+ switch (impostorJoint.joint.type) {
|
|
|
+ case BABYLON.PhysicsJoint.BallAndSocketJoint:
|
|
|
+ joint = new Ammo.btPoint2PointConstraint(mainBody, connectedBody, new Ammo.btVector3(jointData.mainPivot.x, jointData.mainPivot.y, jointData.mainPivot.z), new Ammo.btVector3(jointData.connectedPivot.x, jointData.connectedPivot.y, jointData.connectedPivot.z));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ BABYLON.Tools.Warn("JointType not currently supported by the Ammo plugin, falling back to PhysicsJoint.BallAndSocketJoint");
|
|
|
+ joint = new Ammo.btPoint2PointConstraint(mainBody, connectedBody, new Ammo.btVector3(jointData.mainPivot.x, jointData.mainPivot.y, jointData.mainPivot.z), new Ammo.btVector3(jointData.connectedPivot.x, jointData.connectedPivot.y, jointData.connectedPivot.z));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ this.world.addConstraint(joint, true);
|
|
|
+ impostorJoint.joint.physicsJoint = joint;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Removes a joint
|
|
|
+ * @param impostorJoint the imposter joint to remove the joint from
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.removeJoint = function (impostorJoint) {
|
|
|
+ this.world.removeConstraint(impostorJoint.joint.physicsJoint);
|
|
|
+ };
|
|
|
+ // adds all verticies (including child verticies) to the triangle mesh
|
|
|
+ AmmoJSPlugin.prototype._addMeshVerts = function (btTriangleMesh, topLevelObject, object) {
|
|
|
+ var _this = this;
|
|
|
+ var triangleCount = 0;
|
|
|
+ if (object && object.getIndices && object.getWorldMatrix && object.getChildMeshes) {
|
|
|
+ var indices = object.getIndices();
|
|
|
+ if (!indices) {
|
|
|
+ indices = [];
|
|
|
+ }
|
|
|
+ var vertexPositions = object.getVerticesData(BABYLON.VertexBuffer.PositionKind);
|
|
|
+ if (!vertexPositions) {
|
|
|
+ vertexPositions = [];
|
|
|
+ }
|
|
|
+ object.computeWorldMatrix(false);
|
|
|
+ var faceCount = indices.length / 3;
|
|
|
+ for (var i = 0; i < faceCount; i++) {
|
|
|
+ var triPoints = [];
|
|
|
+ for (var point = 0; point < 3; point++) {
|
|
|
+ var v = new BABYLON.Vector3(vertexPositions[(indices[(i * 3) + point] * 3) + 0], vertexPositions[(indices[(i * 3) + point] * 3) + 1], vertexPositions[(indices[(i * 3) + point] * 3) + 2]);
|
|
|
+ v = BABYLON.Vector3.TransformCoordinates(v, object.getWorldMatrix());
|
|
|
+ v.subtractInPlace(topLevelObject.position);
|
|
|
+ var vec;
|
|
|
+ if (point == 0) {
|
|
|
+ vec = this._tmpAmmoVectorA;
|
|
|
+ }
|
|
|
+ else if (point == 1) {
|
|
|
+ vec = this._tmpAmmoVectorB;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ vec = this._tmpAmmoVectorC;
|
|
|
+ }
|
|
|
+ vec.setValue(v.x, v.y, v.z);
|
|
|
+ triPoints.push(vec);
|
|
|
+ }
|
|
|
+ btTriangleMesh.addTriangle(triPoints[0], triPoints[1], triPoints[2]);
|
|
|
+ triangleCount++;
|
|
|
+ }
|
|
|
+ object.getChildMeshes().forEach(function (m) {
|
|
|
+ triangleCount += _this._addMeshVerts(btTriangleMesh, topLevelObject, m);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return triangleCount;
|
|
|
+ };
|
|
|
+ AmmoJSPlugin.prototype._createShape = function (impostor, ignoreChildren) {
|
|
|
+ var _this = this;
|
|
|
+ if (ignoreChildren === void 0) { ignoreChildren = false; }
|
|
|
+ var object = impostor.object;
|
|
|
+ var returnValue;
|
|
|
+ var extendSize = impostor.getObjectExtendSize();
|
|
|
+ if (!ignoreChildren) {
|
|
|
+ var meshChildren = impostor.object.getChildMeshes ? impostor.object.getChildMeshes(true) : [];
|
|
|
+ if (meshChildren.length > 0) {
|
|
|
+ returnValue = new Ammo.btCompoundShape();
|
|
|
+ // Add shape of all children to the compound shape
|
|
|
+ meshChildren.forEach(function (childMesh) {
|
|
|
+ var childImpostor = childMesh.getPhysicsImpostor();
|
|
|
+ if (childImpostor) {
|
|
|
+ var shape = _this._createShape(childImpostor);
|
|
|
+ _this._tmpAmmoTransform.getOrigin().setValue(childMesh.position.x, childMesh.position.y, childMesh.position.z);
|
|
|
+ _this._tmpAmmoQuaternion.setValue(childMesh.rotationQuaternion.x, childMesh.rotationQuaternion.y, childMesh.rotationQuaternion.z, childMesh.rotationQuaternion.w);
|
|
|
+ _this._tmpAmmoTransform.setRotation(_this._tmpAmmoQuaternion);
|
|
|
+ returnValue.addChildShape(_this._tmpAmmoTransform, shape);
|
|
|
+ childImpostor.dispose();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // Add parents shape as a child if present
|
|
|
+ var shape = this._createShape(impostor, true);
|
|
|
+ if (shape) {
|
|
|
+ this._tmpAmmoTransform.getOrigin().setValue(0, 0, 0);
|
|
|
+ //this._tmpAmmoQuaternion = new this.BJSAMMO.btQuaternion(0,0,0,1);
|
|
|
+ this._tmpAmmoQuaternion.setValue(0, 0, 0, 1);
|
|
|
+ this._tmpAmmoTransform.setRotation(this._tmpAmmoQuaternion);
|
|
|
+ returnValue.addChildShape(this._tmpAmmoTransform, shape);
|
|
|
+ }
|
|
|
+ return returnValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ switch (impostor.type) {
|
|
|
+ case BABYLON.PhysicsImpostor.SphereImpostor:
|
|
|
+ returnValue = new Ammo.btSphereShape(extendSize.x / 2);
|
|
|
+ break;
|
|
|
+ case BABYLON.PhysicsImpostor.CylinderImpostor:
|
|
|
+ this._tmpAmmoVectorA.setValue(extendSize.x / 2, extendSize.y / 2, extendSize.z / 2);
|
|
|
+ returnValue = new Ammo.btCylinderShape(this._tmpAmmoVectorA);
|
|
|
+ break;
|
|
|
+ case BABYLON.PhysicsImpostor.PlaneImpostor:
|
|
|
+ case BABYLON.PhysicsImpostor.BoxImpostor:
|
|
|
+ this._tmpAmmoVectorA.setValue(extendSize.x / 2, extendSize.y / 2, extendSize.z / 2);
|
|
|
+ returnValue = new Ammo.btBoxShape(this._tmpAmmoVectorA);
|
|
|
+ break;
|
|
|
+ case BABYLON.PhysicsImpostor.MeshImpostor:
|
|
|
+ var tetraMesh = new Ammo.btTriangleMesh();
|
|
|
+ impostor._pluginData.toDispose.concat([tetraMesh]);
|
|
|
+ var triangeCount = this._addMeshVerts(tetraMesh, object, object);
|
|
|
+ if (triangeCount == 0) {
|
|
|
+ returnValue = new Ammo.btCompoundShape();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ returnValue = new Ammo.btBvhTriangleMeshShape(tetraMesh);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return returnValue;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets the physics body position/rotation from the babylon mesh's position/rotation
|
|
|
+ * @param impostor imposter containing the physics body and babylon object
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setTransformationFromPhysicsBody = function (impostor) {
|
|
|
+ impostor.physicsBody.getMotionState().getWorldTransform(this._tmpAmmoTransform);
|
|
|
+ impostor.object.position.set(this._tmpAmmoTransform.getOrigin().x(), this._tmpAmmoTransform.getOrigin().y(), this._tmpAmmoTransform.getOrigin().z());
|
|
|
+ if (!impostor.object.rotationQuaternion) {
|
|
|
+ if (impostor.object.rotation) {
|
|
|
+ this._tmpQuaternion.set(this._tmpAmmoTransform.getRotation().x(), this._tmpAmmoTransform.getRotation().y(), this._tmpAmmoTransform.getRotation().z(), this._tmpAmmoTransform.getRotation().w());
|
|
|
+ this._tmpQuaternion.toEulerAnglesToRef(impostor.object.rotation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ impostor.object.rotationQuaternion.set(this._tmpAmmoTransform.getRotation().x(), this._tmpAmmoTransform.getRotation().y(), this._tmpAmmoTransform.getRotation().z(), this._tmpAmmoTransform.getRotation().w());
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets the babylon object's position/rotation from the physics body's position/rotation
|
|
|
+ * @param impostor imposter containing the physics body and babylon object
|
|
|
+ * @param newPosition new position
|
|
|
+ * @param newRotation new rotation
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setPhysicsBodyTransformation = function (impostor, newPosition, newRotation) {
|
|
|
+ var trans = impostor.physicsBody.getWorldTransform();
|
|
|
+ // If rotation/position has changed update and activate riged body
|
|
|
+ if (trans.getOrigin().x() != newPosition.x ||
|
|
|
+ trans.getOrigin().y() != newPosition.y ||
|
|
|
+ trans.getOrigin().z() != newPosition.z ||
|
|
|
+ trans.getRotation().x() != newRotation.x ||
|
|
|
+ trans.getRotation().y() != newRotation.y ||
|
|
|
+ trans.getRotation().z() != newRotation.z ||
|
|
|
+ trans.getRotation().w() != newRotation.w) {
|
|
|
+ this._tmpAmmoVectorA.setValue(newPosition.x, newPosition.y, newPosition.z);
|
|
|
+ trans.setOrigin(this._tmpAmmoVectorA);
|
|
|
+ this._tmpAmmoQuaternion.setValue(newRotation.x, newRotation.y, newRotation.z, newRotation.w);
|
|
|
+ trans.setRotation(this._tmpAmmoQuaternion);
|
|
|
+ impostor.physicsBody.setWorldTransform(trans);
|
|
|
+ if (impostor.mass == 0) {
|
|
|
+ // Kinematic objects must be updated using motion state
|
|
|
+ var motionState = impostor.physicsBody.getMotionState();
|
|
|
+ if (motionState) {
|
|
|
+ motionState.setWorldTransform(trans);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ impostor.physicsBody.activate();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * If this plugin is supported
|
|
|
+ * @returns true if its supported
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.isSupported = function () {
|
|
|
+ return this.bjsAMMO !== undefined;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets the linear velocity of the physics body
|
|
|
+ * @param impostor imposter to set the velocity on
|
|
|
+ * @param velocity velocity to set
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setLinearVelocity = function (impostor, velocity) {
|
|
|
+ this._tmpAmmoVectorA.setValue(velocity.x, velocity.y, velocity.z);
|
|
|
+ impostor.physicsBody.setLinearVelocity(this._tmpAmmoVectorA);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets the angular velocity of the physics body
|
|
|
+ * @param impostor imposter to set the velocity on
|
|
|
+ * @param velocity velocity to set
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
|
|
|
+ this._tmpAmmoVectorA.setValue(velocity.x, velocity.y, velocity.z);
|
|
|
+ impostor.physicsBody.setAngularVelocity(this._tmpAmmoVectorA);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * gets the linear velocity
|
|
|
+ * @param impostor imposter to get linear velocity from
|
|
|
+ * @returns linear velocity
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getLinearVelocity = function (impostor) {
|
|
|
+ var v = impostor.physicsBody.getLinearVelocity();
|
|
|
+ if (!v) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return new BABYLON.Vector3(v.x(), v.y(), v.z());
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * gets the angular velocity
|
|
|
+ * @param impostor imposter to get angular velocity from
|
|
|
+ * @returns angular velocity
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getAngularVelocity = function (impostor) {
|
|
|
+ var v = impostor.physicsBody.getAngularVelocity();
|
|
|
+ if (!v) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return new BABYLON.Vector3(v.x(), v.y(), v.z());
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets the mass of physics body
|
|
|
+ * @param impostor imposter to set the mass on
|
|
|
+ * @param mass mass to set
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setBodyMass = function (impostor, mass) {
|
|
|
+ impostor.physicsBody.setMassProps(mass);
|
|
|
+ impostor._pluginData.mass = mass;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Gets the mass of the physics body
|
|
|
+ * @param impostor imposter to get the mass from
|
|
|
+ * @returns mass
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getBodyMass = function (impostor) {
|
|
|
+ return impostor._pluginData.mass;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Gets friction of the impostor
|
|
|
+ * @param impostor impostor to get friction from
|
|
|
+ * @returns friction value
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getBodyFriction = function (impostor) {
|
|
|
+ return impostor.physicsBody.getFriction();
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets friction of the impostor
|
|
|
+ * @param impostor impostor to set friction on
|
|
|
+ * @param friction friction value
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setBodyFriction = function (impostor, friction) {
|
|
|
+ impostor.physicsBody.setFriction(friction);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Gets restitution of the impostor
|
|
|
+ * @param impostor impostor to get restitution from
|
|
|
+ * @returns restitution value
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getBodyRestitution = function (impostor) {
|
|
|
+ return impostor.physicsBody.getRestitution();
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets resitution of the impostor
|
|
|
+ * @param impostor impostor to set resitution on
|
|
|
+ * @param restitution resitution value
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setBodyRestitution = function (impostor, restitution) {
|
|
|
+ impostor.physicsBody.setRestitution(restitution);
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sleeps the physics body and stops it from being active
|
|
|
+ * @param impostor impostor to sleep
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.sleepBody = function (impostor) {
|
|
|
+ BABYLON.Tools.Warn("sleepBody is not currently supported by the Ammo physics plugin");
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Activates the physics body
|
|
|
+ * @param impostor impostor to activate
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.wakeUpBody = function (impostor) {
|
|
|
+ impostor.physicsBody.activate();
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Updates the distance parameters of the joint
|
|
|
+ * @param joint joint to update
|
|
|
+ * @param maxDistance maximum distance of the joint
|
|
|
+ * @param minDistance minimum distance of the joint
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
|
|
|
+ BABYLON.Tools.Warn("updateDistanceJoint is not currently supported by the Ammo physics plugin");
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets a motor on the joint
|
|
|
+ * @param joint joint to set motor on
|
|
|
+ * @param speed speed of the motor
|
|
|
+ * @param maxForce maximum force of the motor
|
|
|
+ * @param motorIndex index of the motor
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
|
|
|
+ BABYLON.Tools.Warn("setMotor is not currently supported by the Ammo physics plugin");
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Sets the motors limit
|
|
|
+ * @param joint joint to set limit on
|
|
|
+ * @param upperLimit upper limit
|
|
|
+ * @param lowerLimit lower limit
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit) {
|
|
|
+ BABYLON.Tools.Warn("setLimit is not currently supported by the Ammo physics plugin");
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Syncs the position and rotation of a mesh with the impostor
|
|
|
+ * @param mesh mesh to sync
|
|
|
+ * @param impostor impostor to update the mesh with
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.syncMeshWithImpostor = function (mesh, impostor) {
|
|
|
+ var body = impostor.physicsBody;
|
|
|
+ body.getMotionState().getWorldTransform(this._tmpAmmoTransform);
|
|
|
+ mesh.position.x = this._tmpAmmoTransform.getOrigin().x();
|
|
|
+ mesh.position.y = this._tmpAmmoTransform.getOrigin().y();
|
|
|
+ mesh.position.z = this._tmpAmmoTransform.getOrigin().z();
|
|
|
+ if (mesh.rotationQuaternion) {
|
|
|
+ mesh.rotationQuaternion.x = this._tmpAmmoTransform.getRotation().x();
|
|
|
+ mesh.rotationQuaternion.y = this._tmpAmmoTransform.getRotation().y();
|
|
|
+ mesh.rotationQuaternion.z = this._tmpAmmoTransform.getRotation().z();
|
|
|
+ mesh.rotationQuaternion.w = this._tmpAmmoTransform.getRotation().w();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Gets the radius of the impostor
|
|
|
+ * @param impostor impostor to get radius from
|
|
|
+ * @returns the radius
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getRadius = function (impostor) {
|
|
|
+ var exntend = impostor.getObjectExtendSize();
|
|
|
+ return exntend.x / 2;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Gets the box size of the impostor
|
|
|
+ * @param impostor impostor to get box size from
|
|
|
+ * @param result the resulting box size
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.getBoxSizeToRef = function (impostor, result) {
|
|
|
+ var exntend = impostor.getObjectExtendSize();
|
|
|
+ result.x = exntend.x;
|
|
|
+ result.y = exntend.y;
|
|
|
+ result.z = exntend.z;
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * Disposes of the impostor
|
|
|
+ */
|
|
|
+ AmmoJSPlugin.prototype.dispose = function () {
|
|
|
+ // Dispose of world
|
|
|
+ Ammo.destroy(this.world);
|
|
|
+ Ammo.destroy(this._solver);
|
|
|
+ Ammo.destroy(this._overlappingPairCache);
|
|
|
+ Ammo.destroy(this._dispatcher);
|
|
|
+ Ammo.destroy(this._collisionConfiguration);
|
|
|
+ // Dispose of tmp variables
|
|
|
+ Ammo.destroy(this._tmpAmmoVectorA);
|
|
|
+ Ammo.destroy(this._tmpAmmoVectorB);
|
|
|
+ Ammo.destroy(this._tmpAmmoVectorC);
|
|
|
+ Ammo.destroy(this._tmpAmmoTransform);
|
|
|
+ Ammo.destroy(this._tmpAmmoQuaternion);
|
|
|
+ Ammo.destroy(this._tmpAmmoConcreteContactResultCallback);
|
|
|
+ this.world = null;
|
|
|
+ };
|
|
|
+ AmmoJSPlugin.KINEMATIC_FLAG = 2;
|
|
|
+ AmmoJSPlugin.DISABLE_DEACTIVATION_FLAG = 4;
|
|
|
+ return AmmoJSPlugin;
|
|
|
+ }());
|
|
|
+ BABYLON.AmmoJSPlugin = AmmoJSPlugin;
|
|
|
+})(BABYLON || (BABYLON = {}));
|
|
|
+
|
|
|
+//# sourceMappingURL=babylon.ammoJSPlugin.js.map
|
|
|
+
|
|
|
+var BABYLON;
|
|
|
+(function (BABYLON) {
|
|
|
/** @hidden */
|
|
|
var OimoJSPlugin = /** @class */ (function () {
|
|
|
function OimoJSPlugin(iterations) {
|
|
@@ -101635,6 +102267,10 @@ var BABYLON;
|
|
|
*/
|
|
|
KTXTextureLoader.prototype.transformUrl = function (rootUrl, textureFormatInUse) {
|
|
|
var lastDot = rootUrl.lastIndexOf('.');
|
|
|
+ if (lastDot != -1 && rootUrl.substring(lastDot + 1) == "ktx") {
|
|
|
+ // Already transformed
|
|
|
+ return rootUrl;
|
|
|
+ }
|
|
|
return (lastDot > -1 ? rootUrl.substring(0, lastDot) : rootUrl) + textureFormatInUse;
|
|
|
};
|
|
|
/**
|
|
@@ -101660,6 +102296,8 @@ var BABYLON;
|
|
|
if (Array.isArray(data)) {
|
|
|
return;
|
|
|
}
|
|
|
+ // Need to invert vScale as invertY via UNPACK_FLIP_Y_WEBGL is not supported by compressed texture
|
|
|
+ texture._invertVScale = !texture.invertY;
|
|
|
var engine = texture.getEngine();
|
|
|
var ktx = new BABYLON.KhronosTextureContainer(data, 6);
|
|
|
var loadMipmap = ktx.numberOfMipmapLevels > 1 && texture.generateMipMaps;
|
|
@@ -101677,6 +102315,8 @@ var BABYLON;
|
|
|
* @param callback defines the method to call once ready to upload
|
|
|
*/
|
|
|
KTXTextureLoader.prototype.loadData = function (data, texture, callback) {
|
|
|
+ // Need to invert vScale as invertY via UNPACK_FLIP_Y_WEBGL is not supported by compressed texture
|
|
|
+ texture._invertVScale = !texture.invertY;
|
|
|
var ktx = new BABYLON.KhronosTextureContainer(data, 1);
|
|
|
callback(ktx.pixelWidth, ktx.pixelHeight, false, true, function () {
|
|
|
ktx.uploadLevels(texture, texture.generateMipMaps);
|