MD2Character.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. */
  4. THREE.MD2Character = function () {
  5. var scope = this;
  6. this.scale = 1;
  7. this.animationFPS = 6;
  8. this.root = new THREE.Object3D();
  9. this.meshBody = null;
  10. this.meshWeapon = null;
  11. this.skinsBody = [];
  12. this.skinsWeapon = [];
  13. this.weapons = [];
  14. this.activeAnimation = null;
  15. this.onLoadComplete = function () {};
  16. this.loadCounter = 0;
  17. this.loadParts = function ( config ) {
  18. this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
  19. var weaponsTextures = []
  20. for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
  21. // SKINS
  22. this.skinsBody = loadTextures( config.baseUrl + "skins/", config.skins );
  23. this.skinsWeapon = loadTextures( config.baseUrl + "skins/", weaponsTextures );
  24. // BODY
  25. var loader = new THREE.JSONLoader();
  26. loader.load( config.baseUrl + config.body, function( geo ) {
  27. geo.computeBoundingBox();
  28. scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
  29. var mesh = createPart( geo, scope.skinsBody[ 0 ] );
  30. mesh.scale.set( scope.scale, scope.scale, scope.scale );
  31. scope.root.add( mesh );
  32. scope.meshBody = mesh;
  33. scope.activeAnimation = geo.firstAnimation;
  34. checkLoadingComplete();
  35. } );
  36. // WEAPONS
  37. var generateCallback = function ( index, name ) {
  38. return function( geo ) {
  39. var mesh = createPart( geo, scope.skinsWeapon[ index ] );
  40. mesh.scale.set( scope.scale, scope.scale, scope.scale );
  41. mesh.visible = false;
  42. mesh.name = name;
  43. scope.root.add( mesh );
  44. scope.weapons[ index ] = mesh;
  45. scope.meshWeapon = mesh;
  46. checkLoadingComplete();
  47. }
  48. }
  49. for ( var i = 0; i < config.weapons.length; i ++ ) {
  50. loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
  51. }
  52. };
  53. this.setPlaybackRate = function ( rate ) {
  54. if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
  55. if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
  56. };
  57. this.setWireframe = function ( wireframeEnabled ) {
  58. if ( wireframeEnabled ) {
  59. if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
  60. if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
  61. } else {
  62. if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
  63. if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
  64. }
  65. };
  66. this.setSkin = function( index ) {
  67. if ( this.meshBody && this.meshBody.material.wireframe === false ) {
  68. this.meshBody.material.map = this.skinsBody[ index ];
  69. }
  70. };
  71. this.setWeapon = function ( index ) {
  72. for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
  73. var activeWeapon = this.weapons[ index ];
  74. if ( activeWeapon ) {
  75. activeWeapon.visible = true;
  76. this.meshWeapon = activeWeapon;
  77. activeWeapon.playAnimation( this.activeAnimation, this.animationFPS );
  78. this.meshWeapon.baseDuration = this.meshWeapon.duration;
  79. this.meshWeapon.time = this.meshBody.time;
  80. this.meshWeapon.duration = this.meshBody.duration;
  81. }
  82. };
  83. this.setAnimation = function ( animationName ) {
  84. if ( this.meshBody ) {
  85. this.meshBody.playAnimation( animationName, this.animationFPS );
  86. this.meshBody.baseDuration = this.meshBody.duration;
  87. }
  88. if ( this.meshWeapon ) {
  89. this.meshWeapon.playAnimation( animationName, this.animationFPS );
  90. this.meshWeapon.baseDuration = this.meshWeapon.duration;
  91. this.meshWeapon.time = this.meshBody.time;
  92. }
  93. this.activeAnimation = animationName;
  94. };
  95. this.update = function ( delta ) {
  96. if ( this.meshBody ) {
  97. this.meshBody.updateAnimation( 1000 * delta );
  98. }
  99. if ( this.meshWeapon ) {
  100. this.meshWeapon.updateAnimation( 1000 * delta );
  101. }
  102. };
  103. function loadTextures( baseUrl, textureUrls ) {
  104. var mapping = new THREE.UVMapping();
  105. var textures = [];
  106. for ( var i = 0; i < textureUrls.length; i ++ ) {
  107. textures[ i ] = THREE.ImageUtils.loadTexture( baseUrl + textureUrls[ i ], mapping, checkLoadingComplete );
  108. textures[ i ].name = textureUrls[ i ];
  109. }
  110. return textures;
  111. };
  112. function createPart( geometry, skinMap ) {
  113. geometry.computeMorphNormals();
  114. var whiteMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color( 0xffffff ) );
  115. var materialWireframe = new THREE.MeshPhongMaterial( { color: 0xffaa00, specular: 0x111111, shininess: 50, wireframe: true, shading: THREE.SmoothShading, map: whiteMap, morphTargets: true, morphNormals: true, metal: false } );
  116. var materialTexture = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 50, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true, metal: false } );
  117. materialTexture.wrapAround = true;
  118. //
  119. var mesh = new THREE.MorphAnimMesh( geometry, materialTexture );
  120. mesh.rotation.y = -Math.PI/2;
  121. mesh.castShadow = true;
  122. mesh.receiveShadow = true;
  123. //
  124. mesh.materialTexture = materialTexture;
  125. mesh.materialWireframe = materialWireframe;
  126. //
  127. mesh.parseAnimations();
  128. mesh.playAnimation( geometry.firstAnimation, scope.animationFPS );
  129. mesh.baseDuration = mesh.duration;
  130. return mesh;
  131. };
  132. function checkLoadingComplete() {
  133. scope.loadCounter -= 1;
  134. if ( scope.loadCounter === 0 ) scope.onLoadComplete();
  135. };
  136. };