115 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { GLTFLoader } from '../loaders/GLTFLoader.js';
 | 
						|
 | 
						|
const DEFAULT_HAND_PROFILE_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles/generic-hand/';
 | 
						|
 | 
						|
class XRHandMeshModel {
 | 
						|
 | 
						|
	constructor( handModel, controller, path, handedness, loader = null, onLoad = null ) {
 | 
						|
 | 
						|
		this.controller = controller;
 | 
						|
		this.handModel = handModel;
 | 
						|
 | 
						|
		this.bones = [];
 | 
						|
 | 
						|
		if ( loader === null ) {
 | 
						|
 | 
						|
			loader = new GLTFLoader();
 | 
						|
			loader.setPath( path || DEFAULT_HAND_PROFILE_PATH );
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		loader.load( `${handedness}.glb`, 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 );
 | 
						|
 | 
						|
			} );
 | 
						|
 | 
						|
			if ( onLoad ) onLoad( object );
 | 
						|
 | 
						|
		} );
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	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;
 | 
						|
 | 
						|
					bone.position.copy( position );
 | 
						|
					bone.quaternion.copy( XRJoint.quaternion );
 | 
						|
					// bone.scale.setScalar( XRJoint.jointRadius || defaultRadius );
 | 
						|
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
export { XRHandMeshModel };
 |