| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 | ( function () {	class MD2Character {		constructor() {			this.scale = 1;			this.animationFPS = 6;			this.root = new THREE.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;		}		loadParts( config ) {			const scope = this;			function createPart( geometry, skinMap ) {				const materialWireframe = new THREE.MeshLambertMaterial( {					color: 0xffaa00,					wireframe: true				} );				const materialTexture = new THREE.MeshLambertMaterial( {					color: 0xffffff,					wireframe: false,					map: skinMap				} ); //				const mesh = new THREE.Mesh( geometry, materialTexture );				mesh.rotation.y = - Math.PI / 2;				mesh.castShadow = true;				mesh.receiveShadow = true; //				mesh.materialTexture = materialTexture;				mesh.materialWireframe = materialWireframe;				return mesh;			}			function loadTextures( baseUrl, textureUrls ) {				const textureLoader = new THREE.TextureLoader();				const textures = [];				for ( let i = 0; i < textureUrls.length; i ++ ) {					textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );					textures[ i ].mapping = THREE.UVMapping;					textures[ i ].name = textureUrls[ i ];					textures[ i ].encoding = THREE.sRGBEncoding;				}				return textures;			}			function checkLoadingComplete() {				scope.loadCounter -= 1;				if ( scope.loadCounter === 0 ) scope.onLoadComplete();			}			this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;			const weaponsTextures = [];			for ( let 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			const loader = new THREE.MD2Loader();			loader.load( config.baseUrl + config.body, function ( geo ) {				const boundingBox = new THREE.Box3();				boundingBox.setFromBufferAttribute( geo.attributes.position );				scope.root.position.y = - scope.scale * boundingBox.min.y;				const 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 THREE.AnimationMixer( mesh );				checkLoadingComplete();			} ); // WEAPONS			const generateCallback = function ( index, name ) {				return function ( geo ) {					const 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 ( let i = 0; i < config.weapons.length; i ++ ) {				loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );			}		}		setPlaybackRate( rate ) {			if ( rate !== 0 ) {				this.mixer.timeScale = 1 / rate;			} else {				this.mixer.timeScale = 0;			}		}		setWireframe( 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;			}		}		setSkin( index ) {			if ( this.meshBody && this.meshBody.material.wireframe === false ) {				this.meshBody.material.map = this.skinsBody[ index ];			}		}		setWeapon( index ) {			for ( let i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;			const activeWeapon = this.weapons[ index ];			if ( activeWeapon ) {				activeWeapon.visible = true;				this.meshWeapon = activeWeapon;				this.syncWeaponAnimation();			}		}		setAnimation( clipName ) {			if ( this.meshBody ) {				if ( this.meshBody.activeAction ) {					this.meshBody.activeAction.stop();					this.meshBody.activeAction = null;				}				const action = this.mixer.clipAction( clipName, this.meshBody );				if ( action ) {					this.meshBody.activeAction = action.play();				}			}			this.activeClipName = clipName;			this.syncWeaponAnimation();		}		syncWeaponAnimation() {			const clipName = this.activeClipName;			if ( this.meshWeapon ) {				if ( this.meshWeapon.activeAction ) {					this.meshWeapon.activeAction.stop();					this.meshWeapon.activeAction = null;				}				const action = this.mixer.clipAction( clipName, this.meshWeapon );				if ( action ) {					this.meshWeapon.activeAction = action.syncWith( this.meshBody.activeAction ).play();				}			}		}		update( delta ) {			if ( this.mixer ) this.mixer.update( delta );		}	}	THREE.MD2Character = MD2Character;} )();
 |