未验证 提交 a51bed7e 编写于 作者: M Michael Herzog 提交者: GitHub

Examples: Clean up. (#21794)

上级 9bbd837d
import { Object3D, Sphere, Box3 } from "../../../build/three.module.js";
import { Object3D, Sphere, Box3 } from '../../../build/three.module.js';
import { fetchProfile } from '../libs/motion-controllers.module.js';
import { XRHandMeshModel } from "./XRHandMeshModel.js";
import { XRHandMeshModel } from './XRHandMeshModel.js';
const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles';
const DEFAULT_PROFILE = 'generic-hand';
const POINTING_JOINT = "index-finger-tip";
const POINTING_JOINT = 'index-finger-tip';
class OculusHandModel extends Object3D {
constructor(controller) {
super();
this.controller = controller;
this.motionController = null;
this.envMap = null;
this.mesh = null;
controller.addEventListener("connected", (event) => {
const xrInputSource = event.data;
if (xrInputSource.hand && !this.motionController) {
this.visible = true;
this.xrInputSource = xrInputSource;
fetchProfile(xrInputSource, DEFAULT_PROFILES_PATH, DEFAULT_PROFILE).then(({ profile, assetPath }) => {
this.motionController = new XRHandMeshModel(
this,
controller,
assetPath
);
}).catch((err) => {
console.warn(err);
});
}
});
controller.addEventListener("disconnected", () => {
this.clear();
this.motionController = null;
})
}
updateMatrixWorld(force) {
super.updateMatrixWorld(force);
if (this.motionController) {
this.motionController.updateMesh();
}
}
getPointerPosition() {
let indexFingerTip = this.controller.joints[POINTING_JOINT];
if (indexFingerTip) {
return indexFingerTip.position;
} else {
return null;
}
}
intersectBoxObject(boxObject) {
let pointerPosition = this.getPointerPosition();
if (pointerPosition) {
let indexSphere = new Sphere(pointerPosition, TOUCH_RADIUS);
let box = new Box3().setFromObject(boxObject);
return indexSphere.intersectsBox(box);
} else {
return false;
}
}
checkButton(button) {
if (this.intersectBoxObject(button)) {
button.onPress();
} else {
button.onClear();
}
if (button.isPressed()) {
button.whilePressed();
}
}
constructor( controller ) {
super();
this.controller = controller;
this.motionController = null;
this.envMap = null;
this.mesh = null;
controller.addEventListener( 'connected', ( event ) => {
const xrInputSource = event.data;
if ( xrInputSource.hand && ! this.motionController ) {
this.visible = true;
this.xrInputSource = xrInputSource;
fetchProfile( xrInputSource, DEFAULT_PROFILES_PATH, DEFAULT_PROFILE ).then( ( { profile, assetPath } ) => {
this.motionController = new XRHandMeshModel(
this,
controller,
assetPath
);
} ).catch( ( err ) => {
console.warn( err );
} );
}
} );
controller.addEventListener( 'disconnected', () => {
this.clear();
this.motionController = null;
} );
}
updateMatrixWorld( force ) {
super.updateMatrixWorld( force );
if ( this.motionController ) {
this.motionController.updateMesh();
}
}
getPointerPosition() {
const indexFingerTip = this.controller.joints[ POINTING_JOINT ];
if ( indexFingerTip ) {
return indexFingerTip.position;
} else {
return null;
}
}
intersectBoxObject( boxObject ) {
const pointerPosition = this.getPointerPosition();
if ( pointerPosition ) {
const indexSphere = new Sphere( pointerPosition, TOUCH_RADIUS );
const box = new Box3().setFromObject( boxObject );
return indexSphere.intersectsBox( box );
} else {
return false;
}
}
checkButton( button ) {
if ( this.intersectBoxObject( button ) ) {
button.onPress();
} else {
button.onClear();
}
if ( button.isPressed() ) {
button.whilePressed();
}
}
}
export { OculusHandModel };
import * as THREE from "../../../build/three.module.js";
import * as THREE from '../../../build/three.module.js';
const PINCH_MAX = 0.05;
const PINCH_THRESHOLD = 0.02;
......@@ -13,302 +13,375 @@ const POINTER_LENGTH = 0.035;
const POINTER_SEGMENTS = 16;
const POINTER_RINGS = 12;
const POINTER_HEMISPHERE_ANGLE = 110;
const YAXIS = new THREE.Vector3(0, 1, 0);
const ZAXIS = new THREE.Vector3(0, 0, 1);
const YAXIS = new THREE.Vector3( 0, 1, 0 );
const ZAXIS = new THREE.Vector3( 0, 0, 1 );
const CURSOR_RADIUS = 0.02;
const CURSOR_MAX_DISTANCE = 1.5;
class OculusHandPointerModel extends THREE.Object3D {
constructor(hand, controller) {
super();
this.hand = hand;
this.controller = controller;
this.motionController = null;
this.envMap = null;
this.mesh = null;
this.pointerGeometry = null;
this.pointerMesh = null;
this.pointerObject = null;
this.pinched = false;
this.attached = false;
this.cursorObject = null;
this.raycaster = null;
hand.addEventListener("connected", (event) => {
const xrInputSource = event.data;
if (xrInputSource.hand) {
this.visible = true;
this.xrInputSource = xrInputSource;
this.createPointer();
}
});
}
_drawVerticesRing(vertices, baseVector, ringIndex) {
const segmentVector = baseVector.clone();
for (var i = 0; i < POINTER_SEGMENTS; i++) {
segmentVector.applyAxisAngle(ZAXIS, (Math.PI * 2) / POINTER_SEGMENTS);
let vid = ringIndex * POINTER_SEGMENTS + i;
vertices[3 * vid] = segmentVector.x;
vertices[3 * vid + 1] = segmentVector.y;
vertices[3 * vid + 2] = segmentVector.z;
}
}
_updatePointerVertices(rearRadius) {
const vertices = this.pointerGeometry.attributes.position.array;
// first ring for front face
const frontFaceBase = new THREE.Vector3(
POINTER_FRONT_RADIUS,
0,
-1 * (POINTER_LENGTH - rearRadius)
);
this._drawVerticesRing(vertices, frontFaceBase, 0);
// rings for rear hemisphere
const rearBase = new THREE.Vector3(
Math.sin((Math.PI * POINTER_HEMISPHERE_ANGLE) / 180) * rearRadius,
Math.cos((Math.PI * POINTER_HEMISPHERE_ANGLE) / 180) * rearRadius,
0
);
for (var i = 0; i < POINTER_RINGS; i++) {
this._drawVerticesRing(vertices, rearBase, i + 1);
rearBase.applyAxisAngle(
YAXIS,
(Math.PI * POINTER_HEMISPHERE_ANGLE) / 180 / (POINTER_RINGS * -2)
);
}
// front and rear face center vertices
const frontCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS);
const rearCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS) + 1;
const frontCenter = new THREE.Vector3(
0,
0,
-1 * (POINTER_LENGTH - rearRadius)
);
vertices[frontCenterIndex * 3] = frontCenter.x;
vertices[frontCenterIndex * 3 + 1] = frontCenter.y;
vertices[frontCenterIndex * 3 + 2] = frontCenter.z;
const rearCenter = new THREE.Vector3(0, 0, rearRadius);
vertices[rearCenterIndex * 3] = rearCenter.x;
vertices[rearCenterIndex * 3 + 1] = rearCenter.y;
vertices[rearCenterIndex * 3 + 2] = rearCenter.z;
this.pointerGeometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(vertices, 3)
);
// verticesNeedUpdate = true;
}
createPointer() {
var i, j;
const vertices = new Array(
((POINTER_RINGS + 1) * POINTER_SEGMENTS + 2) * 3
).fill(0);
// const vertices = [];
const indices = [];
this.pointerGeometry = new THREE.BufferGeometry();
this.pointerGeometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(vertices, 3)
);
this._updatePointerVertices(POINTER_REAR_RADIUS);
// construct faces to connect rings
for (i = 0; i < POINTER_RINGS; i++) {
for (j = 0; j < POINTER_SEGMENTS - 1; j++) {
indices.push(
i * POINTER_SEGMENTS + j,
i * POINTER_SEGMENTS + j + 1,
(i + 1) * POINTER_SEGMENTS + j
);
indices.push(
i * POINTER_SEGMENTS + j + 1,
(i + 1) * POINTER_SEGMENTS + j + 1,
(i + 1) * POINTER_SEGMENTS + j
);
}
indices.push(
(i + 1) * POINTER_SEGMENTS - 1,
i * POINTER_SEGMENTS,
(i + 2) * POINTER_SEGMENTS - 1
);
indices.push(
i * POINTER_SEGMENTS,
(i + 1) * POINTER_SEGMENTS,
(i + 2) * POINTER_SEGMENTS - 1
);
}
// construct front and rear face
const frontCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS);
const rearCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS) + 1;
for (i = 0; i < POINTER_SEGMENTS - 1; i++) {
indices.push(frontCenterIndex, i + 1, i);
indices.push(
rearCenterIndex,
i + POINTER_SEGMENTS * POINTER_RINGS,
i + POINTER_SEGMENTS * POINTER_RINGS + 1
);
}
indices.push(frontCenterIndex, 0, POINTER_SEGMENTS - 1);
indices.push(
rearCenterIndex,
POINTER_SEGMENTS * (POINTER_RINGS + 1) - 1,
POINTER_SEGMENTS * POINTER_RINGS
);
const material = new THREE.MeshBasicMaterial();
material.transparent = true;
material.opacity = POINTER_OPACITY_MIN;
this.pointerGeometry.setIndex(indices);
this.pointerMesh = new THREE.Mesh(this.pointerGeometry, material);
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS);
this.pointerObject = new THREE.Object3D();
this.pointerObject.add(this.pointerMesh);
this.raycaster = new THREE.Raycaster();
// create cursor
const cursorGeometry = new THREE.SphereGeometry(CURSOR_RADIUS, 10, 10);
const cursorMaterial = new THREE.MeshBasicMaterial();
cursorMaterial.transparent = true;
cursorMaterial.opacity = POINTER_OPACITY_MIN;
this.cursorObject = new THREE.Mesh(cursorGeometry, cursorMaterial);
this.pointerObject.add(this.cursorObject);
this.add(this.pointerObject);
}
_updateRaycaster() {
if (this.raycaster) {
const pointerMatrix = this.pointerObject.matrixWorld;
const tempMatrix = new THREE.Matrix4();
tempMatrix.identity().extractRotation(pointerMatrix);
this.raycaster.ray.origin.setFromMatrixPosition(pointerMatrix);
this.raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix);
}
}
_updatePointer() {
this.pointerObject.visible = this.controller.visible;
const indexTip = this.hand.joints["index-finger-tip"];
const thumbTip = this.hand.joints["thumb-tip"];
const distance = indexTip.position.distanceTo(thumbTip.position);
const position = indexTip.position
.clone()
.add(thumbTip.position)
.multiplyScalar(0.5);
this.pointerObject.position.copy(position);
this.pointerObject.quaternion.copy(this.controller.quaternion);
this.pinched = distance <= PINCH_THRESHOLD;
const pinchScale = (distance - PINCH_MIN) / (PINCH_MAX - PINCH_MIN);
const focusScale = (distance - PINCH_MIN) / (PINCH_THRESHOLD - PINCH_MIN);
if (pinchScale > 1) {
this._updatePointerVertices(POINTER_REAR_RADIUS);
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS);
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
} else if (pinchScale > 0) {
const rearRadius =
(POINTER_REAR_RADIUS - POINTER_REAR_RADIUS_MIN) * pinchScale +
constructor( hand, controller ) {
super();
this.hand = hand;
this.controller = controller;
this.motionController = null;
this.envMap = null;
this.mesh = null;
this.pointerGeometry = null;
this.pointerMesh = null;
this.pointerObject = null;
this.pinched = false;
this.attached = false;
this.cursorObject = null;
this.raycaster = null;
hand.addEventListener( 'connected', ( event ) => {
const xrInputSource = event.data;
if ( xrInputSource.hand ) {
this.visible = true;
this.xrInputSource = xrInputSource;
this.createPointer();
}
} );
}
_drawVerticesRing( vertices, baseVector, ringIndex ) {
const segmentVector = baseVector.clone();
for ( var i = 0; i < POINTER_SEGMENTS; i ++ ) {
segmentVector.applyAxisAngle( ZAXIS, ( Math.PI * 2 ) / POINTER_SEGMENTS );
const vid = ringIndex * POINTER_SEGMENTS + i;
vertices[ 3 * vid ] = segmentVector.x;
vertices[ 3 * vid + 1 ] = segmentVector.y;
vertices[ 3 * vid + 2 ] = segmentVector.z;
}
}
_updatePointerVertices( rearRadius ) {
const vertices = this.pointerGeometry.attributes.position.array;
// first ring for front face
const frontFaceBase = new THREE.Vector3(
POINTER_FRONT_RADIUS,
0,
- 1 * ( POINTER_LENGTH - rearRadius )
);
this._drawVerticesRing( vertices, frontFaceBase, 0 );
// rings for rear hemisphere
const rearBase = new THREE.Vector3(
Math.sin( ( Math.PI * POINTER_HEMISPHERE_ANGLE ) / 180 ) * rearRadius,
Math.cos( ( Math.PI * POINTER_HEMISPHERE_ANGLE ) / 180 ) * rearRadius,
0
);
for ( var i = 0; i < POINTER_RINGS; i ++ ) {
this._drawVerticesRing( vertices, rearBase, i + 1 );
rearBase.applyAxisAngle(
YAXIS,
( Math.PI * POINTER_HEMISPHERE_ANGLE ) / 180 / ( POINTER_RINGS * - 2 )
);
}
// front and rear face center vertices
const frontCenterIndex = POINTER_SEGMENTS * ( 1 + POINTER_RINGS );
const rearCenterIndex = POINTER_SEGMENTS * ( 1 + POINTER_RINGS ) + 1;
const frontCenter = new THREE.Vector3(
0,
0,
- 1 * ( POINTER_LENGTH - rearRadius )
);
vertices[ frontCenterIndex * 3 ] = frontCenter.x;
vertices[ frontCenterIndex * 3 + 1 ] = frontCenter.y;
vertices[ frontCenterIndex * 3 + 2 ] = frontCenter.z;
const rearCenter = new THREE.Vector3( 0, 0, rearRadius );
vertices[ rearCenterIndex * 3 ] = rearCenter.x;
vertices[ rearCenterIndex * 3 + 1 ] = rearCenter.y;
vertices[ rearCenterIndex * 3 + 2 ] = rearCenter.z;
this.pointerGeometry.setAttribute(
'position',
new THREE.Float32BufferAttribute( vertices, 3 )
);
// verticesNeedUpdate = true;
}
createPointer() {
var i, j;
const vertices = new Array(
( ( POINTER_RINGS + 1 ) * POINTER_SEGMENTS + 2 ) * 3
).fill( 0 );
// const vertices = [];
const indices = [];
this.pointerGeometry = new THREE.BufferGeometry();
this.pointerGeometry.setAttribute(
'position',
new THREE.Float32BufferAttribute( vertices, 3 )
);
this._updatePointerVertices( POINTER_REAR_RADIUS );
// construct faces to connect rings
for ( i = 0; i < POINTER_RINGS; i ++ ) {
for ( j = 0; j < POINTER_SEGMENTS - 1; j ++ ) {
indices.push(
i * POINTER_SEGMENTS + j,
i * POINTER_SEGMENTS + j + 1,
( i + 1 ) * POINTER_SEGMENTS + j
);
indices.push(
i * POINTER_SEGMENTS + j + 1,
( i + 1 ) * POINTER_SEGMENTS + j + 1,
( i + 1 ) * POINTER_SEGMENTS + j
);
}
indices.push(
( i + 1 ) * POINTER_SEGMENTS - 1,
i * POINTER_SEGMENTS,
( i + 2 ) * POINTER_SEGMENTS - 1
);
indices.push(
i * POINTER_SEGMENTS,
( i + 1 ) * POINTER_SEGMENTS,
( i + 2 ) * POINTER_SEGMENTS - 1
);
}
// construct front and rear face
const frontCenterIndex = POINTER_SEGMENTS * ( 1 + POINTER_RINGS );
const rearCenterIndex = POINTER_SEGMENTS * ( 1 + POINTER_RINGS ) + 1;
for ( i = 0; i < POINTER_SEGMENTS - 1; i ++ ) {
indices.push( frontCenterIndex, i + 1, i );
indices.push(
rearCenterIndex,
i + POINTER_SEGMENTS * POINTER_RINGS,
i + POINTER_SEGMENTS * POINTER_RINGS + 1
);
}
indices.push( frontCenterIndex, 0, POINTER_SEGMENTS - 1 );
indices.push(
rearCenterIndex,
POINTER_SEGMENTS * ( POINTER_RINGS + 1 ) - 1,
POINTER_SEGMENTS * POINTER_RINGS
);
const material = new THREE.MeshBasicMaterial();
material.transparent = true;
material.opacity = POINTER_OPACITY_MIN;
this.pointerGeometry.setIndex( indices );
this.pointerMesh = new THREE.Mesh( this.pointerGeometry, material );
this.pointerMesh.position.set( 0, 0, - 1 * POINTER_REAR_RADIUS );
this.pointerObject = new THREE.Object3D();
this.pointerObject.add( this.pointerMesh );
this.raycaster = new THREE.Raycaster();
// create cursor
const cursorGeometry = new THREE.SphereGeometry( CURSOR_RADIUS, 10, 10 );
const cursorMaterial = new THREE.MeshBasicMaterial();
cursorMaterial.transparent = true;
cursorMaterial.opacity = POINTER_OPACITY_MIN;
this.cursorObject = new THREE.Mesh( cursorGeometry, cursorMaterial );
this.pointerObject.add( this.cursorObject );
this.add( this.pointerObject );
}
_updateRaycaster() {
if ( this.raycaster ) {
const pointerMatrix = this.pointerObject.matrixWorld;
const tempMatrix = new THREE.Matrix4();
tempMatrix.identity().extractRotation( pointerMatrix );
this.raycaster.ray.origin.setFromMatrixPosition( pointerMatrix );
this.raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix );
}
}
_updatePointer() {
this.pointerObject.visible = this.controller.visible;
const indexTip = this.hand.joints[ 'index-finger-tip' ];
const thumbTip = this.hand.joints[ 'thumb-tip' ];
const distance = indexTip.position.distanceTo( thumbTip.position );
const position = indexTip.position
.clone()
.add( thumbTip.position )
.multiplyScalar( 0.5 );
this.pointerObject.position.copy( position );
this.pointerObject.quaternion.copy( this.controller.quaternion );
this.pinched = distance <= PINCH_THRESHOLD;
const pinchScale = ( distance - PINCH_MIN ) / ( PINCH_MAX - PINCH_MIN );
const focusScale = ( distance - PINCH_MIN ) / ( PINCH_THRESHOLD - PINCH_MIN );
if ( pinchScale > 1 ) {
this._updatePointerVertices( POINTER_REAR_RADIUS );
this.pointerMesh.position.set( 0, 0, - 1 * POINTER_REAR_RADIUS );
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
} else if ( pinchScale > 0 ) {
const rearRadius =
( POINTER_REAR_RADIUS - POINTER_REAR_RADIUS_MIN ) * pinchScale +
POINTER_REAR_RADIUS_MIN;
this._updatePointerVertices(rearRadius);
if (focusScale < 1) {
this.pointerMesh.position.set(
0,
0,
-1 * rearRadius - (1 - focusScale) * POINTER_ADVANCE_MAX
);
this.pointerMesh.material.opacity =
this._updatePointerVertices( rearRadius );
if ( focusScale < 1 ) {
this.pointerMesh.position.set(
0,
0,
- 1 * rearRadius - ( 1 - focusScale ) * POINTER_ADVANCE_MAX
);
this.pointerMesh.material.opacity =
POINTER_OPACITY_MIN +
(1 - focusScale) * (POINTER_OPACITY_MAX - POINTER_OPACITY_MIN);
} else {
this.pointerMesh.position.set(0, 0, -1 * rearRadius);
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
}
} else {
this._updatePointerVertices(POINTER_REAR_RADIUS_MIN);
this.pointerMesh.position.set(
0,
0,
-1 * POINTER_REAR_RADIUS_MIN - POINTER_ADVANCE_MAX
);
this.pointerMesh.material.opacity = POINTER_OPACITY_MAX;
}
this.cursorObject.material.opacity = this.pointerMesh.material.opacity;
}
updateMatrixWorld(force) {
super.updateMatrixWorld( force );
if (this.pointerGeometry) {
this._updatePointer();
this._updateRaycaster();
}
}
isPinched() {
return this.pinched;
}
setAttached(attached) {
this.attached = attached;
}
isAttached() {
return this.attached;
}
intersectObject(object) {
if (this.raycaster) {
return this.raycaster.intersectObject(object);
}
}
intersectObjects(objects) {
if (this.raycaster) {
return this.raycaster.intersectObjects(objects);
}
}
checkIntersections(objects) {
if (this.raycaster && !this.attached) {
let intersections = this.raycaster.intersectObjects(objects);
let direction = new THREE.Vector3(0, 0, -1);
if (intersections.length > 0) {
let intersection = intersections[0];
let distance = intersection.distance;
this.cursorObject.position.copy(direction.multiplyScalar(distance));
} else {
this.cursorObject.position.copy(direction.multiplyScalar(CURSOR_MAX_DISTANCE));
}
}
}
setCursor(distance) {
let direction = new THREE.Vector3(0, 0, -1);
if (this.raycaster && !this.attached) {
this.cursorObject.position.copy(direction.multiplyScalar(distance));
}
}
( 1 - focusScale ) * ( POINTER_OPACITY_MAX - POINTER_OPACITY_MIN );
} else {
this.pointerMesh.position.set( 0, 0, - 1 * rearRadius );
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
}
} else {
this._updatePointerVertices( POINTER_REAR_RADIUS_MIN );
this.pointerMesh.position.set(
0,
0,
- 1 * POINTER_REAR_RADIUS_MIN - POINTER_ADVANCE_MAX
);
this.pointerMesh.material.opacity = POINTER_OPACITY_MAX;
}
this.cursorObject.material.opacity = this.pointerMesh.material.opacity;
}
updateMatrixWorld( force ) {
super.updateMatrixWorld( force );
if ( this.pointerGeometry ) {
this._updatePointer();
this._updateRaycaster();
}
}
isPinched() {
return this.pinched;
}
setAttached( attached ) {
this.attached = attached;
}
isAttached() {
return this.attached;
}
intersectObject( object ) {
if ( this.raycaster ) {
return this.raycaster.intersectObject( object );
}
}
intersectObjects( objects ) {
if ( this.raycaster ) {
return this.raycaster.intersectObjects( objects );
}
}
checkIntersections( objects ) {
if ( this.raycaster && ! this.attached ) {
const intersections = this.raycaster.intersectObjects( objects );
const direction = new THREE.Vector3( 0, 0, - 1 );
if ( intersections.length > 0 ) {
const intersection = intersections[ 0 ];
const distance = intersection.distance;
this.cursorObject.position.copy( direction.multiplyScalar( distance ) );
} else {
this.cursorObject.position.copy( direction.multiplyScalar( CURSOR_MAX_DISTANCE ) );
}
}
}
setCursor( distance ) {
const direction = new THREE.Vector3( 0, 0, - 1 );
if ( this.raycaster && ! this.attached ) {
this.cursorObject.position.copy( direction.multiplyScalar( distance ) );
}
}
}
export { OculusHandPointerModel };
import * as THREE from "../../../build/three.module.js";
import * as THREE from '../../../build/three.module.js';
function createText(message, height) {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
let metrics = null,
textHeight = 100;
context.font = "normal " + textHeight + "px Arial";
metrics = context.measureText(message);
const textWidth = metrics.width;
canvas.width = textWidth;
canvas.height = textHeight;
context.font = "normal " + textHeight + "px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = "#ffffff";
context.fillText(message, textWidth / 2, textHeight / 2);
function createText( message, height ) {
const canvas = document.createElement( 'canvas' );
const context = canvas.getContext( '2d' );
let metrics = null;
const textHeight = 100;
context.font = 'normal ' + textHeight + 'px Arial';
metrics = context.measureText( message );
const textWidth = metrics.width;
canvas.width = textWidth;
canvas.height = textHeight;
context.font = 'normal ' + textHeight + 'px Arial';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillStyle = '#ffffff';
context.fillText( message, textWidth / 2, textHeight / 2 );
const texture = new THREE.Texture( canvas );
texture.needsUpdate = true;
//var spriteAlignment = new THREE.Vector2(0,0) ;
const material = new THREE.MeshBasicMaterial( {
color: 0xffffff,
side: THREE.DoubleSide,
map: texture,
transparent: true,
} );
const geometry = new THREE.PlaneGeometry(
( height * textWidth ) / textHeight,
height
);
const plane = new THREE.Mesh( geometry, material );
return plane;
const texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
//var spriteAlignment = new THREE.Vector2(0,0) ;
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
map: texture,
transparent: true,
});
const geometry = new THREE.PlaneGeometry(
(height * textWidth) / textHeight,
height
);
let plane = new THREE.Mesh(geometry, material);
return plane;
}
export { createText };
......@@ -2,82 +2,103 @@ import { GLTFLoader } from '../loaders/GLTFLoader.js';
class XRHandMeshModel {
constructor(handModel, controller, assetUrl) {
this.controller = controller;
this.handModel = handModel;
this.bones = [];
const loader = new GLTFLoader();
loader.setPath('');
loader.load(assetUrl, gltf => {
const object = gltf.scene.children[0];
this.handModel.add(object);
const mesh = object.getObjectByProperty('type', 'SkinnedMesh');
mesh.frustumCulled = false;
mesh.castShadow = true;
mesh.receiveShadow = true;
const joints = [
'wrist',
'thumb-metacarpal',
'thumb-phalanx-proximal',
'thumb-phalanx-distal',
'thumb-tip',
'index-finger-metacarpal',
'index-finger-phalanx-proximal',
'index-finger-phalanx-intermediate',
'index-finger-phalanx-distal',
'index-finger-tip',
'middle-finger-metacarpal',
'middle-finger-phalanx-proximal',
'middle-finger-phalanx-intermediate',
'middle-finger-phalanx-distal',
'middle-finger-tip',
'ring-finger-metacarpal',
'ring-finger-phalanx-proximal',
'ring-finger-phalanx-intermediate',
'ring-finger-phalanx-distal',
'ring-finger-tip',
'pinky-finger-metacarpal',
'pinky-finger-phalanx-proximal',
'pinky-finger-phalanx-intermediate',
'pinky-finger-phalanx-distal',
'pinky-finger-tip',
];
joints.forEach(jointName => {
const bone = object.getObjectByName(jointName);
if (bone !== undefined) {
bone.jointName = jointName;
} else {
console.warn(`Couldn't find ${jointName} in ${handedness} hand mesh`);
}
this.bones.push(bone);
});
});
}
updateMesh() {
// XR Joints
const XRJoints = this.controller.joints;
for (let i = 0; i < this.bones.length; i++) {
const bone = this.bones[i];
if (bone) {
const XRJoint = XRJoints[bone.jointName];
if (XRJoint.visible) {
const position = XRJoint.position;
if (bone) {
bone.position.copy(position);
bone.quaternion.copy(XRJoint.quaternion);
// bone.scale.setScalar( XRJoint.jointRadius || defaultRadius );
}
}
}
}
}
constructor( handModel, controller, assetUrl ) {
this.controller = controller;
this.handModel = handModel;
this.bones = [];
const loader = new GLTFLoader();
loader.setPath( '' );
loader.load( assetUrl, gltf => {
const object = gltf.scene.children[ 0 ];
this.handModel.add( object );
const mesh = object.getObjectByProperty( 'type', 'SkinnedMesh' );
mesh.frustumCulled = false;
mesh.castShadow = true;
mesh.receiveShadow = true;
const joints = [
'wrist',
'thumb-metacarpal',
'thumb-phalanx-proximal',
'thumb-phalanx-distal',
'thumb-tip',
'index-finger-metacarpal',
'index-finger-phalanx-proximal',
'index-finger-phalanx-intermediate',
'index-finger-phalanx-distal',
'index-finger-tip',
'middle-finger-metacarpal',
'middle-finger-phalanx-proximal',
'middle-finger-phalanx-intermediate',
'middle-finger-phalanx-distal',
'middle-finger-tip',
'ring-finger-metacarpal',
'ring-finger-phalanx-proximal',
'ring-finger-phalanx-intermediate',
'ring-finger-phalanx-distal',
'ring-finger-tip',
'pinky-finger-metacarpal',
'pinky-finger-phalanx-proximal',
'pinky-finger-phalanx-intermediate',
'pinky-finger-phalanx-distal',
'pinky-finger-tip',
];
joints.forEach( jointName => {
const bone = object.getObjectByName( jointName );
if ( bone !== undefined ) {
bone.jointName = jointName;
} else {
console.warn( `Couldn't find ${jointName} in ${handedness} hand mesh` );
}
this.bones.push( bone );
} );
} );
}
updateMesh() {
// XR Joints
const XRJoints = this.controller.joints;
for ( let i = 0; i < this.bones.length; i ++ ) {
const bone = this.bones[ i ];
if ( bone ) {
const XRJoint = XRJoints[ bone.jointName ];
if ( XRJoint.visible ) {
const position = XRJoint.position;
if ( bone ) {
bone.position.copy( position );
bone.quaternion.copy( XRJoint.quaternion );
// bone.scale.setScalar( XRJoint.jointRadius || defaultRadius );
}
}
}
}
}
}
export { XRHandMeshModel };
......@@ -6,12 +6,12 @@ import {
XRHandPrimitiveModel
} from './XRHandPrimitiveModel.js';
import {
XRHandMeshModel
} from "./XRHandMeshModel.js";
import {
XRHandMeshModel
} from './XRHandMeshModel.js';
import {
fetchProfile
import {
fetchProfile
} from '../libs/motion-controllers.module.js';
const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles';
......@@ -84,15 +84,15 @@ class XRHandModelFactory {
} else if ( profile === 'oculus' ) {
fetchProfile(xrInputSource, DEFAULT_PROFILES_PATH, DEFAULT_PROFILE).then(({ profile, assetPath }) => {
handModel.motionController = new XRHandMeshModel( handModel, controller, assetPath);
fetchProfile( xrInputSource, DEFAULT_PROFILES_PATH, DEFAULT_PROFILE ).then( ( { profile, assetPath } ) => {
handModel.motionController = new XRHandMeshModel( handModel, controller, assetPath );
}).catch((err) => {
} ).catch( ( err ) => {
console.warn(err);
console.warn( err );
});
} );
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册