SkinningNode.js 2.7 KB

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