window.addEventListener("イベント名", 関数);
とすることで,イベントに対して処理(関数)を割り当てられます.const cameraContainer = new THREE.Object3D(); // コンテナを生み出す
cameraContainer.add(camera);// カメラをコンテナに入れる
cameraContainer.position.set(0, 0, 10);// コンテナの場所を移動する
scene.add(cameraContainer);// シーンにコンテナを追加
高さ(Y方向)以外の情報はコンテナに持たせるので,上の方にあるカメラの位置と見る場所を,以下のように変更します.
camera.position.set(0, 1.7, 0);// カメラの場所
camera.lookAt(0, 1.7, -1);// カメラの見る場所
次に,マウスボタン押下,マウスドラッグ,マウスボタンを離したときの3つの関数を作ります.// 前回のマウスの横の位置と,マウスを押しているかどうかのフラグを入れる変数
var pmouseX, mouseFlag;
// マウスボタンを押したときの処理
function moveStartFunc(e) {
pmouseX = e.offsetX;// 前回のマウスの横の位置を入れておく
mouseFlag = true;// マウスを押したフラグをたてる
}
// マウスボタンを離したときの処理
function moveEndFunc() {
mouseFlag = false;// マウスを押したフラグを消す
}
// マウスドラッグ中の処理
function moveFunc(e) {
if (mouseFlag) {// マウスが押されているなら
var mouseX = e.offsetX;// 今のマウスの横方向の位置
cameraContainer.rotation.y -= 0.001*(mouseX - pmouseX);// 前回との差をもとにY軸回りに回転
pmouseX = mouseX;// 今の横の位置を,前回の横の位置にする (次回使うため).
}
}
ここでは視点の回転だけを定義していて,移動そのものは記述していません.window.addEventListener("mousedown", moveStartFunc);
window.addEventListener("mouseup", moveEndFunc);
window.addEventListener("mousemove", moveFunc);
では,進むための処理を書きましょう.function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
if (mouseFlag) {
var r = cameraContainer.rotation.y;
cameraContainer.position.x -= 0.02*Math.sin(r);
cameraContainer.position.z -= 0.02*Math.cos(r);
}
}
編集できたら上書き保存して,ブラウザでページを再読み込みしましょう.const room = new THREE.Mesh(
new THREE.BoxGeometry(26,5,26),
new THREE.MeshStandardMaterial({
color: 0xdddddd,
roughness: 0.1,
side: THREE.DoubleSide,
})
);
room.position.set(0, 3, 0);
scene.add(room);
const alight = new THREE.AmbientLight(0xffffff, 0.2);
また,点光源の強さも大幅に減らします.const plight = new THREE.PointLight(0xffffff, 1.0);
また,カメラコンテナの移動が遅いので,少し早くしておきます.cameraContainer.position.x -= 0.05*Math.sin(r);
cameraContainer.position.z -= 0.05*Math.cos(r);
編集できたら上書き保存して,ブラウザでページを再読み込みしましょう.<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.146.0/build/three.module.js",
"vrbutton": "https://unpkg.com/three@0.146.0/examples/jsm/webxr/VRButton.js"
}
}
</script>
また,program.js の上部を以下のようにして,VRButtonを読み込みます.
import * as THREE from 'three';
import { VRButton } from 'vrbutton';
そして,program.js の下のほうで
var vrbutton = VRButton.createButton(renderer);
document.body.appendChild(vrbutton);
として,VRボタンを作って配置します.
また,レンダラの設定でXRモードを有効にします.
// レンダラの作成とサイズ調整
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#myCanvas")
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.xr.enabled = true;// 追加
最後に,レンダリングの方法を少し変更します. これまでは requestAnimationFrame を使っていましたが,WebXRではsetAnimationLoopを使います.
// お絵かきするループ(processingでいうところのdraw)
function animate() {
//requestAnimationFrame(animate); // ここをコメントアウト
renderer.render(scene, camera);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
if (mouseFlag) {
var r = cameraContainer.rotation.y;
cameraContainer.position.x -= 0.05*Math.sin(r);
cameraContainer.position.z -= 0.05*Math.cos(r);
}
}
//animate(); // ここをコメントアウト
renderer.setAnimationLoop(animate);// ここを追加
これでWebXR対応ができました.
Meta Quest2などのVRゴーグルをかぶり,ゴーグルのブラウザを起動して,
PCのIPアドレス:8000
にアクセスすると,手元のPCで見ているのと同じような画面が見えるはずです.
下部にあるWebXRのボタンが押せるので,押して見ると没入感のある感じで楽しめます.
ただし,WebXRのモードの際にはマウスイベントがありません.
かわりにコントローラのイベントを取得する必要がありますが,今はそれを書いていないので,
頭を動かした分しか動けないようになっています.