diff --git a/character-controller.js b/character-controller.js index 2f1b7b0048..4c4a70465c 100644 --- a/character-controller.js +++ b/character-controller.js @@ -1136,10 +1136,16 @@ class LocalPlayer extends UninterpolatedPlayer { }); } grab(app, hand = 'left') { - const {position, quaternion} = _getSession() ? - localPlayer[hand === 'left' ? 'leftHand' : 'rightHand'] - : - camera; + let position = null, quaternion = null; + + if(_getSession()) { + const h = this[hand === 'left' ? 'leftHand' : 'rightHand']; + position = h.position; + quaternion = h.quaternion; + } else { + position = this.position; + quaternion = camera.quaternion; + } app.updateMatrixWorld(); app.savedRotation = app.rotation.clone(); diff --git a/game.js b/game.js index aead8b33ac..d3af25eaa8 100644 --- a/game.js +++ b/game.js @@ -80,29 +80,53 @@ const _unwearAppIfHasSitComponent = (player) => { } // returns whether we actually snapped -function updateGrabbedObject(o, grabMatrix, offsetMatrix, {collisionEnabled, handSnapEnabled, physx, gridSnap}) { +function updateGrabbedObject( + o, + grabMatrix, + offsetMatrix, + { collisionEnabled, handSnapEnabled, physx, gridSnap } +) { grabMatrix.decompose(localVector, localQuaternion, localVector2); offsetMatrix.decompose(localVector3, localQuaternion2, localVector4); const offset = localVector3.length(); - localMatrix.multiplyMatrices(grabMatrix, offsetMatrix) + localMatrix + .multiplyMatrices(grabMatrix, offsetMatrix) .decompose(localVector5, localQuaternion3, localVector6); - let collision = collisionEnabled && physicsScene.raycast(localVector, localQuaternion); - if (collision) { - // console.log('got collision', collision); - const {point} = collision; - o.position.fromArray(point) - // .add(localVector2.set(0, 0.01, 0)); + const collision = collisionEnabled && physicsScene.raycast(localVector, localQuaternion); + localQuaternion2.setFromAxisAngle(localVector2.set(1, 0, 0), -Math.PI * 0.5); + const downCollision = collisionEnabled && physicsScene.raycast(localVector5, localQuaternion2); - if (o.position.distanceTo(localVector) > offset) { - collision = null; - } + if (!!collision) { + const { point } = collision; + localVector6.fromArray(point); } - if (!collision) { - o.position.copy(localVector5); + + if (!!downCollision) { + const { point } = downCollision; + localVector4.fromArray(point); + if (ioManager.keys.shift) { + o.position.copy(localVector5.setY(localVector4.y)); + } else { + // if collision point is closer to the player than the grab offset and collisionDown point + // is below collision point then place the object at collision point + if ( + localVector.distanceTo(localVector6) < offset && + localVector4.y < localVector6.y + ) + localVector5.copy(localVector6); + + // if grabbed object would go below another object then place object at downCollision point + if (localVector5.y < localVector4.y) localVector5.setY(localVector4.y); + o.position.copy(localVector5); + } } - const handSnap = !handSnapEnabled || offset >= maxGrabDistance || !!collision; + const handSnap = + !handSnapEnabled || + offset >= maxGrabDistance || + !!collision || + !!downCollision; if (handSnap) { snapPosition(o, gridSnap); o.quaternion.setFromEuler(o.savedRotation); @@ -110,6 +134,8 @@ function updateGrabbedObject(o, grabMatrix, offsetMatrix, {collisionEnabled, han o.quaternion.copy(localQuaternion3); } + o.updateMatrixWorld(); + return { handSnap, }; @@ -541,9 +567,18 @@ const _gameUpdate = (timestamp, timeDiff) => { const grabAction = _getGrabAction(i); const grabbedObject = _getGrabbedObject(i); if (grabbedObject && !_isWear(grabbedObject)) { - const {position, quaternion} = renderer.xr.getSession() ? localPlayer[hand === 'left' ? 'leftHand' : 'rightHand'] : camera; + let position = null, + quaternion = null; + if (renderer.xr.getSession()) { + const h = localPlayer[hand === "left" ? "leftHand" : "rightHand"]; + position = h.position; + quaternion = h.quaternion; + } else { + position = localVector2.copy(localPlayer.position); + quaternion = camera.quaternion; + } + localMatrix.compose(position, quaternion, localVector.set(1, 1, 1)); - grabbedObject.updateMatrixWorld(); updateGrabbedObject(grabbedObject, localMatrix, localMatrix3.fromArray(grabAction.matrix), { collisionEnabled: true,