SkinningNode.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import Node from '../core/Node.js';
  2. import {
  3. ShaderNode,
  4. attribute,
  5. buffer,
  6. mat4,
  7. uniform,
  8. positionLocal,
  9. normalLocal,
  10. assign,
  11. element,
  12. add,
  13. mul,
  14. transformDirection
  15. } from '../shadernode/ShaderNodeBaseElements.js';
  16. import { NodeUpdateType } from '../core/constants.js';
  17. const Skinning = new ShaderNode( ( inputs, builder ) => {
  18. const { index, weight, bindMatrix, bindMatrixInverse, boneMatrices } = inputs;
  19. const boneMatX = element( boneMatrices, index.x );
  20. const boneMatY = element( boneMatrices, index.y );
  21. const boneMatZ = element( boneMatrices, index.z );
  22. const boneMatW = element( boneMatrices, index.w );
  23. // POSITION
  24. const skinVertex = mul( bindMatrix, positionLocal );
  25. const skinned = add(
  26. mul( mul( boneMatX, skinVertex ), weight.x ),
  27. mul( mul( boneMatY, skinVertex ), weight.y ),
  28. mul( mul( boneMatZ, skinVertex ), weight.z ),
  29. mul( mul( boneMatW, skinVertex ), weight.w )
  30. );
  31. const skinPosition = mul( bindMatrixInverse, skinned ).xyz;
  32. // NORMAL
  33. let skinMatrix = add(
  34. mul( weight.x, boneMatX ),
  35. mul( weight.y, boneMatY ),
  36. mul( weight.z, boneMatZ ),
  37. mul( weight.w, boneMatW )
  38. );
  39. skinMatrix = mul( mul( bindMatrixInverse, skinMatrix ), bindMatrix );
  40. const skinNormal = transformDirection( skinMatrix, normalLocal ).xyz;
  41. // ASSIGNS
  42. assign( positionLocal, skinPosition ).build( builder );
  43. assign( normalLocal, skinNormal ).build( builder );
  44. } );
  45. class SkinningNode extends Node {
  46. constructor( skinnedMesh ) {
  47. super( 'void' );
  48. this.skinnedMesh = skinnedMesh;
  49. this.updateType = NodeUpdateType.Object;
  50. //
  51. this.skinIndexNode = attribute( 'skinIndex', 'uvec4' );
  52. this.skinWeightNode = attribute( 'skinWeight', 'vec4' );
  53. this.bindMatrixNode = uniform( mat4( skinnedMesh.bindMatrix ) );
  54. this.bindMatrixInverseNode = uniform( mat4( skinnedMesh.bindMatrixInverse ) );
  55. this.boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length );
  56. }
  57. generate( builder ) {
  58. Skinning.call( {
  59. index: this.skinIndexNode,
  60. weight: this.skinWeightNode,
  61. bindMatrix: this.bindMatrixNode,
  62. bindMatrixInverse: this.bindMatrixInverseNode,
  63. boneMatrices: this.boneMatricesNode
  64. }, builder );
  65. }
  66. update() {
  67. this.skinnedMesh.skeleton.update();
  68. }
  69. }
  70. export default SkinningNode;