VelocityNode.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { Vector3 } from '../../../../build/three.module.js';
  2. import { Vector3Node } from '../inputs/Vector3Node.js';
  3. class VelocityNode extends Vector3Node {
  4. constructor( target, params ) {
  5. super();
  6. this.params = {};
  7. this.velocity = new Vector3();
  8. this.setTarget( target );
  9. this.setParams( params );
  10. }
  11. getReadonly( /*builder*/ ) {
  12. return false;
  13. }
  14. setParams( params ) {
  15. switch ( this.params.type ) {
  16. case 'elastic':
  17. delete this.moment;
  18. delete this.speed;
  19. delete this.springVelocity;
  20. delete this.lastVelocity;
  21. break;
  22. }
  23. this.params = params || {};
  24. switch ( this.params.type ) {
  25. case 'elastic':
  26. this.moment = new Vector3();
  27. this.speed = new Vector3();
  28. this.springVelocity = new Vector3();
  29. this.lastVelocity = new Vector3();
  30. break;
  31. }
  32. }
  33. setTarget( target ) {
  34. if ( this.target ) {
  35. delete this.position;
  36. delete this.oldPosition;
  37. }
  38. this.target = target;
  39. if ( target ) {
  40. this.position = target.getWorldPosition( this.position || new Vector3() );
  41. this.oldPosition = this.position.clone();
  42. }
  43. }
  44. updateFrameVelocity( /*frame*/ ) {
  45. if ( this.target ) {
  46. this.position = this.target.getWorldPosition( this.position || new Vector3() );
  47. this.velocity.subVectors( this.position, this.oldPosition );
  48. this.oldPosition.copy( this.position );
  49. }
  50. }
  51. updateFrame( frame ) {
  52. this.updateFrameVelocity( frame );
  53. switch ( this.params.type ) {
  54. case 'elastic':
  55. // convert to real scale: 0 at 1 values
  56. const deltaFps = frame.delta * ( this.params.fps || 60 );
  57. const spring = Math.pow( this.params.spring, deltaFps ),
  58. damping = Math.pow( this.params.damping, deltaFps );
  59. // fix relative frame-rate
  60. this.velocity.multiplyScalar( Math.exp( - this.params.damping * deltaFps ) );
  61. // elastic
  62. this.velocity.add( this.springVelocity );
  63. this.velocity.add( this.speed.multiplyScalar( damping ).multiplyScalar( 1 - spring ) );
  64. // speed
  65. this.speed.subVectors( this.velocity, this.lastVelocity );
  66. // spring velocity
  67. this.springVelocity.add( this.speed );
  68. this.springVelocity.multiplyScalar( spring );
  69. // moment
  70. this.moment.add( this.springVelocity );
  71. // damping
  72. this.moment.multiplyScalar( damping );
  73. this.lastVelocity.copy( this.velocity );
  74. this.value.copy( this.moment );
  75. break;
  76. default:
  77. this.value.copy( this.velocity );
  78. }
  79. }
  80. copy( source ) {
  81. super.copy( source );
  82. if ( source.target ) this.setTarget( source.target );
  83. this.setParams( source.params );
  84. return this;
  85. }
  86. toJSON( meta ) {
  87. const data = super.toJSON( meta );
  88. if ( this.target ) data.target = this.target.uuid;
  89. // clone params
  90. data.params = JSON.parse( JSON.stringify( this.params ) );
  91. return data;
  92. }
  93. }
  94. VelocityNode.prototype.nodeType = 'Velocity';
  95. export { VelocityNode };