@enable3d/ammo-physics
Advanced tools
Comparing version 0.18.0 to 0.19.0
@@ -11,2 +11,4 @@ /** | ||
export { ExtendedMesh }; | ||
import { ExtendedGroup } from '@enable3d/common/dist/extendedGroup'; | ||
export { ExtendedGroup }; | ||
import EventEmitter from 'eventemitter3'; | ||
@@ -81,3 +83,3 @@ import { Vector3, Quaternion, Scene, Euler } from '@enable3d/three-wrapper/dist/index'; | ||
get add(): { | ||
collider: (object1: ExtendedObject3D, object2: ExtendedObject3D, eventCallback: (event: "end" | "start" | "collision") => void) => void; | ||
collider: (object1: ExtendedObject3D, object2: ExtendedObject3D, eventCallback: (event: Types.CollisionEvent) => void) => void; | ||
constraints: { | ||
@@ -84,0 +86,0 @@ lock: (body: PhysicsBody, targetBody: PhysicsBody) => Ammo.btGeneric6DofConstraint; |
@@ -55,2 +55,4 @@ "use strict"; | ||
exports.ExtendedMesh = extendedMesh_1.ExtendedMesh; | ||
var extendedGroup_1 = require("@enable3d/common/dist/extendedGroup"); | ||
exports.ExtendedGroup = extendedGroup_1.ExtendedGroup; | ||
var shapes_1 = __importDefault(require("./shapes")); | ||
@@ -63,3 +65,3 @@ var constraints_1 = __importDefault(require("./constraints")); | ||
var factories_1 = __importDefault(require("@enable3d/common/dist/factories")); | ||
var events_1 = __importDefault(require("./events")); | ||
var colliderEvents_1 = __importDefault(require("./colliderEvents")); | ||
var index_2 = require("@enable3d/three-wrapper/dist/index"); | ||
@@ -159,3 +161,3 @@ var debugDrawer_1 = __importDefault(require("./debugDrawer")); | ||
} | ||
this.events = new events_1.default(); | ||
this.events = new colliderEvents_1.default(); | ||
this.factory = new factories_1.default(this.scene); | ||
@@ -219,3 +221,4 @@ this.shapes = new shapes_1.default(this.factory, function (object, config) { | ||
var deltaTime = delta / 1000; | ||
this.physicsWorld.stepSimulation(deltaTime, this.config.maxSubSteps || 1, this.config.fixedTimeStep || 1 / 60); | ||
// must always satisfy the equation timeStep < maxSubSteps * fixedTimeStep | ||
this.physicsWorld.stepSimulation(deltaTime, this.config.maxSubSteps || 4, this.config.fixedTimeStep || 1 / 60); | ||
/** | ||
@@ -263,7 +266,7 @@ * Update rigid bodies | ||
} | ||
objThree.body.collided = false; | ||
} | ||
} | ||
var _loop_1 = function () { | ||
var contactManifold = this_1.dispatcher.getManifoldByIndexInternal(i); | ||
// check collisions | ||
for (var i = 0, il = this.dispatcher.getNumManifolds(); i < il; i++) { | ||
var contactManifold = this.dispatcher.getManifoldByIndexInternal(i); | ||
var key = Object.keys(contactManifold.getBody0())[0]; | ||
@@ -277,3 +280,3 @@ // @ts-ignore | ||
if (body0.name === '' && body1.name === '') | ||
return "continue"; | ||
continue; | ||
// @ts-ignore | ||
@@ -283,6 +286,6 @@ var ptr0 = body0[key]; | ||
var ptr1 = body1[key]; | ||
var threeObject0 = this_1.objectsAmmo[ptr0]; | ||
var threeObject1 = this_1.objectsAmmo[ptr1]; | ||
var threeObject0 = this.objectsAmmo[ptr0]; | ||
var threeObject1 = this.objectsAmmo[ptr1]; | ||
if (!threeObject0 || !threeObject1) { | ||
return "continue"; | ||
continue; | ||
} | ||
@@ -294,44 +297,56 @@ /** | ||
var breakable1 = threeObject1.body.breakable; | ||
var collided0 = threeObject0.body.collided; | ||
var collided1 = threeObject1.body.collided; | ||
var checkCollisions0 = (_a = threeObject0.body) === null || _a === void 0 ? void 0 : _a.checkCollisions; | ||
var checkCollisions1 = (_b = threeObject1.body) === null || _b === void 0 ? void 0 : _b.checkCollisions; | ||
/** | ||
* Handle collision events | ||
*/ | ||
if (checkCollisions0 || checkCollisions1) { | ||
// check if a collision between these object has already been processed | ||
var names = [threeObject0.name, threeObject1.name].sort(); | ||
var combinedName_1 = names[0] + "__" + names[1]; | ||
var event_1 = void 0; | ||
if (this_1.earlierDetectedCollisions.find(function (el) { return el.combinedName === combinedName_1; })) | ||
event_1 = 'colliding'; | ||
else | ||
event_1 = 'start'; | ||
detectedCollisions.push({ combinedName: combinedName_1, collision: true }); | ||
this_1.emit('collision', { bodies: [threeObject0, threeObject1], event: event_1 }); | ||
} | ||
if ((!breakable0 && !breakable1) || (collided0 && collided1)) { | ||
return "continue"; | ||
} | ||
if (!checkCollisions0 && !checkCollisions1 && !breakable0 && !breakable1) | ||
continue; | ||
var contact = false; | ||
var maxImpulse = 0; | ||
for (var j = 0, jl = contactManifold.getNumContacts(); j < jl; j++) { | ||
contactPoint = contactManifold.getContactPoint(j); | ||
if (contactPoint.getDistance() < 0) { | ||
var _loop_1 = function (j, jl) { | ||
var contactPoint = contactManifold.getContactPoint(j); | ||
// Distance definition: when the distance between objects is positive, they are separated. When the distance is negative, they are penetrating. Zero distance means exactly touching. | ||
// https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=5831 | ||
if (contactPoint.getDistance() <= 0) { | ||
contact = true; | ||
impulse = contactPoint.getAppliedImpulse(); | ||
var impulse = contactPoint.getAppliedImpulse(); | ||
if (impulse > maxImpulse) { | ||
maxImpulse = impulse; | ||
pos = contactPoint.get_m_positionWorldOnB(); | ||
normal = contactPoint.get_m_normalWorldOnB(); | ||
this_1.impactPoint.set(pos.x(), pos.y(), pos.z()); | ||
this_1.impactNormal.set(normal.x(), normal.y(), normal.z()); | ||
var impactPoint = contactPoint.get_m_positionWorldOnB(); | ||
var impactNormal = contactPoint.get_m_normalWorldOnB(); | ||
// handle collision events | ||
if (checkCollisions0 || checkCollisions1) { | ||
var names = [threeObject0.name, threeObject1.name].sort(); | ||
var combinedName_1 = names[0] + "__" + names[1]; | ||
var event_1 = { | ||
name: 'start', | ||
impactPoint: { x: impactPoint.x(), y: impactPoint.y(), z: impactPoint.z() }, | ||
impactNormal: { x: impactNormal.x(), y: impactNormal.y(), z: impactNormal.z() } | ||
}; | ||
if (this_1.earlierDetectedCollisions.find(function (el) { return el.combinedName === combinedName_1; })) | ||
event_1.name = 'collision'; | ||
// else event = 'start' | ||
if (!detectedCollisions.find(function (el) { return el.combinedName === combinedName_1; })) { | ||
detectedCollisions.push({ combinedName: combinedName_1, collision: true }); | ||
this_1.emit('collision', { bodies: [threeObject0, threeObject1], event: event_1 }); | ||
} | ||
} | ||
// get what ween need for the convex breaking | ||
if (breakable0 || breakable1) { | ||
this_1.impactPoint.set(impactPoint.x(), impactPoint.y(), impactPoint.z()); | ||
this_1.impactNormal.set(impactNormal.x(), impactNormal.y(), impactNormal.z()); | ||
} | ||
} | ||
return "break"; | ||
} | ||
}; | ||
var this_1 = this; | ||
for (var j = 0, jl = contactManifold.getNumContacts(); j < jl; j++) { | ||
var state_1 = _loop_1(j, jl); | ||
if (state_1 === "break") | ||
break; | ||
} | ||
} | ||
// If no point has contact, abort | ||
if (!contact) | ||
return "continue"; | ||
continue; | ||
if (!breakable0 && !breakable1) | ||
continue; | ||
/** | ||
@@ -345,7 +360,7 @@ * Check for breakable objects (subdivision) | ||
// TODO improve this | ||
this_1.emptyV3.set(0, 0, 0); | ||
this.emptyV3.set(0, 0, 0); | ||
threeObject0.userData = { | ||
mass: 1, | ||
velocity: this_1.emptyV3, | ||
angularVelocity: this_1.emptyV3, | ||
velocity: this.emptyV3, | ||
angularVelocity: this.emptyV3, | ||
breakable: breakable0, | ||
@@ -356,4 +371,4 @@ physicsBody: body0 | ||
mass: 1, | ||
velocity: this_1.emptyV3, | ||
angularVelocity: this_1.emptyV3, | ||
velocity: this.emptyV3, | ||
angularVelocity: this.emptyV3, | ||
breakable: breakable1, | ||
@@ -367,42 +382,31 @@ physicsBody: body1 | ||
// threeObject0 | ||
if (breakable0 && !collided0 && maxImpulse > fractureImpulse && threeObject0.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
debris = this_1.convexBreaker.subdivideByImpact(threeObject0, this_1.impactPoint, this_1.impactNormal, 1, 2); //, 1.5) | ||
numObjects = debris.length; | ||
if (breakable0 && maxImpulse > fractureImpulse && threeObject0.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
var debris = this.convexBreaker.subdivideByImpact(threeObject0, this.impactPoint, this.impactNormal, 1, 2); //, 1.5) | ||
var numObjects = debris.length; | ||
for (var j = 0; j < numObjects; j++) { | ||
vel = body0.getLinearVelocity(); | ||
angVel = body0.getAngularVelocity(); | ||
fragment = debris[j]; | ||
var vel = body0.getLinearVelocity(); | ||
var angVel = body0.getAngularVelocity(); | ||
var fragment = debris[j]; | ||
fragment.userData.velocity.set(vel.x(), vel.y(), vel.z()); | ||
fragment.userData.angularVelocity.set(angVel.x(), angVel.y(), angVel.z()); | ||
this_1.createDebrisFromBreakableObject(fragment, threeObject0); | ||
this.createDebrisFromBreakableObject(fragment, threeObject0); | ||
} | ||
this_1.objectsToRemove[this_1.numObjectsToRemove++] = threeObject0; | ||
threeObject0.body.collided = true; | ||
this.objectsToRemove[this.numObjectsToRemove++] = threeObject0; | ||
} | ||
// threeObject1 | ||
if (breakable1 && !collided1 && maxImpulse > fractureImpulse && threeObject1.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
debris = this_1.convexBreaker.subdivideByImpact(threeObject1, this_1.impactPoint, this_1.impactNormal, 1, 2); //, 1.5) | ||
numObjects = debris.length; | ||
if (breakable1 && maxImpulse > fractureImpulse && threeObject1.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
var debris = this.convexBreaker.subdivideByImpact(threeObject1, this.impactPoint, this.impactNormal, 1, 2); //, 1.5) | ||
var numObjects = debris.length; | ||
for (var j = 0; j < numObjects; j++) { | ||
vel = body1.getLinearVelocity(); | ||
angVel = body1.getAngularVelocity(); | ||
fragment = debris[j]; | ||
var vel = body1.getLinearVelocity(); | ||
var angVel = body1.getAngularVelocity(); | ||
var fragment = debris[j]; | ||
fragment.userData.velocity.set(vel.x(), vel.y(), vel.z()); | ||
fragment.userData.angularVelocity.set(angVel.x(), angVel.y(), angVel.z()); | ||
this_1.createDebrisFromBreakableObject(fragment, threeObject1); | ||
this.createDebrisFromBreakableObject(fragment, threeObject1); | ||
} | ||
this_1.objectsToRemove[this_1.numObjectsToRemove++] = threeObject1; | ||
threeObject1.body.collided = true; | ||
this.objectsToRemove[this.numObjectsToRemove++] = threeObject1; | ||
} | ||
}; | ||
var this_1 = this, contactPoint, impulse, pos, normal, debris, numObjects, vel, angVel, fragment, debris, numObjects, vel, angVel, fragment; | ||
/** | ||
* Check collisions | ||
*/ | ||
for (var i = 0, il = this.dispatcher.getNumManifolds(); i < il; i++) { | ||
_loop_1(); | ||
} | ||
/** | ||
* Remove objects | ||
*/ | ||
// remove objects | ||
for (var i = 0; i < this.numObjectsToRemove; i++) { | ||
@@ -412,5 +416,3 @@ this.removeDebris(this.objectsToRemove[i]); | ||
this.numObjectsToRemove = 0; | ||
/** | ||
* Handle collision end events | ||
*/ | ||
// handle collision end events | ||
this.earlierDetectedCollisions.forEach(function (el) { | ||
@@ -422,4 +424,5 @@ var combinedName = el.combinedName; | ||
var obj1 = _this.rigidBodies.find(function (obj) { return obj.name === split_1[1]; }); | ||
var event_2 = { name: 'end' }; | ||
if (obj0 && obj1) | ||
_this.emit('collision', { bodies: [obj0, obj1], event: 'end' }); | ||
_this.emit('collision', { bodies: [obj0, obj1], event: event_2 }); | ||
} | ||
@@ -426,0 +429,0 @@ }); |
@@ -10,5 +10,9 @@ /** | ||
protected physics: AmmoPhysics; | ||
protected _tmpBtVector3: Ammo.btVector3; | ||
protected _btRayCallback: Ammo.AllHitsRayResultCallback; | ||
constructor(physics: AmmoPhysics); | ||
getHitPointsWorld(): { | ||
x: number; | ||
y: number; | ||
z: number; | ||
}[]; | ||
getHitPointWorld(): { | ||
@@ -19,4 +23,9 @@ x: number; | ||
}[]; | ||
getHitNormalsWorld(): { | ||
x: number; | ||
y: number; | ||
z: number; | ||
}[]; | ||
getCollisionObjects(): ExtendedObject3D[]; | ||
} | ||
//# sourceMappingURL=allHitsRayResultCallback.d.ts.map |
@@ -12,3 +12,3 @@ "use strict"; | ||
} | ||
AllHitsRayResultCallback.prototype.getHitPointWorld = function () { | ||
AllHitsRayResultCallback.prototype.getHitPointsWorld = function () { | ||
var h = this._btRayCallback.get_m_hitPointWorld(); | ||
@@ -22,2 +22,16 @@ var points = []; | ||
}; | ||
// TODO: Remove this in future versions! | ||
AllHitsRayResultCallback.prototype.getHitPointWorld = function () { | ||
console.warn('[enable3d] Use getHitPointsWorld() instead of getHitPointWorld() for the AllHitsRayCaster!'); | ||
return this.getHitPointsWorld(); | ||
}; | ||
AllHitsRayResultCallback.prototype.getHitNormalsWorld = function () { | ||
var h = this._btRayCallback.get_m_hitNormalWorld(); | ||
var normals = []; | ||
for (var i = h.size() - 1; i >= 0; i--) { | ||
var hh = h.at(i); | ||
normals.push({ x: hh.x(), y: hh.y(), z: hh.z() }); | ||
} | ||
return normals; | ||
}; | ||
AllHitsRayResultCallback.prototype.getCollisionObjects = function () { | ||
@@ -28,3 +42,2 @@ var getPtr = function (obj) { | ||
var obs = []; | ||
// @ts-ignore | ||
var o = this._btRayCallback.get_m_collisionObjects(); | ||
@@ -31,0 +44,0 @@ for (var i = o.size() - 1; i >= 0; i--) { |
@@ -10,3 +10,2 @@ /** | ||
protected physics: AmmoPhysics; | ||
protected _tmpBtVector3: Ammo.btVector3; | ||
protected _btRayCallback: Ammo.ClosestRayResultCallback; | ||
@@ -19,4 +18,9 @@ constructor(physics: AmmoPhysics); | ||
}; | ||
getHitNormalWorld(): { | ||
x: number; | ||
y: number; | ||
z: number; | ||
}; | ||
getCollisionObject(): ExtendedObject3D; | ||
} | ||
//# sourceMappingURL=closestRayResultCallback.d.ts.map |
@@ -17,2 +17,7 @@ "use strict"; | ||
}; | ||
ClosestRayResultCallback.prototype.getHitNormalWorld = function () { | ||
var h = this._btRayCallback.get_m_hitNormalWorld(); | ||
var normal = { x: h.x(), y: h.y(), z: h.z() }; | ||
return normal; | ||
}; | ||
ClosestRayResultCallback.prototype.getCollisionObject = function () { | ||
@@ -19,0 +24,0 @@ var getPtr = function (obj) { |
@@ -11,11 +11,10 @@ /** | ||
protected physics: AmmoPhysics; | ||
protected _tmpBtVector3: Ammo.btVector3; | ||
readonly type: string; | ||
protected _btRayFrom: Ammo.btVector3; | ||
protected _btRayTo: Ammo.btVector3; | ||
protected _btRayCallback: any; | ||
protected initCallback: any; | ||
protected _btRayCallback: Ammo.RayResultCallback; | ||
constructor(physics: AmmoPhysics); | ||
setRayFromWorld(x?: number, y?: number, z?: number): void; | ||
setRayToWorld(x?: number, y?: number, z?: number): void; | ||
hasHit(): any; | ||
hasHit(): boolean; | ||
rayTest(): void; | ||
@@ -28,5 +27,5 @@ destroy(): void; | ||
} | ||
declare class ClosestRaycaster { | ||
declare class ClosestRaycaster implements Raycaster, ClosestRayResultCallback { | ||
protected physics: AmmoPhysics; | ||
protected _tmpBtVector3: Ammo.btVector3; | ||
readonly type = "closest"; | ||
protected _btRayFrom: Ammo.btVector3; | ||
@@ -37,5 +36,5 @@ protected _btRayTo: Ammo.btVector3; | ||
} | ||
declare class AllHitsRaycaster { | ||
declare class AllHitsRaycaster implements Raycaster, AllHitsRayResultCallback { | ||
protected physics: AmmoPhysics; | ||
protected _tmpBtVector3: Ammo.btVector3; | ||
readonly type = "allHits"; | ||
protected _btRayFrom: Ammo.btVector3; | ||
@@ -42,0 +41,0 @@ protected _btRayTo: Ammo.btVector3; |
@@ -23,3 +23,2 @@ "use strict"; | ||
this._btRayFrom.setValue(x, y, z); | ||
this._btRayCallback.set_m_rayFromWorld(this._btRayFrom); | ||
}; | ||
@@ -31,3 +30,2 @@ Raycaster.prototype.setRayToWorld = function (x, y, z) { | ||
this._btRayTo.setValue(x, y, z); | ||
this._btRayCallback.set_m_rayToWorld(this._btRayTo); | ||
}; | ||
@@ -38,9 +36,17 @@ Raycaster.prototype.hasHit = function () { | ||
Raycaster.prototype.rayTest = function () { | ||
if (typeof this._btRayCallback !== 'undefined') | ||
Ammo.destroy(this._btRayCallback); | ||
this._btRayCallback = | ||
this.type === 'closest' | ||
? new Ammo.ClosestRayResultCallback(this._btRayFrom, this._btRayTo) | ||
: new Ammo.AllHitsRayResultCallback(this._btRayFrom, this._btRayTo); | ||
this.physics.physicsWorld.rayTest(this._btRayFrom, this._btRayTo, this._btRayCallback); | ||
}; | ||
Raycaster.prototype.destroy = function () { | ||
Ammo.destroy(this._tmpBtVector3); | ||
Ammo.destroy(this._btRayFrom); | ||
Ammo.destroy(this._btRayTo); | ||
Ammo.destroy(this._btRayCallback); | ||
if (typeof this._btRayFrom !== 'undefined') | ||
Ammo.destroy(this._btRayFrom); | ||
if (typeof this._btRayTo !== 'undefined') | ||
Ammo.destroy(this._btRayTo); | ||
if (typeof this._btRayCallback !== 'undefined') | ||
Ammo.destroy(this._btRayCallback); | ||
}; | ||
@@ -52,6 +58,5 @@ return Raycaster; | ||
this.physics = physics; | ||
this._tmpBtVector3 = new Ammo.btVector3(0, 0, 0); | ||
this.type = 'closest'; | ||
this._btRayFrom = new Ammo.btVector3(0, 0, 0); | ||
this._btRayTo = new Ammo.btVector3(0, 0, 0); | ||
this._btRayCallback = new Ammo.ClosestRayResultCallback(this._tmpBtVector3, this._tmpBtVector3); | ||
} | ||
@@ -64,6 +69,5 @@ return ClosestRaycaster; | ||
this.physics = physics; | ||
this._tmpBtVector3 = new Ammo.btVector3(0, 0, 0); | ||
this.type = 'allHits'; | ||
this._btRayFrom = new Ammo.btVector3(0, 0, 0); | ||
this._btRayTo = new Ammo.btVector3(0, 0, 0); | ||
this._btRayCallback = new Ammo.AllHitsRayResultCallback(this._tmpBtVector3, this._tmpBtVector3); | ||
} | ||
@@ -70,0 +74,0 @@ return AllHitsRaycaster; |
{ | ||
"name": "@enable3d/ammo-physics", | ||
"version": "0.18.0", | ||
"version": "0.19.0", | ||
"description": "Physics Plugin for three.js", | ||
@@ -32,6 +32,9 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@enable3d/common": "^0.18.0", | ||
"@enable3d/three-wrapper": "^0.18.0", | ||
"@enable3d/common": "^0.19.0", | ||
"@enable3d/three-wrapper": "^0.19.0", | ||
"eventemitter3": "^4.0.0" | ||
}, | ||
"funding": { | ||
"url": "https://github.com/sponsors/yandeu" | ||
} | ||
} |
@@ -16,2 +16,5 @@ /** | ||
import { ExtendedGroup } from '@enable3d/common/dist/extendedGroup' | ||
export { ExtendedGroup } | ||
import Shapes from './shapes' | ||
@@ -24,3 +27,3 @@ import Constraints from './constraints' | ||
import Factories from '@enable3d/common/dist/factories' | ||
import Events from './events' | ||
import Events from './colliderEvents' | ||
import { REVISION } from '@enable3d/three-wrapper/dist/index' | ||
@@ -143,3 +146,3 @@ | ||
// remove from this.rigidBodies | ||
for (var i = 0; i < this.rigidBodies.length; i++) { | ||
for (let i = 0; i < this.rigidBodies.length; i++) { | ||
if (this.rigidBodies[i].name === name) { | ||
@@ -168,3 +171,3 @@ this.rigidBodies.splice(i, 1) | ||
this.numObjectsToRemove = 0 | ||
for (var i = 0; i < 500; i++) { | ||
for (let i = 0; i < 500; i++) { | ||
this.objectsToRemove[i] = null | ||
@@ -242,11 +245,13 @@ } | ||
const deltaTime = delta / 1000 | ||
this.physicsWorld.stepSimulation(deltaTime, this.config.maxSubSteps || 1, this.config.fixedTimeStep || 1 / 60) | ||
// must always satisfy the equation timeStep < maxSubSteps * fixedTimeStep | ||
this.physicsWorld.stepSimulation(deltaTime, this.config.maxSubSteps || 4, this.config.fixedTimeStep || 1 / 60) | ||
/** | ||
* Update rigid bodies | ||
*/ | ||
for (var i = 0, il = this.rigidBodies.length; i < il; i++) { | ||
var objThree = this.rigidBodies[i] | ||
var objPhys = objThree.body.ammo | ||
var ms = objPhys.getMotionState() | ||
for (let i = 0, il = this.rigidBodies.length; i < il; i++) { | ||
const objThree = this.rigidBodies[i] | ||
const objPhys = objThree.body.ammo | ||
const ms = objPhys.getMotionState() | ||
@@ -293,11 +298,7 @@ if (ms) { | ||
} | ||
objThree.body.collided = false | ||
} | ||
} | ||
/** | ||
* Check collisions | ||
*/ | ||
for (var i = 0, il = this.dispatcher.getNumManifolds(); i < il; i++) { | ||
// check collisions | ||
for (let i = 0, il = this.dispatcher.getNumManifolds(); i < il; i++) { | ||
const contactManifold = this.dispatcher.getManifoldByIndexInternal(i) | ||
@@ -319,2 +320,3 @@ const key = Object.keys(contactManifold.getBody0())[0] | ||
const ptr1 = body1[key] | ||
const threeObject0 = this.objectsAmmo[ptr0] as ExtendedObject3D | ||
@@ -333,41 +335,48 @@ const threeObject1 = this.objectsAmmo[ptr1] as ExtendedObject3D | ||
const collided0 = threeObject0.body.collided | ||
const collided1 = threeObject1.body.collided | ||
const checkCollisions0 = threeObject0.body?.checkCollisions | ||
const checkCollisions1 = threeObject1.body?.checkCollisions | ||
/** | ||
* Handle collision events | ||
*/ | ||
if (checkCollisions0 || checkCollisions1) { | ||
// check if a collision between these object has already been processed | ||
const names = [threeObject0.name, threeObject1.name].sort() | ||
const combinedName = `${names[0]}__${names[1]}` | ||
let event | ||
if (this.earlierDetectedCollisions.find(el => el.combinedName === combinedName)) event = 'colliding' | ||
else event = 'start' | ||
detectedCollisions.push({ combinedName, collision: true }) | ||
this.emit('collision', { bodies: [threeObject0, threeObject1], event }) | ||
} | ||
if (!checkCollisions0 && !checkCollisions1 && !breakable0 && !breakable1) continue | ||
if ((!breakable0 && !breakable1) || (collided0 && collided1)) { | ||
continue | ||
} | ||
let contact = false | ||
let maxImpulse = 0 | ||
for (var j = 0, jl = contactManifold.getNumContacts(); j < jl; j++) { | ||
var contactPoint = contactManifold.getContactPoint(j) | ||
for (let j = 0, jl = contactManifold.getNumContacts(); j < jl; j++) { | ||
const contactPoint = contactManifold.getContactPoint(j) | ||
if (contactPoint.getDistance() < 0) { | ||
// Distance definition: when the distance between objects is positive, they are separated. When the distance is negative, they are penetrating. Zero distance means exactly touching. | ||
// https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=5831 | ||
if (contactPoint.getDistance() <= 0) { | ||
contact = true | ||
var impulse = contactPoint.getAppliedImpulse() | ||
const impulse = contactPoint.getAppliedImpulse() | ||
if (impulse > maxImpulse) { | ||
maxImpulse = impulse | ||
var pos = contactPoint.get_m_positionWorldOnB() | ||
var normal = contactPoint.get_m_normalWorldOnB() | ||
this.impactPoint.set(pos.x(), pos.y(), pos.z()) | ||
this.impactNormal.set(normal.x(), normal.y(), normal.z()) | ||
const impactPoint = contactPoint.get_m_positionWorldOnB() | ||
const impactNormal = contactPoint.get_m_normalWorldOnB() | ||
// handle collision events | ||
if (checkCollisions0 || checkCollisions1) { | ||
const names = [threeObject0.name, threeObject1.name].sort() | ||
const combinedName = `${names[0]}__${names[1]}` | ||
let event: Types.CollisionEvent = { | ||
name: 'start', | ||
impactPoint: { x: impactPoint.x(), y: impactPoint.y(), z: impactPoint.z() }, | ||
impactNormal: { x: impactNormal.x(), y: impactNormal.y(), z: impactNormal.z() } | ||
} | ||
if (this.earlierDetectedCollisions.find(el => el.combinedName === combinedName)) event.name = 'collision' | ||
// else event = 'start' | ||
if (!detectedCollisions.find(el => el.combinedName === combinedName)) { | ||
detectedCollisions.push({ combinedName, collision: true }) | ||
this.emit('collision', { bodies: [threeObject0, threeObject1], event }) | ||
} | ||
} | ||
// get what ween need for the convex breaking | ||
if (breakable0 || breakable1) { | ||
this.impactPoint.set(impactPoint.x(), impactPoint.y(), impactPoint.z()) | ||
this.impactNormal.set(impactNormal.x(), impactNormal.y(), impactNormal.z()) | ||
} | ||
} | ||
@@ -382,2 +391,4 @@ | ||
if (!breakable0 && !breakable1) continue | ||
/** | ||
@@ -412,10 +423,10 @@ * Check for breakable objects (subdivision) | ||
// threeObject0 | ||
if (breakable0 && !collided0 && maxImpulse > fractureImpulse && threeObject0.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
var debris = this.convexBreaker.subdivideByImpact(threeObject0, this.impactPoint, this.impactNormal, 1, 2) //, 1.5) | ||
if (breakable0 && maxImpulse > fractureImpulse && threeObject0.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
const debris = this.convexBreaker.subdivideByImpact(threeObject0, this.impactPoint, this.impactNormal, 1, 2) //, 1.5) | ||
var numObjects = debris.length | ||
for (var j = 0; j < numObjects; j++) { | ||
var vel = body0.getLinearVelocity() | ||
var angVel = body0.getAngularVelocity() | ||
var fragment = debris[j] as ExtendedObject3D | ||
const numObjects = debris.length | ||
for (let j = 0; j < numObjects; j++) { | ||
const vel = body0.getLinearVelocity() | ||
const angVel = body0.getAngularVelocity() | ||
const fragment = debris[j] as ExtendedObject3D | ||
fragment.userData.velocity.set(vel.x(), vel.y(), vel.z()) | ||
@@ -428,14 +439,13 @@ fragment.userData.angularVelocity.set(angVel.x(), angVel.y(), angVel.z()) | ||
this.objectsToRemove[this.numObjectsToRemove++] = threeObject0 | ||
threeObject0.body.collided = true | ||
} | ||
// threeObject1 | ||
if (breakable1 && !collided1 && maxImpulse > fractureImpulse && threeObject1.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
var debris = this.convexBreaker.subdivideByImpact(threeObject1, this.impactPoint, this.impactNormal, 1, 2) //, 1.5) | ||
if (breakable1 && maxImpulse > fractureImpulse && threeObject1.fragmentDepth < MAX_FRAGMENT_DEPTH) { | ||
const debris = this.convexBreaker.subdivideByImpact(threeObject1, this.impactPoint, this.impactNormal, 1, 2) //, 1.5) | ||
var numObjects = debris.length | ||
for (var j = 0; j < numObjects; j++) { | ||
var vel = body1.getLinearVelocity() | ||
var angVel = body1.getAngularVelocity() | ||
var fragment = debris[j] as ExtendedObject3D | ||
const numObjects = debris.length | ||
for (let j = 0; j < numObjects; j++) { | ||
const vel = body1.getLinearVelocity() | ||
const angVel = body1.getAngularVelocity() | ||
const fragment = debris[j] as ExtendedObject3D | ||
fragment.userData.velocity.set(vel.x(), vel.y(), vel.z()) | ||
@@ -448,10 +458,7 @@ fragment.userData.angularVelocity.set(angVel.x(), angVel.y(), angVel.z()) | ||
this.objectsToRemove[this.numObjectsToRemove++] = threeObject1 | ||
threeObject1.body.collided = true | ||
} | ||
} | ||
/** | ||
* Remove objects | ||
*/ | ||
for (var i = 0; i < this.numObjectsToRemove; i++) { | ||
// remove objects | ||
for (let i = 0; i < this.numObjectsToRemove; i++) { | ||
this.removeDebris(this.objectsToRemove[i]) | ||
@@ -461,5 +468,3 @@ } | ||
/** | ||
* Handle collision end events | ||
*/ | ||
// handle collision end events | ||
this.earlierDetectedCollisions.forEach(el => { | ||
@@ -471,3 +476,4 @@ const { combinedName } = el | ||
const obj1 = this.rigidBodies.find(obj => obj.name === split[1]) | ||
if (obj0 && obj1) this.emit('collision', { bodies: [obj0, obj1], event: 'end' }) | ||
const event: Types.CollisionEvent = { name: 'end' } | ||
if (obj0 && obj1) this.emit('collision', { bodies: [obj0, obj1], event }) | ||
} | ||
@@ -517,3 +523,3 @@ }) | ||
object2: ExtendedObject3D, | ||
eventCallback: (event: 'start' | 'collision' | 'end') => void | ||
eventCallback: (event: Types.CollisionEvent) => void | ||
) => this.events.addCollider(object1, object2, eventCallback), | ||
@@ -520,0 +526,0 @@ constraints: this.constraints.addConstraints, |
@@ -11,3 +11,2 @@ /** | ||
export default class AllHitsRayResultCallback { | ||
protected _tmpBtVector3: Ammo.btVector3 | ||
protected _btRayCallback: Ammo.AllHitsRayResultCallback | ||
@@ -17,3 +16,3 @@ | ||
getHitPointWorld(): { x: number; y: number; z: number }[] { | ||
getHitPointsWorld() { | ||
const h = this._btRayCallback.get_m_hitPointWorld() as Ammo.btVector3Array | ||
@@ -30,3 +29,21 @@ | ||
getCollisionObjects(): ExtendedObject3D[] { | ||
// TODO: Remove this in future versions! | ||
getHitPointWorld() { | ||
console.warn('[enable3d] Use getHitPointsWorld() instead of getHitPointWorld() for the AllHitsRayCaster!') | ||
return this.getHitPointsWorld() | ||
} | ||
getHitNormalsWorld() { | ||
const h = this._btRayCallback.get_m_hitNormalWorld() | ||
const normals = [] | ||
for (let i = h.size() - 1; i >= 0; i--) { | ||
const hh = h.at(i) | ||
normals.push({ x: hh.x(), y: hh.y(), z: hh.z() }) | ||
} | ||
return normals | ||
} | ||
getCollisionObjects() { | ||
const getPtr = (obj: any) => { | ||
@@ -36,4 +53,3 @@ return Object.values(obj)[0] | ||
const obs = [] | ||
// @ts-ignore | ||
const obs: ExtendedObject3D[] = [] | ||
const o = this._btRayCallback.get_m_collisionObjects() | ||
@@ -40,0 +56,0 @@ for (let i = o.size() - 1; i >= 0; i--) { |
@@ -11,3 +11,2 @@ /** | ||
export default class ClosestRayResultCallback { | ||
protected _tmpBtVector3: Ammo.btVector3 | ||
protected _btRayCallback: Ammo.ClosestRayResultCallback | ||
@@ -25,2 +24,10 @@ | ||
getHitNormalWorld() { | ||
const h = this._btRayCallback.get_m_hitNormalWorld() | ||
const normal = { x: h.x(), y: h.y(), z: h.z() } | ||
return normal | ||
} | ||
getCollisionObject(): ExtendedObject3D { | ||
@@ -27,0 +34,0 @@ const getPtr = (obj: any) => { |
@@ -13,7 +13,6 @@ /** | ||
class Raycaster { | ||
protected _tmpBtVector3: Ammo.btVector3 | ||
public readonly type: string | ||
protected _btRayFrom: Ammo.btVector3 | ||
protected _btRayTo: Ammo.btVector3 | ||
protected _btRayCallback: any | ||
protected initCallback: any | ||
protected _btRayCallback: Ammo.RayResultCallback | ||
@@ -24,3 +23,2 @@ constructor(protected physics: AmmoPhysics) {} | ||
this._btRayFrom.setValue(x, y, z) | ||
this._btRayCallback.set_m_rayFromWorld(this._btRayFrom) | ||
} | ||
@@ -30,3 +28,2 @@ | ||
this._btRayTo.setValue(x, y, z) | ||
this._btRayCallback.set_m_rayToWorld(this._btRayTo) | ||
} | ||
@@ -39,2 +36,9 @@ | ||
rayTest() { | ||
if (typeof this._btRayCallback !== 'undefined') Ammo.destroy(this._btRayCallback) | ||
this._btRayCallback = | ||
this.type === 'closest' | ||
? new Ammo.ClosestRayResultCallback(this._btRayFrom, this._btRayTo) | ||
: new Ammo.AllHitsRayResultCallback(this._btRayFrom, this._btRayTo) | ||
this.physics.physicsWorld.rayTest(this._btRayFrom, this._btRayTo, this._btRayCallback) | ||
@@ -44,6 +48,5 @@ } | ||
destroy() { | ||
Ammo.destroy(this._tmpBtVector3) | ||
Ammo.destroy(this._btRayFrom) | ||
Ammo.destroy(this._btRayTo) | ||
Ammo.destroy(this._btRayCallback) | ||
if (typeof this._btRayFrom !== 'undefined') Ammo.destroy(this._btRayFrom) | ||
if (typeof this._btRayTo !== 'undefined') Ammo.destroy(this._btRayTo) | ||
if (typeof this._btRayCallback !== 'undefined') Ammo.destroy(this._btRayCallback) | ||
} | ||
@@ -55,25 +58,17 @@ } | ||
class ClosestRaycaster { | ||
protected _tmpBtVector3: Ammo.btVector3 = new Ammo.btVector3(0, 0, 0) | ||
class ClosestRaycaster implements Raycaster, ClosestRayResultCallback { | ||
public readonly type = 'closest' | ||
protected _btRayFrom = new Ammo.btVector3(0, 0, 0) | ||
protected _btRayTo = new Ammo.btVector3(0, 0, 0) | ||
protected _btRayCallback: Ammo.ClosestRayResultCallback | ||
protected _btRayCallback: Ammo.ClosestRayResultCallback = new Ammo.ClosestRayResultCallback( | ||
this._tmpBtVector3, | ||
this._tmpBtVector3 | ||
) | ||
constructor(protected physics: AmmoPhysics) {} | ||
} | ||
class AllHitsRaycaster { | ||
protected _tmpBtVector3: Ammo.btVector3 = new Ammo.btVector3(0, 0, 0) | ||
class AllHitsRaycaster implements Raycaster, AllHitsRayResultCallback { | ||
public readonly type = 'allHits' | ||
protected _btRayFrom = new Ammo.btVector3(0, 0, 0) | ||
protected _btRayTo = new Ammo.btVector3(0, 0, 0) | ||
protected _btRayCallback: Ammo.AllHitsRayResultCallback | ||
protected _btRayCallback: Ammo.AllHitsRayResultCallback = new Ammo.AllHitsRayResultCallback( | ||
this._tmpBtVector3, | ||
this._tmpBtVector3 | ||
) | ||
constructor(protected physics: AmmoPhysics) {} | ||
@@ -80,0 +75,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3524162
16078
+ Added@enable3d/common@0.19.1(transitive)
+ Added@enable3d/three-wrapper@0.19.1(transitive)
- Removed@enable3d/common@0.18.0(transitive)
- Removed@enable3d/three-wrapper@0.18.0(transitive)
Updated@enable3d/common@^0.19.0