Browse Source

JSM: Added module and TS file for MD2Character.

Mugen87 6 years ago
parent
commit
9ce7030ba1

+ 2 - 0
docs/manual/en/introduction/Import-via-modules.html

@@ -208,6 +208,8 @@
 				</li>
 				<li>misc
 					<ul>
+						<li>Car</li>
+						<li>MD2Character</li>
 						<li>Ocean</li>
 					</ul>
 				</li>

+ 1 - 1
examples/js/MD2Character.js → examples/js/misc/MD2Character.js

@@ -46,7 +46,7 @@ THREE.MD2Character = function () {
 
 			var boundingBox = new THREE.Box3();
 			boundingBox.setFromBufferAttribute( geo.attributes.position );
-			
+
 			scope.root.position.y = - scope.scale * boundingBox.min.y;
 
 			var mesh = createPart( geo, scope.skinsBody[ 0 ] );

+ 24 - 0
examples/jsm/misc/MD2Character.d.ts

@@ -0,0 +1,24 @@
+import {
+  Object3D,
+  Mesh,
+  Texture
+} from '../../../src/Three';
+
+export class MD2Character {
+  constructor();
+  scale: number;
+  animationFPS: number;
+  root: Object3D;
+  meshBody: Mesh | null;
+  meshWeapon: Mesh | null;
+  skinsBody: Texture[];
+  skinsWeapon: Texture[];
+
+  setPlaybackRate(rate: number): void;
+  setWireframe(wireframeEnabled: boolean): void;
+  setSkin(index: number): void;
+  setWeapon(index: number): void;
+  setAnimation(clipName: string): void;
+  syncWeaponAnimation(): void;
+  update(delta: number): void;
+}

+ 274 - 0
examples/jsm/misc/MD2Character.js

@@ -0,0 +1,274 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+import {
+	AnimationMixer,
+	Box3,
+	Mesh,
+	MeshLambertMaterial,
+	Object3D,
+	TextureLoader,
+	UVMapping
+} from "../../../build/three.module.js";
+import { MD2Loader } from "../loaders/MD2Loader.js";
+
+var MD2Character = function () {
+
+	var scope = this;
+
+	this.scale = 1;
+	this.animationFPS = 6;
+
+	this.root = new Object3D();
+
+	this.meshBody = null;
+	this.meshWeapon = null;
+
+	this.skinsBody = [];
+	this.skinsWeapon = [];
+
+	this.weapons = [];
+
+	this.activeAnimation = null;
+
+	this.mixer = null;
+
+	this.onLoadComplete = function () {};
+
+	this.loadCounter = 0;
+
+	this.loadParts = function ( config ) {
+
+		this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
+
+		var weaponsTextures = [];
+		for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
+		// SKINS
+
+		this.skinsBody = loadTextures( config.baseUrl + "skins/", config.skins );
+		this.skinsWeapon = loadTextures( config.baseUrl + "skins/", weaponsTextures );
+
+		// BODY
+
+		var loader = new MD2Loader();
+
+		loader.load( config.baseUrl + config.body, function ( geo ) {
+
+			var boundingBox = new Box3();
+			boundingBox.setFromBufferAttribute( geo.attributes.position );
+
+			scope.root.position.y = - scope.scale * boundingBox.min.y;
+
+			var mesh = createPart( geo, scope.skinsBody[ 0 ] );
+			mesh.scale.set( scope.scale, scope.scale, scope.scale );
+
+			scope.root.add( mesh );
+
+			scope.meshBody = mesh;
+
+			scope.meshBody.clipOffset = 0;
+			scope.activeAnimationClipName = mesh.geometry.animations[ 0 ].name;
+
+			scope.mixer = new AnimationMixer( mesh );
+
+			checkLoadingComplete();
+
+		} );
+
+		// WEAPONS
+
+		var generateCallback = function ( index, name ) {
+
+			return function ( geo ) {
+
+				var mesh = createPart( geo, scope.skinsWeapon[ index ] );
+				mesh.scale.set( scope.scale, scope.scale, scope.scale );
+				mesh.visible = false;
+
+				mesh.name = name;
+
+				scope.root.add( mesh );
+
+				scope.weapons[ index ] = mesh;
+				scope.meshWeapon = mesh;
+
+				checkLoadingComplete();
+
+			};
+
+		};
+
+		for ( var i = 0; i < config.weapons.length; i ++ ) {
+
+			loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
+
+		}
+
+	};
+
+	this.setPlaybackRate = function ( rate ) {
+
+		if ( rate !== 0 ) {
+
+			this.mixer.timeScale = 1 / rate;
+
+		} else {
+
+			this.mixer.timeScale = 0;
+
+		}
+
+	};
+
+	this.setWireframe = function ( wireframeEnabled ) {
+
+		if ( wireframeEnabled ) {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
+
+		} else {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
+
+		}
+
+	};
+
+	this.setSkin = function ( index ) {
+
+		if ( this.meshBody && this.meshBody.material.wireframe === false ) {
+
+			this.meshBody.material.map = this.skinsBody[ index ];
+
+		}
+
+	};
+
+	this.setWeapon = function ( index ) {
+
+		for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
+
+		var activeWeapon = this.weapons[ index ];
+
+		if ( activeWeapon ) {
+
+			activeWeapon.visible = true;
+			this.meshWeapon = activeWeapon;
+
+			scope.syncWeaponAnimation();
+
+		}
+
+	};
+
+	this.setAnimation = function ( clipName ) {
+
+		if ( this.meshBody ) {
+
+			if ( this.meshBody.activeAction ) {
+
+				this.meshBody.activeAction.stop();
+				this.meshBody.activeAction = null;
+
+			}
+
+			var action = this.mixer.clipAction( clipName, this.meshBody );
+
+			if ( action ) {
+
+				this.meshBody.activeAction = action.play();
+
+			}
+
+		}
+
+		scope.activeClipName = clipName;
+
+		scope.syncWeaponAnimation();
+
+	};
+
+	this.syncWeaponAnimation = function () {
+
+		var clipName = scope.activeClipName;
+
+		if ( scope.meshWeapon ) {
+
+			if ( this.meshWeapon.activeAction ) {
+
+				this.meshWeapon.activeAction.stop();
+				this.meshWeapon.activeAction = null;
+
+			}
+
+			var action = this.mixer.clipAction( clipName, this.meshWeapon );
+
+			if ( action ) {
+
+				this.meshWeapon.activeAction = action.syncWith( this.meshBody.activeAction ).play();
+
+			}
+
+		}
+
+	};
+
+	this.update = function ( delta ) {
+
+		if ( this.mixer ) this.mixer.update( delta );
+
+	};
+
+	function loadTextures( baseUrl, textureUrls ) {
+
+		var textureLoader = new TextureLoader();
+		var textures = [];
+
+		for ( var i = 0; i < textureUrls.length; i ++ ) {
+
+			textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
+			textures[ i ].mapping = UVMapping;
+			textures[ i ].name = textureUrls[ i ];
+
+		}
+
+		return textures;
+
+	}
+
+	function createPart( geometry, skinMap ) {
+
+		var materialWireframe = new MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
+		var materialTexture = new MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
+
+		//
+
+		var mesh = new Mesh( geometry, materialTexture );
+		mesh.rotation.y = - Math.PI / 2;
+
+		mesh.castShadow = true;
+		mesh.receiveShadow = true;
+
+		//
+
+		mesh.materialTexture = materialTexture;
+		mesh.materialWireframe = materialWireframe;
+
+		return mesh;
+
+	}
+
+	function checkLoadingComplete() {
+
+		scope.loadCounter -= 1;
+
+		if ( scope.loadCounter === 0 ) scope.onLoadComplete();
+
+	}
+
+};
+
+export { MD2Character };

+ 1 - 1
examples/webgl_loader_md2.html

@@ -18,7 +18,7 @@
 		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src="js/loaders/MD2Loader.js"></script>
-		<script src="js/MD2Character.js"></script>
+		<script src="js/misc/MD2Character.js"></script>
 
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>

+ 1 - 0
utils/modularize.js

@@ -108,6 +108,7 @@ var files = [
 
 	{ path: 'misc/CarControls.js', dependencies: [], ignoreList: [] },
 	{ path: 'misc/ConvexObjectBreaker.js', dependencies: [ { name: 'ConvexBufferGeometry', path: 'geometries/ConvexGeometry.js' } ], ignoreList: [ 'Matrix4' ] },
+	{ path: 'misc/MD2Character.js', dependencies: [ { name: 'MD2Loader', path: 'loaders/MD2Loader.js' } ], ignoreList: [] },
 	{ path: 'misc/Ocean.js', dependencies: [ { name: 'OceanShaders', path: 'shaders/OceanShaders.js' } ], ignoreList: [] },
 
 	{ path: 'modifiers/ExplodeModifier.js', dependencies: [], ignoreList: [] },