MDDLoader.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /**
  2. * MDD is a special format that stores a position for every vertex in a model for every frame in an animation.
  3. * Similar to BVH, it can be used to transfer animation data between different 3D applications or engines.
  4. *
  5. * MDD stores its data in binary format (big endian) in the following way:
  6. *
  7. * number of frames (a single uint32)
  8. * number of vertices (a single uint32)
  9. * time values for each frame (sequence of float32)
  10. * vertex data for each frame (sequence of float32)
  11. */
  12. import {
  13. AnimationClip,
  14. BufferAttribute,
  15. FileLoader,
  16. Loader,
  17. NumberKeyframeTrack
  18. } from 'three';
  19. class MDDLoader extends Loader {
  20. constructor( manager ) {
  21. super( manager );
  22. }
  23. load( url, onLoad, onProgress, onError ) {
  24. const scope = this;
  25. const loader = new FileLoader( this.manager );
  26. loader.setPath( this.path );
  27. loader.setResponseType( 'arraybuffer' );
  28. loader.load( url, function ( data ) {
  29. onLoad( scope.parse( data ) );
  30. }, onProgress, onError );
  31. }
  32. parse( data ) {
  33. const view = new DataView( data );
  34. const totalFrames = view.getUint32( 0 );
  35. const totalPoints = view.getUint32( 4 );
  36. let offset = 8;
  37. // animation clip
  38. const times = new Float32Array( totalFrames );
  39. const values = new Float32Array( totalFrames * totalFrames ).fill( 0 );
  40. for ( let i = 0; i < totalFrames; i ++ ) {
  41. times[ i ] = view.getFloat32( offset ); offset += 4;
  42. values[ ( totalFrames * i ) + i ] = 1;
  43. }
  44. const track = new NumberKeyframeTrack( '.morphTargetInfluences', times, values );
  45. const clip = new AnimationClip( 'default', times[ times.length - 1 ], [ track ] );
  46. // morph targets
  47. const morphTargets = [];
  48. for ( let i = 0; i < totalFrames; i ++ ) {
  49. const morphTarget = new Float32Array( totalPoints * 3 );
  50. for ( let j = 0; j < totalPoints; j ++ ) {
  51. const stride = ( j * 3 );
  52. morphTarget[ stride + 0 ] = view.getFloat32( offset ); offset += 4; // x
  53. morphTarget[ stride + 1 ] = view.getFloat32( offset ); offset += 4; // y
  54. morphTarget[ stride + 2 ] = view.getFloat32( offset ); offset += 4; // z
  55. }
  56. const attribute = new BufferAttribute( morphTarget, 3 );
  57. attribute.name = 'morph_' + i;
  58. morphTargets.push( attribute );
  59. }
  60. return {
  61. morphTargets: morphTargets,
  62. clip: clip
  63. };
  64. }
  65. }
  66. export { MDDLoader };