Skip to content

Commit bd95a77

Browse files
committed
Add body tracking sample
1 parent 9c7e303 commit bd95a77

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

proposals/body-tracking.html

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset='utf-8'>
5+
<meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no'>
6+
<meta name='mobile-web-app-capable' content='yes'>
7+
<meta name='apple-mobile-web-app-capable' content='yes'>
8+
9+
<meta http-equiv="origin-trial" content="Ahfj+MLeL6bh+LNmpnSdepftxoDHHwjUG2KWZ4jjCb1WoZxtBlzF3cDHuJNVqnhr3HXJwQ+kLaw57NO15S0mRwwAAABkeyJvcmlnaW4iOiJodHRwczovL2ltbWVyc2l2ZS13ZWIuZ2l0aHViLmlvOjQ0MyIsImZlYXR1cmUiOiJXZWJYUlBsYW5lRGV0ZWN0aW9uIiwiZXhwaXJ5IjoxNjI5ODQ5NTk5fQ==">
10+
11+
<title>AR Plane Detection</title>
12+
13+
<link href='../css/common.css' rel='stylesheet'></link>
14+
15+
</head>
16+
<body>
17+
<header>
18+
<details open>
19+
<summary>Simple body tracking</summary>
20+
This sample demonstrates using the WebXR body tracking API
21+
to show your body's joints.
22+
<p>
23+
24+
<a class="back" href="./index.html">Back</a>
25+
</p>
26+
</details>
27+
</header>
28+
29+
<script type="module">
30+
// Code adapted from three.js' WebXR hit test sample.
31+
// three.js is covered by MIT license which can be found at:
32+
// https://github.com/mrdoob/three.js/blob/master/LICENSE
33+
34+
35+
import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';
36+
import {WebXRButton} from '../js/util/webxr-button.js';
37+
import {hitTest, filterHitTestResults} from '../js/hit-test.js';
38+
39+
let xrButton = null;
40+
let camera, scene, renderer;
41+
let room, spheres;
42+
const scalehand = new THREE.Matrix4().makeScale(3, 3, 3);
43+
44+
init();
45+
46+
function init() {
47+
scene = new THREE.Scene();
48+
scene.background = new THREE.Color( 0x505050 );
49+
50+
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 50 );
51+
52+
const light = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 1);
53+
light.position.set(0.5, 1, 0.25);
54+
scene.add(light);
55+
56+
renderer = new THREE.WebGLRenderer( { antialias: true } );
57+
renderer.setPixelRatio( window.devicePixelRatio );
58+
renderer.setSize( window.innerWidth, window.innerHeight );
59+
renderer.setAnimationLoop( render );
60+
renderer.xr.enabled = true;
61+
renderer.autoClear = false;
62+
document.body.appendChild( renderer.domElement );
63+
64+
xrButton = new WebXRButton({
65+
onRequestSession: onRequestSession,
66+
onEndSession: onEndSession,
67+
textEnterXRTitle: "START AR",
68+
textXRNotFoundTitle: "AR NOT FOUND",
69+
textExitXRTitle: "EXIT AR",
70+
});
71+
72+
document.querySelector('header').appendChild(xrButton.domElement);
73+
74+
if (navigator.xr) {
75+
navigator.xr.isSessionSupported('immersive-ar')
76+
.then((supported) => {
77+
xrButton.enabled = supported;
78+
});
79+
}
80+
81+
window.addEventListener( 'resize', onWindowResize );
82+
83+
}
84+
85+
function onRequestSession() {
86+
let sessionInit = {
87+
requiredFeatures: ['body-tracking'],
88+
optionalFeatures: ['local-floor', 'bounded-floor'],
89+
};
90+
navigator.xr.requestSession('immersive-ar', sessionInit).then((session) => {
91+
session.mode = 'immersive-ar';
92+
xrButton.setSession(session);
93+
onSessionStarted(session);
94+
});
95+
}
96+
97+
function onSessionStarted(session) {
98+
session.addEventListener('end', onSessionEnded);
99+
100+
renderer.xr.setSession(session);
101+
102+
renderer.setAnimationLoop(render);
103+
}
104+
105+
function onEndSession(session) {
106+
session.end();
107+
}
108+
109+
function onSessionEnded(event) {
110+
xrButton.setSession(null);
111+
112+
renderer.setAnimationLoop(null);
113+
renderer.xr.setSession(null)
114+
}
115+
116+
function onWindowResize() {
117+
camera.aspect = window.innerWidth / window.innerHeight;
118+
camera.updateProjectionMatrix();
119+
120+
renderer.setSize(window.innerWidth, window.innerHeight);
121+
}
122+
123+
124+
function render(timestamp, frame) {
125+
if (frame) {
126+
127+
if ( frame.body ) {
128+
129+
let body = frame.body;
130+
131+
if (spheres == undefined) {
132+
133+
const geometry = new THREE.IcosahedronGeometry( 0.01, 3 );
134+
const material = new THREE.MeshLambertMaterial();
135+
136+
spheres = new THREE.InstancedMesh( geometry, material, body.size );
137+
spheres.translateZ( -1 ).setRotationFromMatrix (new THREE.Matrix4().makeRotationY(Math.PI));
138+
spheres.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame
139+
scene.add( spheres );
140+
141+
const color = new THREE.Color();
142+
143+
for ( let i = 0; i < spheres.count; i ++ ) {
144+
145+
spheres.setColorAt( i, color.setHex( 0xffffff * Math.random() ) );
146+
147+
}
148+
149+
spheres.instanceMatrix.needsUpdate = true;
150+
151+
}
152+
153+
let i = 0;
154+
const matrix = new THREE.Matrix4();
155+
let space = renderer.xr.getReferenceSpace();
156+
body.forEach(part => {
157+
158+
const pose = frame.getPose(part, space);
159+
const position = pose.transform.position;
160+
161+
if (!part.jointName.includes("hand")) {
162+
matrix.copy(scalehand);
163+
} else {
164+
matrix.identity();
165+
}
166+
167+
matrix.setPosition( -position.x, position.y, position.z );
168+
spheres.setMatrixAt( i++, matrix );
169+
170+
});
171+
172+
spheres.instanceMatrix.needsUpdate = true;
173+
174+
}
175+
176+
renderer.render(scene, camera);
177+
}
178+
}
179+
180+
</script>
181+
</body>
182+
</html>

proposals/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ <h2 class='tagline'>Proposals</h2>
132132
description: 'Demonstrates use of the mesh detection API in an immersive-ar session. ' +
133133
'Implements JavaScript-level hit-test on the meshes and leverages the Anchors API.' },
134134

135+
{ title: 'Body tracking', category: 'AR',
136+
path: 'body-tracking.html',
137+
description: 'Demonstrates use of the body tracking in an immersive-ar session. ' },
135138
];
136139

137140
let mainElement = document.getElementById("main");

0 commit comments

Comments
 (0)