さっそくコード
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>posDetect</title>
</head>
<body>
<canvas class="output-canvas"></canvas>
<!-- <button class="green button" type="button">Start Game</button> -->
<button id="xrStartButton" class="blue button use-webxr" type="button">
Start(VR mode)
</button>
<script src="/libs/gl-matrix.js"></script>
<script>
const outputCanvas = document.querySelector('.output-canvas');
const gl = outputCanvas.getContext('webgl');
const viewerStartPosition = glMatrix.vec3.fromValues(0, 0, -10);
const viewerStartOrientation = glMatrix.vec3.fromValues(0, 0, 1.0);
let xrSession = null;
let usingXR = false;
let xrStartButton = document.getElementById('xrStartButton');
let worldRefSpace;
let viewerRefSpace;
let animationFrameRequestID;
window.addEventListener('load', (event) => {
console.log('window loaded');
xrStartButton.addEventListener('click', handleStartButtonClick);
});
outputCanvas.addEventListener('webglcontextlost', (event) => {
/* The context has been lost but can be restored */
event.canceled = true;
});
/* When the GL context is reconnected, reload the resources for the
current scene. */
outputCanvas.addEventListener('webglcontextrestored', (event) => {
// loadSceneResources(currentScene);
});
function XRRenderingLoop(currentFrameTime, frame) {
// ループ
animationFrameRequestID =
xrSession.requestAnimationFrame(XRRenderingLoop);
// デバイスの位置取得
const pose = frame.getViewerPose(viewerRefSpace);
if (!pose) return;
console.log(pose.transform.position);
}
async function onStartedXRSession(xrSession) {
xrStartButton.style.visibility = 'hidden';
try {
await gl.makeXRCompatible();
const xrWebGLLayer = new XRWebGLLayer(xrSession, gl);
xrSession.updateRenderState({ baseLayer: xrWebGLLayer });
worldRefSpace = await xrSession.requestReferenceSpace('local');
if (worldRefSpace) {
viewerRefSpace = worldRefSpace.getOffsetReferenceSpace(
new XRRigidTransform(viewerStartPosition, viewerStartOrientation)
);
// loopスタート
animationFrameRequestID =
xrSession.requestAnimationFrame(XRRenderingLoop);
}
} catch (err) {
console.error(err);
xrSession.end();
}
}
async function handleStartButtonClick(event) {
if (event.target.classList.contains('use-webxr') && navigator.xr) {
try {
xrSession = await navigator.xr.requestSession('immersive-vr'); //immersive-ar
await onStartedXRSession(xrSession);
usingXR = true;
} catch (err) {
xrSession = null;
usingXR = false;
}
}
}
</script>
</body>
</html>
p5xr使うとすっごい短縮できる
p5xr.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>p5</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.10.0/p5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5.xr/dist/p5xr.js"></script>
<style>
html,
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script>
async function preload() {
createARCanvas();
// createVRCanvas();
}
function setup() {}
function draw() {
const viewer = getViewer();
console.log(viewer.pose.transform.position);
}
</script>
</body>
</html>
開発方法Tips
Chromeの拡張機能でエミュレーターがあった
https://chromewebstore.google.com/detail/immersive-web-emulator/cgffilbpcibhmcfbgggfhfolhkfbhmik
いくつかあるけど上記のものは対応機能が多かったのでこれを使ってます
実行方法
localhostでデバッグをやるならいいのですが、同じLAN内のスマートフォンだとhttpsじゃないとだ
以前の記事から
https://qiita.com/ono-honeycomb/items/359a254fd4c859692472
$ openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
$ http-server -S -C cert.pem
いろいろ試してみたい!
部屋内でスマートフォンがどこにいて、どこに向けているかってのが検出できそうなので、
部屋のどこの壁の位置にかざしているかだったり、部屋に設置されているどの物を見ているかだったり、ユーザーの首からぶら下げてもらって、ユーザーがどの位置にいるかっていうのを検出したりいろいろできそうです
他の検出方法
- ネイティブアプリでもよさそう
- UWBとかの別機器
- RTKとか
- 壁に測域センサ
- かざすならNFCでも?
- Kinect的なのでも
- Femtoとか
- 今単眼のカメラでも人検出できちゃうのでそれでも
- スマートフォンにQRコード貼っちゃってもいいのか