369 lines
11 KiB
Vue
369 lines
11 KiB
Vue
/**
|
|
* 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;
|
|
})();
|