提交 2a39c1b9 编写于 作者: M Mugen87

3MFLoader: Add support for multiple textures.

上级 bc67d5f0
......@@ -46,7 +46,6 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
var scope = this;
var textureLoader = new THREE.TextureLoader( this.manager );
var textureMap = {};
function loadDocument( data ) {
......@@ -358,10 +357,16 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
var p3 = triangleNode.getAttribute( 'p3' );
var pid = triangleNode.getAttribute( 'pid' );
triangles.push( parseInt( v1, 10 ), parseInt( v2, 10 ), parseInt( v3, 10 ) );
var triangleProperty = {};
triangleProperty[ 'v1' ] = parseInt( v1, 10 );
triangleProperty[ 'v2' ] = parseInt( v2, 10 );
triangleProperty[ 'v3' ] = parseInt( v3, 10 );
triangles.push( triangleProperty[ 'v1' ], triangleProperty[ 'v2' ], triangleProperty[ 'v3' ] );
// optional
if ( p1 ) {
triangleProperty[ 'p1' ] = parseInt( p1, 10 );
......@@ -535,11 +540,15 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
function parseResourcesNode( resourcesNode ) {
var resourcesData = {};
var basematerialsNode = resourcesNode.querySelector( 'basematerials' );
if ( basematerialsNode ) {
resourcesData[ 'basematerials' ] = {};
var basematerialsNodes = resourcesNode.querySelectorAll( 'basematerials' );
for ( var i = 0; i < basematerialsNodes.length; i ++ ) {
resourcesData[ 'basematerials' ] = parseBasematerialsNode( basematerialsNode );
var basematerialsNode = basematerialsNodes[ i ];
var basematerialsData = parseBasematerialsNode( basematerialsNode );
resourcesData[ 'basematerials' ][ basematerialsData[ 'id' ] ] = basematerialsData;
}
......@@ -644,371 +653,350 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
}
function buildGroups( geometry, modelData, meshData ) {
function buildTexture( texture2dgroup, objects, modelData, textureData ) {
var basematerialsData = modelData[ 'resources' ][ 'basematerials' ];
var triangleProperties = meshData[ 'triangleProperties' ];
var texid = texture2dgroup.texid;
var texture2ds = modelData.resources.texture2d;
var texture2d = texture2ds[ texid ];
var start = 0;
var count = 0;
var currentMaterialIndex = - 1;
if ( texture2d ) {
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
var data = textureData[ texture2d.path ];
var type = texture2d.contenttype;
var triangleProperty = triangleProperties[ i ];
var pid = triangleProperty.pid;
var blob = new Blob( [ data ], { type: type } );
var sourceURI = URL.createObjectURL( blob );
// only proceed if the triangle refers to a basematerials definition
var texture = textureLoader.load( sourceURI, function () {
if ( basematerialsData && ( basematerialsData.id === pid ) ) {
URL.revokeObjectURL( sourceURI );
if ( currentMaterialIndex === - 1 ) currentMaterialIndex = triangleProperty.p1;
} );
if ( currentMaterialIndex === triangleProperty.p1 ) {
texture.encoding = THREE.sRGBEncoding;
count += 3; // primitives per triangle
// texture parameters
} else {
switch ( texture2d.tilestyleu ) {
geometry.addGroup( start, count, currentMaterialIndex );
case 'wrap':
texture.wrapS = THREE.RepeatWrapping;
break;
start += count;
count = 3;
currentMaterialIndex = triangleProperty.p1;
case 'mirror':
texture.wrapS = THREE.MirroredRepeatWrapping;
break;
}
case 'none':
case 'clamp':
texture.wrapS = THREE.ClampToEdgeWrapping;
break;
}
default:
texture.wrapS = THREE.RepeatWrapping;
}
if ( geometry.groups.length > 0 ) mergeGroups( geometry );
}
function buildGeometry( modelData, meshData, objectData ) {
var geometry = new THREE.BufferGeometry();
geometry.setIndex( new THREE.BufferAttribute( meshData[ 'triangles' ], 1 ) );
geometry.setAttribute( 'position', new THREE.BufferAttribute( meshData[ 'vertices' ], 3 ) );
//
}
var texture2dgroups = modelData.resources.texture2dgroup;
switch ( texture2d.tilestylev ) {
if ( texture2dgroups ) {
case 'wrap':
texture.wrapT = THREE.RepeatWrapping;
break;
var textureCoordinates = [];
case 'mirror':
texture.wrapT = THREE.MirroredRepeatWrapping;
break;
var triangleProperties = meshData[ 'triangleProperties' ];
var texture2dgroupObjectLevel;
case 'none':
case 'clamp':
texture.wrapT = THREE.ClampToEdgeWrapping;
break;
// check reference to texture coordinates on object level
default:
texture.wrapT = THREE.RepeatWrapping;
var texid;
var pid = objectData.pid;
}
if ( pid && texture2dgroups[ pid ] ) texture2dgroupObjectLevel = texture2dgroups[ pid ];
switch ( texture2d.filter ) {
// process all triangles
case 'auto':
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearMipmapLinearFilter;
break;
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
case 'linear':
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;
break;
var texture2dgroup = texture2dgroupObjectLevel;
var triangleProperty = triangleProperties[ i ];
pid = triangleProperty.pid;
case 'nearest':
texture.magFilter = THREE.NearestFilter;
texture.minFilter = THREE.NearestFilter;
break;
// overwrite existing resource reference if necessary
default:
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearMipmapLinearFilter;
if ( pid && texture2dgroups[ pid ] ) texture2dgroup = texture2dgroups[ pid ];
}
if ( texture2dgroup ) {
return texture;
texid = texture2dgroup.texid; // the loader only supports a single texture for a single geometry right now (and not per face)
var uvs = texture2dgroup.uvs;
} else {
textureCoordinates.push( uvs[ ( triangleProperty.p1 * 2 ) + 0 ] );
textureCoordinates.push( uvs[ ( triangleProperty.p1 * 2 ) + 1 ] );
return null;
textureCoordinates.push( uvs[ ( triangleProperty.p2 * 2 ) + 0 ] );
textureCoordinates.push( uvs[ ( triangleProperty.p2 * 2 ) + 1 ] );
}
textureCoordinates.push( uvs[ ( triangleProperty.p3 * 2 ) + 0 ] );
textureCoordinates.push( uvs[ ( triangleProperty.p3 * 2 ) + 1 ] );
}
}
function buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData ) {
}
var objectPindex = objectData.pindex;
if ( textureCoordinates.length > 0 ) {
var materialMap = {};
// uvs are defined on face level so the same vertex can have multiple uv coordinates
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
geometry = geometry.toNonIndexed();
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( textureCoordinates, 2 ) );
geometry.__texid = texid; // save the relationship between texture coordinates and texture
var triangleProperty = triangleProperties[ i ];
var pindex = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectPindex;
return geometry;
if ( materialMap[ pindex ] === undefined ) materialMap[ pindex ] = [];
}
materialMap[ pindex ].push( triangleProperty );
}
return geometry;
}
function buildTexture( geometry, modelData, textureData ) {
var texid = geometry.__texid;
if ( texid !== undefined ) {
delete geometry.__texid;
//
if ( textureMap[ texid ] !== undefined ) {
var keys = Object.keys( materialMap );
var meshes = [];
return textureMap[ texid ];
for ( var i = 0, l = keys.length; i < l; i ++ ) {
} else {
var materialIndex = keys[ i ];
var trianglePropertiesProps = materialMap[ materialIndex ];
var basematerialData = basematerials.basematerials[ materialIndex ];
var material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial );
var texture2ds = modelData.resources.texture2d;
var texture2d = texture2ds[ texid ];
//
if ( texture2d ) {
var geometry = new THREE.BufferGeometry();
var data = textureData[ texture2d.path ];
var type = texture2d.contenttype;
var positionData = [];
var blob = new Blob( [ data ], { type: type } );
var sourceURI = URL.createObjectURL( blob );
var vertices = meshData.vertices;
var texture = textureLoader.load( sourceURI, function () {
for ( var j = 0, jl = trianglePropertiesProps.length; j < jl; j ++ ) {
URL.revokeObjectURL( sourceURI );
var triangleProperty = trianglePropertiesProps[ j ];
} );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 2 ] );
texture.encoding = THREE.sRGBEncoding;
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 2 ] );
// texture parameters
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 2 ] );
switch ( texture2d.tilestyleu ) {
case 'wrap':
texture.wrapS = THREE.RepeatWrapping;
break;
}
case 'mirror':
texture.wrapS = THREE.MirroredRepeatWrapping;
break;
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) );
case 'none':
case 'clamp':
texture.wrapS = THREE.ClampToEdgeWrapping;
break;
//
default:
texture.wrapS = THREE.RepeatWrapping;
var mesh = new THREE.Mesh( geometry, material );
meshes.push( mesh );
}
}
switch ( texture2d.tilestylev ) {
return meshes;
case 'wrap':
texture.wrapT = THREE.RepeatWrapping;
break;
}
case 'mirror':
texture.wrapT = THREE.MirroredRepeatWrapping;
break;
function buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData, objectData ) {
case 'none':
case 'clamp':
texture.wrapT = THREE.ClampToEdgeWrapping;
break;
// geometry
default:
texture.wrapT = THREE.RepeatWrapping;
var geometry = new THREE.BufferGeometry();
}
var positionData = [];
var uvData = [];
switch ( texture2d.filter ) {
var vertices = meshData.vertices;
var uvs = texture2dgroup.uvs;
case 'auto':
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearMipmapLinearFilter;
break;
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
case 'linear':
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;
break;
var triangleProperty = triangleProperties[ i ];
case 'nearest':
texture.magFilter = THREE.NearestFilter;
texture.minFilter = THREE.NearestFilter;
break;
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 2 ] );
default:
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearMipmapLinearFilter;
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 2 ] );
}
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 2 ] );
textureMap[ texid ] = texture;
//
return texture;
uvData.push( uvs[ ( triangleProperty.p1 * 2 ) + 0 ] );
uvData.push( uvs[ ( triangleProperty.p1 * 2 ) + 1 ] );
}
uvData.push( uvs[ ( triangleProperty.p2 * 2 ) + 0 ] );
uvData.push( uvs[ ( triangleProperty.p2 * 2 ) + 1 ] );
}
uvData.push( uvs[ ( triangleProperty.p3 * 2 ) + 0 ] );
uvData.push( uvs[ ( triangleProperty.p3 * 2 ) + 1 ] );
}
return null;
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) );
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvData, 2 ) );
}
// material
function buildMesh( meshData, objects, modelData, textureData, objectData ) {
var texture = getBuild( texture2dgroup, objects, modelData, textureData, objectData, buildTexture );
var geometry = buildGeometry( modelData, meshData, objectData );
var texture = buildTexture( geometry, modelData, textureData );
var material = new THREE.MeshPhongMaterial( { map: texture, flatShading: true } );
// groups
// mesh
buildGroups( geometry, modelData, meshData );
var mesh = new THREE.Mesh( geometry, material );
// material
return mesh;
var material = null;
// add material if an object-level definition is present
}
var basematerialsData = modelData[ 'resources' ][ 'basematerials' ];
function buildDefaultMesh( meshData ) {
if ( basematerialsData && ( basematerialsData.id === objectData.pid ) ) {
var geometry = new THREE.BufferGeometry();
geometry.setIndex( new THREE.BufferAttribute( meshData[ 'triangles' ], 1 ) );
geometry.setAttribute( 'position', new THREE.BufferAttribute( meshData[ 'vertices' ], 3 ) );
var materialIndex = objectData.pindex;
var basematerialData = basematerialsData.basematerials[ materialIndex ];
var material = new THREE.MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } );
material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial );
var mesh = new THREE.Mesh( geometry, material );
}
return mesh;
// add/overwrite material if definitions on triangles are present
}
if ( geometry.groups.length > 0 ) {
function buildMeshes( resourceMap, modelData, meshData, textureData, objectData ) {
var groups = geometry.groups;
material = [];
var keys = Object.keys( resourceMap );
var meshes = [];
for ( var i = 0, l = groups.length; i < l; i ++ ) {
for ( var i = 0; i < keys.length; i ++ ) {
var group = groups[ i ];
var basematerialData = basematerialsData.basematerials[ group.materialIndex ];
material.push( getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial ) );
var resourceId = keys[ i ];
var triangleProperties = resourceMap[ resourceId ];
var resourceType = getResourceType( resourceId, modelData );
}
switch ( resourceType ) {
}
case 'material':
var basematerials = modelData.resources.basematerials[ resourceId ];
var newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData );
// default material
for ( var i = 0, l = newMeshes.length; i < l; i ++ ) {
if ( material === null ) {
meshes.push( newMeshes[ i ] );
if ( texture === null ) {
}
break;
material = new THREE.MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } );
case 'texture':
var texture2dgroup = modelData.resources.texture2dgroup[ resourceId ];
meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData ) );
break;
} else {
case 'default':
meshes.push( buildDefaultMesh( meshData ) );
break;
material = new THREE.MeshPhongMaterial( { map: texture, flatShading: true } );
default:
console.error( 'THREE.3MFLoader: Unsupported resource type.' );
}
}
return new THREE.Mesh( geometry, material );
return meshes;
}
function mergeGroups( geometry ) {
// sort by material index
var groups = geometry.groups.sort( function ( a, b ) {
function getResourceType( pid, modelData ) {
if ( a.materialIndex !== b.materialIndex ) return a.materialIndex - b.materialIndex;
return a.start - b.start;
} );
if ( modelData.resources.texture2dgroup[ pid ] !== undefined ) {
// reorganize index buffer
return 'texture';
var index = geometry.index;
} else if ( modelData.resources.basematerials[ pid ] !== undefined ) {
var itemSize = index.itemSize;
var srcArray = index.array;
return 'material';
var targetOffset = 0;
} else if ( pid === 'default' ) {
var targetArray = new srcArray.constructor( srcArray.length );
return 'default';
for ( var i = 0; i < groups.length; i ++ ) {
} else {
var group = groups[ i ];
return undefined;
var groupLength = group.count * itemSize;
var groupStart = group.start * itemSize;
}
var sub = srcArray.subarray( groupStart, groupStart + groupLength );
}
targetArray.set( sub, targetOffset );
function analyzeObject( modelData, meshData, objectData ) {
targetOffset += groupLength;
var resourceMap = {};
}
var triangleProperties = meshData[ 'triangleProperties' ];
srcArray.set( targetArray );
var objectPid = objectData.pid;
// update groups
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
var start = 0;
var triangleProperty = triangleProperties[ i ];
var pid = ( triangleProperty.pid !== undefined ) ? triangleProperty.pid : objectPid;
for ( i = 0; i < groups.length; i ++ ) {
if ( pid === undefined ) pid = 'default';
group = groups[ i ];
if ( resourceMap[ pid ] === undefined ) resourceMap[ pid ] = [];
group.start = start;
start += group.count;
resourceMap[ pid ].push( triangleProperty );
}
// merge groups
var lastGroup = groups[ 0 ];
geometry.groups = [ lastGroup ];
for ( i = 1; i < groups.length; i ++ ) {
return resourceMap;
group = groups[ i ];
}
if ( lastGroup.materialIndex === group.materialIndex ) {
function buildGroup( meshData, objects, modelData, textureData, objectData ) {
lastGroup.count += group.count;
var group = new THREE.Group();
} else {
var resourceMap = analyzeObject( modelData, meshData, objectData );
var meshes = buildMeshes( resourceMap, modelData, meshData, textureData, objectData );
lastGroup = group;
geometry.groups.push( lastGroup );
for ( var i = 0, l = meshes.length; i < l; i ++ ) {
}
group.add( meshes[ i ] );
}
return group;
}
function applyExtensions( extensions, meshData, modelXml ) {
......@@ -1134,7 +1122,7 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
applyExtensions( extensions, meshData, modelXml );
objects[ objectData.id ] = getBuild( meshData, objects, modelData, textureData, objectData, buildMesh );
objects[ objectData.id ] = getBuild( meshData, objects, modelData, textureData, objectData, buildGroup );
} else {
......
......@@ -67,7 +67,6 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
var scope = this;
var textureLoader = new TextureLoader( this.manager );
var textureMap = {};
function loadDocument( data ) {
......@@ -379,10 +378,16 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
var p3 = triangleNode.getAttribute( 'p3' );
var pid = triangleNode.getAttribute( 'pid' );
triangles.push( parseInt( v1, 10 ), parseInt( v2, 10 ), parseInt( v3, 10 ) );
var triangleProperty = {};
triangleProperty[ 'v1' ] = parseInt( v1, 10 );
triangleProperty[ 'v2' ] = parseInt( v2, 10 );
triangleProperty[ 'v3' ] = parseInt( v3, 10 );
triangles.push( triangleProperty[ 'v1' ], triangleProperty[ 'v2' ], triangleProperty[ 'v3' ] );
// optional
if ( p1 ) {
triangleProperty[ 'p1' ] = parseInt( p1, 10 );
......@@ -556,11 +561,15 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
function parseResourcesNode( resourcesNode ) {
var resourcesData = {};
var basematerialsNode = resourcesNode.querySelector( 'basematerials' );
if ( basematerialsNode ) {
resourcesData[ 'basematerials' ] = {};
var basematerialsNodes = resourcesNode.querySelectorAll( 'basematerials' );
for ( var i = 0; i < basematerialsNodes.length; i ++ ) {
resourcesData[ 'basematerials' ] = parseBasematerialsNode( basematerialsNode );
var basematerialsNode = basematerialsNodes[ i ];
var basematerialsData = parseBasematerialsNode( basematerialsNode );
resourcesData[ 'basematerials' ][ basematerialsData[ 'id' ] ] = basematerialsData;
}
......@@ -665,371 +674,350 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
}
function buildGroups( geometry, modelData, meshData ) {
function buildTexture( texture2dgroup, objects, modelData, textureData ) {
var basematerialsData = modelData[ 'resources' ][ 'basematerials' ];
var triangleProperties = meshData[ 'triangleProperties' ];
var texid = texture2dgroup.texid;
var texture2ds = modelData.resources.texture2d;
var texture2d = texture2ds[ texid ];
var start = 0;
var count = 0;
var currentMaterialIndex = - 1;
if ( texture2d ) {
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
var data = textureData[ texture2d.path ];
var type = texture2d.contenttype;
var triangleProperty = triangleProperties[ i ];
var pid = triangleProperty.pid;
var blob = new Blob( [ data ], { type: type } );
var sourceURI = URL.createObjectURL( blob );
// only proceed if the triangle refers to a basematerials definition
var texture = textureLoader.load( sourceURI, function () {
if ( basematerialsData && ( basematerialsData.id === pid ) ) {
URL.revokeObjectURL( sourceURI );
if ( currentMaterialIndex === - 1 ) currentMaterialIndex = triangleProperty.p1;
} );
if ( currentMaterialIndex === triangleProperty.p1 ) {
texture.encoding = sRGBEncoding;
count += 3; // primitives per triangle
// texture parameters
} else {
switch ( texture2d.tilestyleu ) {
geometry.addGroup( start, count, currentMaterialIndex );
case 'wrap':
texture.wrapS = RepeatWrapping;
break;
start += count;
count = 3;
currentMaterialIndex = triangleProperty.p1;
case 'mirror':
texture.wrapS = MirroredRepeatWrapping;
break;
}
case 'none':
case 'clamp':
texture.wrapS = ClampToEdgeWrapping;
break;
}
default:
texture.wrapS = RepeatWrapping;
}
if ( geometry.groups.length > 0 ) mergeGroups( geometry );
}
function buildGeometry( modelData, meshData, objectData ) {
var geometry = new BufferGeometry();
geometry.setIndex( new BufferAttribute( meshData[ 'triangles' ], 1 ) );
geometry.setAttribute( 'position', new BufferAttribute( meshData[ 'vertices' ], 3 ) );
//
}
var texture2dgroups = modelData.resources.texture2dgroup;
switch ( texture2d.tilestylev ) {
if ( texture2dgroups ) {
case 'wrap':
texture.wrapT = RepeatWrapping;
break;
var textureCoordinates = [];
case 'mirror':
texture.wrapT = MirroredRepeatWrapping;
break;
var triangleProperties = meshData[ 'triangleProperties' ];
var texture2dgroupObjectLevel;
case 'none':
case 'clamp':
texture.wrapT = ClampToEdgeWrapping;
break;
// check reference to texture coordinates on object level
default:
texture.wrapT = RepeatWrapping;
var texid;
var pid = objectData.pid;
}
if ( pid && texture2dgroups[ pid ] ) texture2dgroupObjectLevel = texture2dgroups[ pid ];
switch ( texture2d.filter ) {
// process all triangles
case 'auto':
texture.magFilter = LinearFilter;
texture.minFilter = LinearMipmapLinearFilter;
break;
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
case 'linear':
texture.magFilter = LinearFilter;
texture.minFilter = LinearFilter;
break;
var texture2dgroup = texture2dgroupObjectLevel;
var triangleProperty = triangleProperties[ i ];
pid = triangleProperty.pid;
case 'nearest':
texture.magFilter = NearestFilter;
texture.minFilter = NearestFilter;
break;
// overwrite existing resource reference if necessary
default:
texture.magFilter = LinearFilter;
texture.minFilter = LinearMipmapLinearFilter;
if ( pid && texture2dgroups[ pid ] ) texture2dgroup = texture2dgroups[ pid ];
}
if ( texture2dgroup ) {
return texture;
texid = texture2dgroup.texid; // the loader only supports a single texture for a single geometry right now (and not per face)
var uvs = texture2dgroup.uvs;
} else {
textureCoordinates.push( uvs[ ( triangleProperty.p1 * 2 ) + 0 ] );
textureCoordinates.push( uvs[ ( triangleProperty.p1 * 2 ) + 1 ] );
return null;
textureCoordinates.push( uvs[ ( triangleProperty.p2 * 2 ) + 0 ] );
textureCoordinates.push( uvs[ ( triangleProperty.p2 * 2 ) + 1 ] );
}
textureCoordinates.push( uvs[ ( triangleProperty.p3 * 2 ) + 0 ] );
textureCoordinates.push( uvs[ ( triangleProperty.p3 * 2 ) + 1 ] );
}
}
function buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData ) {
}
var objectPindex = objectData.pindex;
if ( textureCoordinates.length > 0 ) {
var materialMap = {};
// uvs are defined on face level so the same vertex can have multiple uv coordinates
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
geometry = geometry.toNonIndexed();
geometry.setAttribute( 'uv', new Float32BufferAttribute( textureCoordinates, 2 ) );
geometry.__texid = texid; // save the relationship between texture coordinates and texture
var triangleProperty = triangleProperties[ i ];
var pindex = ( triangleProperty.p1 !== undefined ) ? triangleProperty.p1 : objectPindex;
return geometry;
if ( materialMap[ pindex ] === undefined ) materialMap[ pindex ] = [];
}
materialMap[ pindex ].push( triangleProperty );
}
return geometry;
}
function buildTexture( geometry, modelData, textureData ) {
var texid = geometry.__texid;
if ( texid !== undefined ) {
delete geometry.__texid;
//
if ( textureMap[ texid ] !== undefined ) {
var keys = Object.keys( materialMap );
var meshes = [];
return textureMap[ texid ];
for ( var i = 0, l = keys.length; i < l; i ++ ) {
} else {
var materialIndex = keys[ i ];
var trianglePropertiesProps = materialMap[ materialIndex ];
var basematerialData = basematerials.basematerials[ materialIndex ];
var material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial );
var texture2ds = modelData.resources.texture2d;
var texture2d = texture2ds[ texid ];
//
if ( texture2d ) {
var geometry = new BufferGeometry();
var data = textureData[ texture2d.path ];
var type = texture2d.contenttype;
var positionData = [];
var blob = new Blob( [ data ], { type: type } );
var sourceURI = URL.createObjectURL( blob );
var vertices = meshData.vertices;
var texture = textureLoader.load( sourceURI, function () {
for ( var j = 0, jl = trianglePropertiesProps.length; j < jl; j ++ ) {
URL.revokeObjectURL( sourceURI );
var triangleProperty = trianglePropertiesProps[ j ];
} );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 2 ] );
texture.encoding = sRGBEncoding;
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 2 ] );
// texture parameters
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 2 ] );
switch ( texture2d.tilestyleu ) {
case 'wrap':
texture.wrapS = RepeatWrapping;
break;
}
case 'mirror':
texture.wrapS = MirroredRepeatWrapping;
break;
geometry.setAttribute( 'position', new Float32BufferAttribute( positionData, 3 ) );
case 'none':
case 'clamp':
texture.wrapS = ClampToEdgeWrapping;
break;
//
default:
texture.wrapS = RepeatWrapping;
var mesh = new Mesh( geometry, material );
meshes.push( mesh );
}
}
switch ( texture2d.tilestylev ) {
return meshes;
case 'wrap':
texture.wrapT = RepeatWrapping;
break;
}
case 'mirror':
texture.wrapT = MirroredRepeatWrapping;
break;
function buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData, objectData ) {
case 'none':
case 'clamp':
texture.wrapT = ClampToEdgeWrapping;
break;
// geometry
default:
texture.wrapT = RepeatWrapping;
var geometry = new BufferGeometry();
}
var positionData = [];
var uvData = [];
switch ( texture2d.filter ) {
var vertices = meshData.vertices;
var uvs = texture2dgroup.uvs;
case 'auto':
texture.magFilter = LinearFilter;
texture.minFilter = LinearMipmapLinearFilter;
break;
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
case 'linear':
texture.magFilter = LinearFilter;
texture.minFilter = LinearFilter;
break;
var triangleProperty = triangleProperties[ i ];
case 'nearest':
texture.magFilter = NearestFilter;
texture.minFilter = NearestFilter;
break;
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v1 * 3 ) + 2 ] );
default:
texture.magFilter = LinearFilter;
texture.minFilter = LinearMipmapLinearFilter;
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v2 * 3 ) + 2 ] );
}
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 0 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 1 ] );
positionData.push( vertices[ ( triangleProperty.v3 * 3 ) + 2 ] );
textureMap[ texid ] = texture;
//
return texture;
uvData.push( uvs[ ( triangleProperty.p1 * 2 ) + 0 ] );
uvData.push( uvs[ ( triangleProperty.p1 * 2 ) + 1 ] );
}
uvData.push( uvs[ ( triangleProperty.p2 * 2 ) + 0 ] );
uvData.push( uvs[ ( triangleProperty.p2 * 2 ) + 1 ] );
}
uvData.push( uvs[ ( triangleProperty.p3 * 2 ) + 0 ] );
uvData.push( uvs[ ( triangleProperty.p3 * 2 ) + 1 ] );
}
return null;
geometry.setAttribute( 'position', new Float32BufferAttribute( positionData, 3 ) );
geometry.setAttribute( 'uv', new Float32BufferAttribute( uvData, 2 ) );
}
// material
function buildMesh( meshData, objects, modelData, textureData, objectData ) {
var texture = getBuild( texture2dgroup, objects, modelData, textureData, objectData, buildTexture );
var geometry = buildGeometry( modelData, meshData, objectData );
var texture = buildTexture( geometry, modelData, textureData );
var material = new MeshPhongMaterial( { map: texture, flatShading: true } );
// groups
// mesh
buildGroups( geometry, modelData, meshData );
var mesh = new Mesh( geometry, material );
// material
return mesh;
var material = null;
// add material if an object-level definition is present
}
var basematerialsData = modelData[ 'resources' ][ 'basematerials' ];
function buildDefaultMesh( meshData ) {
if ( basematerialsData && ( basematerialsData.id === objectData.pid ) ) {
var geometry = new BufferGeometry();
geometry.setIndex( new BufferAttribute( meshData[ 'triangles' ], 1 ) );
geometry.setAttribute( 'position', new BufferAttribute( meshData[ 'vertices' ], 3 ) );
var materialIndex = objectData.pindex;
var basematerialData = basematerialsData.basematerials[ materialIndex ];
var material = new MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } );
material = getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial );
var mesh = new Mesh( geometry, material );
}
return mesh;
// add/overwrite material if definitions on triangles are present
}
if ( geometry.groups.length > 0 ) {
function buildMeshes( resourceMap, modelData, meshData, textureData, objectData ) {
var groups = geometry.groups;
material = [];
var keys = Object.keys( resourceMap );
var meshes = [];
for ( var i = 0, l = groups.length; i < l; i ++ ) {
for ( var i = 0; i < keys.length; i ++ ) {
var group = groups[ i ];
var basematerialData = basematerialsData.basematerials[ group.materialIndex ];
material.push( getBuild( basematerialData, objects, modelData, textureData, objectData, buildBasematerial ) );
var resourceId = keys[ i ];
var triangleProperties = resourceMap[ resourceId ];
var resourceType = getResourceType( resourceId, modelData );
}
switch ( resourceType ) {
}
case 'material':
var basematerials = modelData.resources.basematerials[ resourceId ];
var newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData );
// default material
for ( var i = 0, l = newMeshes.length; i < l; i ++ ) {
if ( material === null ) {
meshes.push( newMeshes[ i ] );
if ( texture === null ) {
}
break;
material = new MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } );
case 'texture':
var texture2dgroup = modelData.resources.texture2dgroup[ resourceId ];
meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData ) );
break;
} else {
case 'default':
meshes.push( buildDefaultMesh( meshData ) );
break;
material = new MeshPhongMaterial( { map: texture, flatShading: true } );
default:
console.error( 'THREE.3MFLoader: Unsupported resource type.' );
}
}
return new Mesh( geometry, material );
return meshes;
}
function mergeGroups( geometry ) {
// sort by material index
var groups = geometry.groups.sort( function ( a, b ) {
function getResourceType( pid, modelData ) {
if ( a.materialIndex !== b.materialIndex ) return a.materialIndex - b.materialIndex;
return a.start - b.start;
} );
if ( modelData.resources.texture2dgroup[ pid ] !== undefined ) {
// reorganize index buffer
return 'texture';
var index = geometry.index;
} else if ( modelData.resources.basematerials[ pid ] !== undefined ) {
var itemSize = index.itemSize;
var srcArray = index.array;
return 'material';
var targetOffset = 0;
} else if ( pid === 'default' ) {
var targetArray = new srcArray.constructor( srcArray.length );
return 'default';
for ( var i = 0; i < groups.length; i ++ ) {
} else {
var group = groups[ i ];
return undefined;
var groupLength = group.count * itemSize;
var groupStart = group.start * itemSize;
}
var sub = srcArray.subarray( groupStart, groupStart + groupLength );
}
targetArray.set( sub, targetOffset );
function analyzeObject( modelData, meshData, objectData ) {
targetOffset += groupLength;
var resourceMap = {};
}
var triangleProperties = meshData[ 'triangleProperties' ];
srcArray.set( targetArray );
var objectPid = objectData.pid;
// update groups
for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
var start = 0;
var triangleProperty = triangleProperties[ i ];
var pid = ( triangleProperty.pid !== undefined ) ? triangleProperty.pid : objectPid;
for ( i = 0; i < groups.length; i ++ ) {
if ( pid === undefined ) pid = 'default';
group = groups[ i ];
if ( resourceMap[ pid ] === undefined ) resourceMap[ pid ] = [];
group.start = start;
start += group.count;
resourceMap[ pid ].push( triangleProperty );
}
// merge groups
var lastGroup = groups[ 0 ];
geometry.groups = [ lastGroup ];
for ( i = 1; i < groups.length; i ++ ) {
return resourceMap;
group = groups[ i ];
}
if ( lastGroup.materialIndex === group.materialIndex ) {
function buildGroup( meshData, objects, modelData, textureData, objectData ) {
lastGroup.count += group.count;
var group = new Group();
} else {
var resourceMap = analyzeObject( modelData, meshData, objectData );
var meshes = buildMeshes( resourceMap, modelData, meshData, textureData, objectData );
lastGroup = group;
geometry.groups.push( lastGroup );
for ( var i = 0, l = meshes.length; i < l; i ++ ) {
}
group.add( meshes[ i ] );
}
return group;
}
function applyExtensions( extensions, meshData, modelXml ) {
......@@ -1155,7 +1143,7 @@ ThreeMFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
applyExtensions( extensions, meshData, modelXml );
objects[ objectData.id ] = getBuild( meshData, objects, modelData, textureData, objectData, buildMesh );
objects[ objectData.id ] = getBuild( meshData, objects, modelData, textureData, objectData, buildGroup );
} else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册