qd-changjing/public/leaflet/libs/three/plugins/loaders/LoaderBuilder.js

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;
})();