mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 01:04:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			369 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			369 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * Builds one or many THREE.Mesh from one raw set of Arraybuffers, materialGroup descriptions and further parameters.
 | 
						|
 * Supports vertex, vertexColor, normal, uv and index buffers.
 | 
						|
 * @class
 | 
						|
 */
 | 
						|
THREE.LoaderSupport.MeshBuilder = (function () {
 | 
						|
 | 
						|
	var LOADER_MESH_BUILDER_VERSION = '1.2.0';
 | 
						|
 | 
						|
	var Validator = THREE.LoaderSupport.Validator;
 | 
						|
 | 
						|
	function MeshBuilder() {
 | 
						|
		console.info( 'Using THREE.LoaderSupport.MeshBuilder version: ' + LOADER_MESH_BUILDER_VERSION );
 | 
						|
		this.logging = {
 | 
						|
			enabled: true,
 | 
						|
			debug: false
 | 
						|
		};
 | 
						|
 | 
						|
		this.callbacks = new THREE.LoaderSupport.Callbacks();
 | 
						|
		this.materials = [];
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Enable or disable logging in general (except warn and error), plus enable or disable debug logging.
 | 
						|
	 * @memberOf THREE.LoaderSupport.MeshBuilder
 | 
						|
	 *
 | 
						|
	 * @param {boolean} enabled True or false.
 | 
						|
	 * @param {boolean} debug True or false.
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.setLogging = function ( enabled, debug ) {
 | 
						|
		this.logging.enabled = enabled === true;
 | 
						|
		this.logging.debug = debug === true;
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Initializes the MeshBuilder (currently only default material initialisation).
 | 
						|
	 * @memberOf THREE.LoaderSupport.MeshBuilder
 | 
						|
	 *
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.init = function () {
 | 
						|
		var defaultMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
 | 
						|
		defaultMaterial.name = 'defaultMaterial';
 | 
						|
 | 
						|
		var defaultVertexColorMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
 | 
						|
		defaultVertexColorMaterial.name = 'defaultVertexColorMaterial';
 | 
						|
		defaultVertexColorMaterial.vertexColors = THREE.VertexColors;
 | 
						|
 | 
						|
		var defaultLineMaterial = new THREE.LineBasicMaterial();
 | 
						|
		defaultLineMaterial.name = 'defaultLineMaterial';
 | 
						|
 | 
						|
		var defaultPointMaterial = new THREE.PointsMaterial( { size: 1 } );
 | 
						|
		defaultPointMaterial.name = 'defaultPointMaterial';
 | 
						|
 | 
						|
		var runtimeMaterials = {};
 | 
						|
		runtimeMaterials[ defaultMaterial.name ] = defaultMaterial;
 | 
						|
		runtimeMaterials[ defaultVertexColorMaterial.name ] = defaultVertexColorMaterial;
 | 
						|
		runtimeMaterials[ defaultLineMaterial.name ] = defaultLineMaterial;
 | 
						|
		runtimeMaterials[ defaultPointMaterial.name ] = defaultPointMaterial;
 | 
						|
 | 
						|
		this.updateMaterials(
 | 
						|
			{
 | 
						|
				cmd: 'materialData',
 | 
						|
				materials: {
 | 
						|
					materialCloneInstructions: null,
 | 
						|
					serializedMaterials: null,
 | 
						|
					runtimeMaterials: runtimeMaterials
 | 
						|
				}
 | 
						|
			}
 | 
						|
		);
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Set materials loaded by any supplier of an Array of {@link THREE.Material}.
 | 
						|
	 * @memberOf THREE.LoaderSupport.MeshBuilder
 | 
						|
	 *
 | 
						|
	 * @param {THREE.Material[]} materials Array of {@link THREE.Material}
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.setMaterials = function ( materials ) {
 | 
						|
		var payload = {
 | 
						|
			cmd: 'materialData',
 | 
						|
			materials: {
 | 
						|
				materialCloneInstructions: null,
 | 
						|
				serializedMaterials: null,
 | 
						|
				runtimeMaterials: Validator.isValid( this.callbacks.onLoadMaterials ) ? this.callbacks.onLoadMaterials( materials ) : materials
 | 
						|
			}
 | 
						|
		};
 | 
						|
		this.updateMaterials( payload );
 | 
						|
	};
 | 
						|
 | 
						|
	MeshBuilder.prototype._setCallbacks = function ( callbacks ) {
 | 
						|
		if ( Validator.isValid( callbacks.onProgress ) ) this.callbacks.setCallbackOnProgress( callbacks.onProgress );
 | 
						|
		if ( Validator.isValid( callbacks.onMeshAlter ) ) this.callbacks.setCallbackOnMeshAlter( callbacks.onMeshAlter );
 | 
						|
		if ( Validator.isValid( callbacks.onLoad ) ) this.callbacks.setCallbackOnLoad( callbacks.onLoad );
 | 
						|
		if ( Validator.isValid( callbacks.onLoadMaterials ) ) this.callbacks.setCallbackOnLoadMaterials( callbacks.onLoadMaterials );
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Delegates processing of the payload (mesh building or material update) to the corresponding functions (BW-compatibility).
 | 
						|
	 * @memberOf THREE.LoaderSupport.MeshBuilder
 | 
						|
	 *
 | 
						|
	 * @param {Object} payload Raw Mesh or Material descriptions.
 | 
						|
	 * @returns {THREE.Mesh[]} mesh Array of {@link THREE.Mesh} or null in case of material update
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.processPayload = function ( payload ) {
 | 
						|
		if ( payload.cmd === 'meshData' ) {
 | 
						|
 | 
						|
			return this.buildMeshes( payload );
 | 
						|
 | 
						|
		} else if ( payload.cmd === 'materialData' ) {
 | 
						|
 | 
						|
			this.updateMaterials( payload );
 | 
						|
			return null;
 | 
						|
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Builds one or multiple meshes from the data described in the payload (buffers, params, material info).
 | 
						|
	 * @memberOf THREE.LoaderSupport.MeshBuilder
 | 
						|
	 *
 | 
						|
	 * @param {Object} meshPayload Raw mesh description (buffers, params, materials) used to build one to many meshes.
 | 
						|
	 * @returns {THREE.Mesh[]} mesh Array of {@link THREE.Mesh}
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.buildMeshes = function ( meshPayload ) {
 | 
						|
		var meshName = meshPayload.params.meshName;
 | 
						|
 | 
						|
		var bufferGeometry = new THREE.BufferGeometry();
 | 
						|
		bufferGeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.vertices ), 3 ) );
 | 
						|
		if ( Validator.isValid( meshPayload.buffers.indices ) ) {
 | 
						|
 | 
						|
			bufferGeometry.setIndex( new THREE.BufferAttribute( new Uint32Array( meshPayload.buffers.indices ), 1 ));
 | 
						|
 | 
						|
		}
 | 
						|
		var haveVertexColors = Validator.isValid( meshPayload.buffers.colors );
 | 
						|
		if ( haveVertexColors ) {
 | 
						|
 | 
						|
			bufferGeometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.colors ), 3 ) );
 | 
						|
 | 
						|
		}
 | 
						|
		if ( Validator.isValid( meshPayload.buffers.normals ) ) {
 | 
						|
 | 
						|
			bufferGeometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.normals ), 3 ) );
 | 
						|
 | 
						|
		} else {
 | 
						|
 | 
						|
			bufferGeometry.computeVertexNormals();
 | 
						|
 | 
						|
		}
 | 
						|
		if ( Validator.isValid( meshPayload.buffers.uvs ) ) {
 | 
						|
 | 
						|
			bufferGeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.uvs ), 2 ) );
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		var material, materialName, key;
 | 
						|
		var materialNames = meshPayload.materials.materialNames;
 | 
						|
		var createMultiMaterial = meshPayload.materials.multiMaterial;
 | 
						|
		var multiMaterials = [];
 | 
						|
		for ( key in materialNames ) {
 | 
						|
 | 
						|
			materialName = materialNames[ key ];
 | 
						|
			material = this.materials[ materialName ];
 | 
						|
			if ( createMultiMaterial ) multiMaterials.push( material );
 | 
						|
 | 
						|
		}
 | 
						|
		if ( createMultiMaterial ) {
 | 
						|
 | 
						|
			material = multiMaterials;
 | 
						|
			var materialGroups = meshPayload.materials.materialGroups;
 | 
						|
			var materialGroup;
 | 
						|
			for ( key in materialGroups ) {
 | 
						|
 | 
						|
				materialGroup = materialGroups[ key ];
 | 
						|
				bufferGeometry.addGroup( materialGroup.start, materialGroup.count, materialGroup.index );
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		var meshes = [];
 | 
						|
		var mesh;
 | 
						|
		var callbackOnMeshAlter = this.callbacks.onMeshAlter;
 | 
						|
		var callbackOnMeshAlterResult;
 | 
						|
		var useOrgMesh = true;
 | 
						|
		var geometryType = Validator.verifyInput( meshPayload.geometryType, 0 );
 | 
						|
		if ( Validator.isValid( callbackOnMeshAlter ) ) {
 | 
						|
 | 
						|
			callbackOnMeshAlterResult = callbackOnMeshAlter(
 | 
						|
				{
 | 
						|
					detail: {
 | 
						|
						meshName: meshName,
 | 
						|
						bufferGeometry: bufferGeometry,
 | 
						|
						material: material,
 | 
						|
						geometryType: geometryType
 | 
						|
					}
 | 
						|
				}
 | 
						|
			);
 | 
						|
			if ( Validator.isValid( callbackOnMeshAlterResult ) ) {
 | 
						|
 | 
						|
				if ( ! callbackOnMeshAlterResult.isDisregardMesh() && callbackOnMeshAlterResult.providesAlteredMeshes() ) {
 | 
						|
 | 
						|
					for ( var i in callbackOnMeshAlterResult.meshes ) {
 | 
						|
 | 
						|
						meshes.push( callbackOnMeshAlterResult.meshes[ i ] );
 | 
						|
 | 
						|
					}
 | 
						|
 | 
						|
				}
 | 
						|
				useOrgMesh = false;
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
		if ( useOrgMesh ) {
 | 
						|
 | 
						|
			if ( meshPayload.computeBoundingSphere ) bufferGeometry.computeBoundingSphere();
 | 
						|
			if ( geometryType === 0 ) {
 | 
						|
 | 
						|
				mesh = new THREE.Mesh( bufferGeometry, material );
 | 
						|
 | 
						|
			} else if ( geometryType === 1) {
 | 
						|
 | 
						|
				mesh = new THREE.LineSegments( bufferGeometry, material );
 | 
						|
 | 
						|
			} else {
 | 
						|
 | 
						|
				mesh = new THREE.Points( bufferGeometry, material );
 | 
						|
 | 
						|
			}
 | 
						|
			mesh.name = meshName;
 | 
						|
			meshes.push( mesh );
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		var progressMessage;
 | 
						|
		if ( Validator.isValid( meshes ) && meshes.length > 0 ) {
 | 
						|
 | 
						|
			var meshNames = [];
 | 
						|
			for ( var i in meshes ) {
 | 
						|
 | 
						|
				mesh = meshes[ i ];
 | 
						|
				meshNames[ i ] = mesh.name;
 | 
						|
 | 
						|
			}
 | 
						|
			progressMessage = 'Adding mesh(es) (' + meshNames.length + ': ' + meshNames + ') from input mesh: ' + meshName;
 | 
						|
			progressMessage += ' (' + ( meshPayload.progress.numericalValue * 100 ).toFixed( 2 ) + '%)';
 | 
						|
 | 
						|
		} else {
 | 
						|
 | 
						|
			progressMessage = 'Not adding mesh: ' + meshName;
 | 
						|
			progressMessage += ' (' + ( meshPayload.progress.numericalValue * 100 ).toFixed( 2 ) + '%)';
 | 
						|
 | 
						|
		}
 | 
						|
		var callbackOnProgress = this.callbacks.onProgress;
 | 
						|
		if ( Validator.isValid( callbackOnProgress ) ) {
 | 
						|
 | 
						|
			var event = new CustomEvent( 'MeshBuilderEvent', {
 | 
						|
				detail: {
 | 
						|
					type: 'progress',
 | 
						|
					modelName: meshPayload.params.meshName,
 | 
						|
					text: progressMessage,
 | 
						|
					numericalValue: meshPayload.progress.numericalValue
 | 
						|
				}
 | 
						|
			} );
 | 
						|
			callbackOnProgress( event );
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		return meshes;
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Updates the materials with contained material objects (sync) or from alteration instructions (async).
 | 
						|
	 * @memberOf THREE.LoaderSupport.MeshBuilder
 | 
						|
	 *
 | 
						|
	 * @param {Object} materialPayload Material update instructions
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.updateMaterials = function ( materialPayload ) {
 | 
						|
		var material, materialName;
 | 
						|
		var materialCloneInstructions = materialPayload.materials.materialCloneInstructions;
 | 
						|
		if ( Validator.isValid( materialCloneInstructions ) ) {
 | 
						|
 | 
						|
			var materialNameOrg = materialCloneInstructions.materialNameOrg;
 | 
						|
			var materialOrg = this.materials[ materialNameOrg ];
 | 
						|
 | 
						|
			if ( Validator.isValid( materialNameOrg ) ) {
 | 
						|
 | 
						|
				material = materialOrg.clone();
 | 
						|
 | 
						|
				materialName = materialCloneInstructions.materialName;
 | 
						|
				material.name = materialName;
 | 
						|
 | 
						|
				var materialProperties = materialCloneInstructions.materialProperties;
 | 
						|
				for ( var key in materialProperties ) {
 | 
						|
 | 
						|
					if ( material.hasOwnProperty( key ) && materialProperties.hasOwnProperty( key ) ) material[ key ] = materialProperties[ key ];
 | 
						|
 | 
						|
				}
 | 
						|
				this.materials[ materialName ] = material;
 | 
						|
 | 
						|
			} else {
 | 
						|
 | 
						|
				console.warn( 'Requested material "' + materialNameOrg + '" is not available!' );
 | 
						|
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		var materials = materialPayload.materials.serializedMaterials;
 | 
						|
		if ( Validator.isValid( materials ) && Object.keys( materials ).length > 0 ) {
 | 
						|
 | 
						|
			var loader = new THREE.MaterialLoader();
 | 
						|
			var materialJson;
 | 
						|
			for ( materialName in materials ) {
 | 
						|
 | 
						|
				materialJson = materials[ materialName ];
 | 
						|
				if ( Validator.isValid( materialJson ) ) {
 | 
						|
 | 
						|
					material = loader.parse( materialJson );
 | 
						|
					if ( this.logging.enabled ) console.info( 'De-serialized material with name "' + materialName + '" will be added.' );
 | 
						|
					this.materials[ materialName ] = material;
 | 
						|
				}
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		materials = materialPayload.materials.runtimeMaterials;
 | 
						|
		if ( Validator.isValid( materials ) && Object.keys( materials ).length > 0 ) {
 | 
						|
 | 
						|
			for ( materialName in materials ) {
 | 
						|
 | 
						|
				material = materials[ materialName ];
 | 
						|
				if ( this.logging.enabled ) console.info( 'Material with name "' + materialName + '" will be added.' );
 | 
						|
				this.materials[ materialName ] = material;
 | 
						|
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns the mapping object of material name and corresponding jsonified material.
 | 
						|
	 *
 | 
						|
	 * @returns {Object} Map of Materials in JSON representation
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.getMaterialsJSON = function () {
 | 
						|
		var materialsJSON = {};
 | 
						|
		var material;
 | 
						|
		for ( var materialName in this.materials ) {
 | 
						|
 | 
						|
			material = this.materials[ materialName ];
 | 
						|
			materialsJSON[ materialName ] = material.toJSON();
 | 
						|
		}
 | 
						|
 | 
						|
		return materialsJSON;
 | 
						|
	};
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns the mapping object of material name and corresponding material.
 | 
						|
	 *
 | 
						|
	 * @returns {Object} Map of {@link THREE.Material}
 | 
						|
	 */
 | 
						|
	MeshBuilder.prototype.getMaterials = function () {
 | 
						|
		return this.materials;
 | 
						|
	};
 | 
						|
 | 
						|
	return MeshBuilder;
 | 
						|
})();
 |