Skip to content

Commit

Permalink
Consider scale changes on parents to recalculate collider box. Also i…
Browse files Browse the repository at this point in the history
…gnore parent entities rotations before calculating so bounding box has the right size when calculated
  • Loading branch information
dmarcos committed Nov 26, 2023
1 parent 56a86a9 commit 5da7166
Showing 1 changed file with 57 additions and 40 deletions.
97 changes: 57 additions & 40 deletions src/components/obb-collider.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ registerComponent('obb-collider', {
},

init: function () {
this.previousScale = new THREE.Vector3();
this.previousScale = new THREE.Vector3().copy(this.el.object3D.scale);
this.auxEuler = new THREE.Euler();

this.boundingBox = new THREE.Box3();
Expand All @@ -22,6 +22,7 @@ registerComponent('obb-collider', {

this.el.addEventListener('model-loaded', this.onModelLoaded);
this.updateCollider();

this.system.addCollider(this.el);
},

Expand Down Expand Up @@ -114,41 +115,54 @@ registerComponent('obb-collider', {
this.el.sceneEl.object3D.add(renderColliderMesh);
},

updateBoundingBox: function () {
var auxEuler = this.auxEuler;
var boundingBox = this.boundingBox;
var size = this.data.size;
var trackedObject3D = this.trackedObject3D || this.el.object3D;
var boundingBoxSize = this.boundingBoxSize;
var minimumColliderDimension = this.data.minimumColliderDimension;

// user defined size takes precedence.
if (size) {
this.boundingBoxSize.x = size;
this.boundingBoxSize.y = size;
this.boundingBoxSize.z = size;
return;
}

this.previousScale.copy(trackedObject3D.scale);

// Bounding box is created axis-aligned AABB.
// If there's any local rotation the box will be bigger than expected.
// It undoes the local entity rotation and then restores so box has the expected size.
auxEuler.copy(trackedObject3D.rotation);
trackedObject3D.rotation.set(0, 0, 0);

trackedObject3D.updateMatrixWorld(true);
boundingBox.setFromObject(trackedObject3D, true);
boundingBox.getSize(boundingBoxSize);
updateBoundingBox: (function () {
var auxPosition = new THREE.Vector3();
var auxScale = new THREE.Vector3();
var auxQuaternion = new THREE.Quaternion();
var identityQuaternion = new THREE.Quaternion();
var auxMatrix = new THREE.Matrix4();

boundingBoxSize.x = boundingBoxSize.x < minimumColliderDimension ? minimumColliderDimension : boundingBoxSize.x;
boundingBoxSize.y = boundingBoxSize.y < minimumColliderDimension ? minimumColliderDimension : boundingBoxSize.y;
boundingBoxSize.z = boundingBoxSize.z < minimumColliderDimension ? minimumColliderDimension : boundingBoxSize.z;
return function () {
var auxEuler = this.auxEuler;
var boundingBox = this.boundingBox;
var size = this.data.size;
var trackedObject3D = this.trackedObject3D || this.el.object3D;
var boundingBoxSize = this.boundingBoxSize;
var minimumColliderDimension = this.data.minimumColliderDimension;

// user defined size takes precedence.
if (size) {
this.boundingBoxSize.x = size;
this.boundingBoxSize.y = size;
this.boundingBoxSize.z = size;
return;
}

// Restore rotation.
this.el.object3D.rotation.copy(auxEuler);
},
// Bounding box is created axis-aligned AABB.
// If there's any rotation the box will have the wrong size.
// It undoes the local entity rotation and then restores so box has the expected size.
// We also undo the parent world rotation.
auxEuler.copy(trackedObject3D.rotation);
trackedObject3D.rotation.set(0, 0, 0);

trackedObject3D.parent.matrixWorld.decompose(auxPosition, auxQuaternion, auxScale);
auxMatrix.compose(auxPosition, identityQuaternion, auxScale);
trackedObject3D.parent.matrixWorld.copy(auxMatrix);

// Calculate bounding box size.
boundingBox.setFromObject(trackedObject3D, true);
boundingBox.getSize(boundingBoxSize);

// Enforce minimum dimensions.
boundingBoxSize.x = boundingBoxSize.x < minimumColliderDimension ? minimumColliderDimension : boundingBoxSize.x;
boundingBoxSize.y = boundingBoxSize.y < minimumColliderDimension ? minimumColliderDimension : boundingBoxSize.y;
boundingBoxSize.z = boundingBoxSize.z < minimumColliderDimension ? minimumColliderDimension : boundingBoxSize.z;

// Restore rotations.
trackedObject3D.parent.matrixWorld.compose(auxPosition, auxQuaternion, auxScale);
this.el.object3D.rotation.copy(auxEuler);
};
})(),

checkTrackedObject: function () {
var trackedObject3DPath = this.trackedObject3DPath;
Expand Down Expand Up @@ -183,16 +197,19 @@ registerComponent('obb-collider', {

if (!trackedObject3D) { return; }

trackedObject3D.updateMatrix();
trackedObject3D.updateMatrixWorld(true);
trackedObject3D.matrixWorld.decompose(auxPosition, auxQuaternion, auxScale);

// Recalculate collider if scale has changed.
if (trackedObject3D.scale.x !== this.previousScale.x ||
trackedObject3D.scale.y !== this.previousScale.y ||
trackedObject3D.scale.z !== this.previousScale.z) {
if ((Math.abs(auxScale.x - this.previousScale.x) > 0.0001) ||
(Math.abs(auxScale.y - this.previousScale.y) > 0.0001) ||
(Math.abs(auxScale.z - this.previousScale.z) > 0.0001)) {
this.updateCollider();
}

trackedObject3D.updateMatrix();
trackedObject3D.updateMatrixWorld();
trackedObject3D.matrixWorld.decompose(auxPosition, auxQuaternion, auxScale);
this.previousScale.copy(auxScale);

// reset scale, keep position and rotation
auxScale.set(1, 1, 1);
auxMatrix.compose(auxPosition, auxQuaternion, auxScale);
Expand Down

0 comments on commit 5da7166

Please sign in to comment.