Skip to content

Commit 7d42832

Browse files
committed
add basic skeleton
1 parent edca99c commit 7d42832

File tree

1 file changed

+105
-41
lines changed

1 file changed

+105
-41
lines changed

proposals/body-tracking.html

Lines changed: 105 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,81 @@
2626
</details>
2727
</header>
2828

29+
<script type="importmap">
30+
{
31+
"imports": {
32+
"three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
33+
"three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
34+
}
35+
}
36+
</script>
37+
2938
<script type="module">
3039
// Code adapted from three.js' WebXR hit test sample.
3140
// three.js is covered by MIT license which can be found at:
3241
// https://github.com/mrdoob/three.js/blob/master/LICENSE
3342

3443

35-
import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js';
44+
import * as THREE from 'three';
45+
import {BoxLineGeometry} from 'three/addons/geometries/BoxLineGeometry.js';
3646
import {WebXRButton} from '../js/util/webxr-button.js';
3747
import {hitTest, filterHitTestResults} from '../js/hit-test.js';
3848

3949
let xrButton = null;
4050
let camera, scene, renderer;
41-
let room, spheres;
51+
let room, spheres, skeleton;
4252
const scalehand = new THREE.Matrix4().makeScale(3, 3, 3);
4353

54+
const jointHierarchy = {
55+
'spine-lower': 'spine-middle',
56+
'spine-middle': 'spine-upper',
57+
'spine-upper' : 'chest',
58+
59+
'left-upper-leg': 'hips',
60+
'left-lower-leg': 'left-upper-leg',
61+
62+
'right-upper-leg': 'hips',
63+
'right-lower-leg': 'left-upper-leg',
64+
65+
'left-arm-lower': 'left-arm-upper',
66+
'left-arm-upper': 'left-shoulder',
67+
'left-scapula': 'chest',
68+
69+
'right-arm-lower': 'right-arm-upper',
70+
'right-arm-upper': 'right-shoulder',
71+
'right-scapula': 'chest'
72+
};
73+
4474
init();
4575

46-
function init() {
76+
function dist(p) {
77+
return Math.sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
78+
}
79+
80+
function init(){
4781
scene = new THREE.Scene();
48-
scene.background = new THREE.Color( 0x505050 );
82+
scene.background = new THREE.Color(0x505050);
4983

50-
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 50 );
84+
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 50);
5185

5286
const light = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 1);
5387
light.position.set(0.5, 1, 0.25);
5488
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 );
89+
/*
90+
room = new THREE.LineSegments(
91+
new BoxLineGeometry( 6, 6, 6, 10, 10, 10 ),
92+
new THREE.LineBasicMaterial( { color: 0x808080 } )
93+
);
94+
room.geometry.translate( 0, 3, 0 );
95+
scene.add( room );
96+
*/
97+
renderer = new THREE.WebGLRenderer({ antialias: true });
98+
renderer.setPixelRatio(window.devicePixelRatio);
99+
renderer.setSize(window.innerWidth, window.innerHeight);
100+
renderer.setAnimationLoop(render);
60101
renderer.xr.enabled = true;
61102
renderer.autoClear = false;
62-
document.body.appendChild( renderer.domElement );
103+
document.body.appendChild(renderer.domElement);
63104

64105
xrButton = new WebXRButton({
65106
onRequestSession: onRequestSession,
@@ -71,21 +112,21 @@
71112

72113
document.querySelector('header').appendChild(xrButton.domElement);
73114

74-
if (navigator.xr) {
115+
if (navigator.xr){
75116
navigator.xr.isSessionSupported('immersive-ar')
76117
.then((supported) => {
77118
xrButton.enabled = supported;
78119
});
79120
}
80121

81-
window.addEventListener( 'resize', onWindowResize );
122+
window.addEventListener('resize', onWindowResize);
82123

83124
}
84125

85-
function onRequestSession() {
126+
function onRequestSession(){
86127
let sessionInit = {
87128
requiredFeatures: ['body-tracking'],
88-
optionalFeatures: ['local-floor', 'bounded-floor', 'unbounded'],
129+
optionalFeatures: ['local-floor', 'bounded-floor'],
89130
};
90131
navigator.xr.requestSession('immersive-ar', sessionInit).then((session) => {
91132
session.mode = 'immersive-ar';
@@ -94,84 +135,107 @@
94135
});
95136
}
96137

97-
function onSessionStarted(session) {
138+
function onSessionStarted(session){
98139
session.addEventListener('end', onSessionEnded);
99140

100141
renderer.xr.setSession(session);
101142

102143
renderer.setAnimationLoop(render);
103144
}
104145

105-
function onEndSession(session) {
146+
function onEndSession(session){
106147
session.end();
107148
}
108149

109-
function onSessionEnded(event) {
150+
function onSessionEnded(event){
110151
xrButton.setSession(null);
111152

112153
renderer.setAnimationLoop(null);
113154
}
114155

115-
function onWindowResize() {
156+
function onWindowResize(){
116157
camera.aspect = window.innerWidth / window.innerHeight;
117158
camera.updateProjectionMatrix();
118159

119160
renderer.setSize(window.innerWidth, window.innerHeight);
120161
}
121162

163+
function render(timestamp, frame){
164+
if (frame){
122165

123-
function render(timestamp, frame) {
124-
if (frame) {
125-
126-
if ( frame.body ) {
166+
if (frame.body){
127167

128168
let body = frame.body;
129169

130-
if (spheres == undefined) {
131-
132-
const geometry = new THREE.IcosahedronGeometry( 0.01, 3 );
170+
if (spheres == undefined){
171+
const geometry = new THREE.IcosahedronGeometry(0.01, 3);
133172
const material = new THREE.MeshLambertMaterial();
134173

135-
spheres = new THREE.InstancedMesh( geometry, material, body.size );
136-
spheres.translateZ( -1 ).setRotationFromMatrix (new THREE.Matrix4().makeRotationY(Math.PI));
137-
spheres.instanceMatrix.setUsage( THREE.DynamicDrawUsage ); // will be updated every frame
138-
scene.add( spheres );
174+
spheres = new THREE.InstancedMesh(geometry, material, body.size);
175+
spheres.translateZ(-1).setRotationFromMatrix (new THREE.Matrix4().makeRotationY(Math.PI));
176+
spheres.instanceMatrix.setUsage(THREE.DynamicDrawUsage); // will be updated every frame
177+
scene.add(spheres);
139178

140179
const color = new THREE.Color();
141180

142-
for ( let i = 0; i < spheres.count; i ++ ) {
143-
144-
spheres.setColorAt( i, color.setHex( 0xffffff * Math.random() ) );
145-
181+
for (let i = 0; i < spheres.count; i ++){
182+
spheres.setColorAt(i, color.setHex(0xffffff * Math.random()));
146183
}
147184

148-
spheres.instanceMatrix.needsUpdate = true;
185+
const boxgeometry = new THREE.BoxGeometry(1, 1, 1);
186+
boxgeometry.translate( -.5, 0, 0);
187+
const boxmaterial = new THREE.MeshBasicMaterial({color: 0xffffff});
188+
skeleton = new THREE.InstancedMesh(boxgeometry, boxmaterial, Object.keys(jointHierarchy).length);
189+
skeleton.translateZ(-1).setRotationFromMatrix (new THREE.Matrix4().makeRotationY(Math.PI));
190+
skeleton.instanceMatrix.setUsage(THREE.DynamicDrawUsage); // will be updated every frame
191+
scene.add(skeleton);
149192

193+
spheres.instanceMatrix.needsUpdate = true;
194+
skeleton.instanceMatrix.needsUpdate = true;
150195
}
151196

152197
let i = 0;
153198
const matrix = new THREE.Matrix4();
154199
let space = renderer.xr.getReferenceSpace();
155200
body.forEach(part => {
156-
157201
const pose = frame.getPose(part, space);
158202
const position = pose.transform.position;
159203

160-
if (!part.jointName.includes("hand")) {
204+
if (!part.jointName.includes("hand")){
161205
matrix.copy(scalehand);
162206
} else {
163207
matrix.identity();
164208
}
165209

166-
matrix.setPosition( -position.x, position.y, position.z );
167-
spheres.setMatrixAt( i++, matrix );
168-
210+
matrix.setPosition(position.x, position.y, position.z);
211+
spheres.setMatrixAt(i++, matrix);
169212
});
170213

171-
spheres.instanceMatrix.needsUpdate = true;
214+
i = 0;
215+
for (const [key, value] of Object.entries(jointHierarchy)) {
216+
let distance = dist(frame.getPose(body.get(key), body.get(value)).transform.position);
217+
if (key.includes('right')) {
218+
distance = -distance;
219+
}
220+
if (key.includes('scapula')) {
221+
distance = -distance;
222+
}
223+
const pose = frame.getPose(body.get(key), space);
224+
const position = pose.transform.position;
225+
const orientation = pose.transform.orientation;
226+
227+
matrix.compose(
228+
new THREE.Vector3(position.x, position.y, position.z),
229+
new THREE.Quaternion(orientation.x, orientation.y, orientation.z, orientation.w),
230+
new THREE.Vector3(distance, 0.02, 0.02)
231+
);
172232

233+
skeleton.setMatrixAt(i++, matrix);
173234
}
174235

236+
spheres.instanceMatrix.needsUpdate = true;
237+
skeleton.instanceMatrix.needsUpdate = true;
238+
}
175239
renderer.render(scene, camera);
176240
}
177241
}

0 commit comments

Comments
 (0)