XRHandMeshModel.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { GLTFLoader } from '../loaders/GLTFLoader.js';
  2. const DEFAULT_HAND_PROFILE_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles/generic-hand/';
  3. class XRHandMeshModel {
  4. constructor( handModel, controller, path, handedness, loader = null, onLoad = null ) {
  5. this.controller = controller;
  6. this.handModel = handModel;
  7. this.bones = [];
  8. if ( loader === null ) {
  9. loader = new GLTFLoader();
  10. loader.setPath( path || DEFAULT_HAND_PROFILE_PATH );
  11. }
  12. loader.load( `${handedness}.glb`, gltf => {
  13. const object = gltf.scene.children[ 0 ];
  14. this.handModel.add( object );
  15. const mesh = object.getObjectByProperty( 'type', 'SkinnedMesh' );
  16. mesh.frustumCulled = false;
  17. mesh.castShadow = true;
  18. mesh.receiveShadow = true;
  19. const joints = [
  20. 'wrist',
  21. 'thumb-metacarpal',
  22. 'thumb-phalanx-proximal',
  23. 'thumb-phalanx-distal',
  24. 'thumb-tip',
  25. 'index-finger-metacarpal',
  26. 'index-finger-phalanx-proximal',
  27. 'index-finger-phalanx-intermediate',
  28. 'index-finger-phalanx-distal',
  29. 'index-finger-tip',
  30. 'middle-finger-metacarpal',
  31. 'middle-finger-phalanx-proximal',
  32. 'middle-finger-phalanx-intermediate',
  33. 'middle-finger-phalanx-distal',
  34. 'middle-finger-tip',
  35. 'ring-finger-metacarpal',
  36. 'ring-finger-phalanx-proximal',
  37. 'ring-finger-phalanx-intermediate',
  38. 'ring-finger-phalanx-distal',
  39. 'ring-finger-tip',
  40. 'pinky-finger-metacarpal',
  41. 'pinky-finger-phalanx-proximal',
  42. 'pinky-finger-phalanx-intermediate',
  43. 'pinky-finger-phalanx-distal',
  44. 'pinky-finger-tip',
  45. ];
  46. joints.forEach( jointName => {
  47. const bone = object.getObjectByName( jointName );
  48. if ( bone !== undefined ) {
  49. bone.jointName = jointName;
  50. } else {
  51. console.warn( `Couldn't find ${jointName} in ${handedness} hand mesh` );
  52. }
  53. this.bones.push( bone );
  54. } );
  55. if ( onLoad ) onLoad( object );
  56. } );
  57. }
  58. updateMesh() {
  59. // XR Joints
  60. const XRJoints = this.controller.joints;
  61. for ( let i = 0; i < this.bones.length; i ++ ) {
  62. const bone = this.bones[ i ];
  63. if ( bone ) {
  64. const XRJoint = XRJoints[ bone.jointName ];
  65. if ( XRJoint.visible ) {
  66. const position = XRJoint.position;
  67. bone.position.copy( position );
  68. bone.quaternion.copy( XRJoint.quaternion );
  69. // bone.scale.setScalar( XRJoint.jointRadius || defaultRadius );
  70. }
  71. }
  72. }
  73. }
  74. }
  75. export { XRHandMeshModel };