DEMO
Oculus Quest用 DEMO 👉 https://kimizuka.org/mock/r127/vr-collision
Oculus Rift用 DEMO 👉 https://kimizuka.org/mock/r111/vr-collision
※ r111はコントローラーの位置にCubeが表示されます
解説
こちらの記事で作ったコードを改造して、VRコントローラーの当たり判定を取りました。
r111にはXRControllerModelFactory.jsが無いのでコントローラーの姿を再現することは諦め、コントローラーの位置にCubeを置いています。
ソースコード抜粋
const controllerModelFactory = new XRControllerModelFactory(); const controller = renderer.vr.getController(0); const controllerModel = controllerModelFactory.createControllerModel(controller); const mesh = new THREE.Mesh( new THREE.SphereGeometry(.06, 8, 8), // ❶ BoxGeometryからSphereGeometryに変更 new THREE.MeshNormalMaterial() ); const cube = new THREE.Mesh( new THREE.BoxGeometry(.1, .1, .1), new THREE.MeshNormalMaterial() ); mesh.material.transparent = true; mesh.material.alphaToCoverage = true; mesh.material.opacity = 0; // ❷ メッシュを透明にする controller.add(controllerModel); controller.add(mesh); if (!mesh.geometry.boundingSphere) { mesh.geometry.computeBoundingSphere(); controller.hit = new THREE.Sphere( controller.position, mesh.geometry.boundingSphere.radius ); } if (!cube.geometry.boundingSphere) { cube.geometry.computeBoundingSphere(); cube.hit = new THREE.Sphere( cube.position, cube.geometry.boundingSphere.radius ); } renderer.setAnimationLoop(() => { orbitControls && orbitControls.update(); controller.hit.center.set(controller.position.x, controller.position.y, controller.position.z); cube.hit.center.set(cube.position.x, cube.position.y, cube.position.z); if (controller.hit.intersectsSphere(cube.hit)) { debug.log('HIT!'); } else { debug.log(''); } renderer.render(scene, camera); });
前回との変更点で言うと、
❶ BoxGeometryからSphereGeometryに変更 → 当たり判定用にコントローラぐらいのサイズの球を作りました
❷ 当たり判定用の球を透明にする → 当たり判定は肉眼で確認出来なくて良いので透明にしました
の2点で、boundingSphereを使わずに当たり判定用のメッシュを作る方針にしました。
これは、controllerModelからboundingSphereを作る方法がわからないがための苦肉の策だったのですが、よく考えると、透明化を解除すれば当たり判定が目視確認できるのはデバッグ時に役に立ちそうだと思い、今後はこちらの方法を採用しようと思いました。