diff --git a/src/components/obb-collider.js b/src/components/obb-collider.js index 7cddffdee71..329964819ee 100644 --- a/src/components/obb-collider.js +++ b/src/components/obb-collider.js @@ -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(); @@ -22,6 +22,7 @@ registerComponent('obb-collider', { this.el.addEventListener('model-loaded', this.onModelLoaded); this.updateCollider(); + this.system.addCollider(this.el); }, @@ -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; @@ -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);