未验证 提交 37ae761f 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #13536 from takahirox/GLTFExporterMultiMaterial

GLTFExporter: Multi-material support
......@@ -169,10 +169,12 @@ THREE.GLTFExporter.prototype = {
/**
* Get the min and max vectors from the given attribute
* @param {THREE.BufferAttribute} attribute Attribute to find the min/max
* @param {THREE.BufferAttribute} attribute Attribute to find the min/max in range from start to start + count
* @param {Integer} start
* @param {Integer} count
* @return {Object} Object containing the `min` and `max` values (As an array of attribute.itemSize components)
*/
function getMinMax( attribute ) {
function getMinMax( attribute, start, count ) {
var output = {
......@@ -181,7 +183,7 @@ THREE.GLTFExporter.prototype = {
};
for ( var i = 0; i < attribute.count; i ++ ) {
for ( var i = start; i < start + count; i ++ ) {
for ( var a = 0; a < attribute.itemSize; a ++ ) {
......@@ -393,9 +395,11 @@ THREE.GLTFExporter.prototype = {
* Process attribute to generate an accessor
* @param {THREE.BufferAttribute} attribute Attribute to process
* @param {THREE.BufferGeometry} geometry (Optional) Geometry used for truncated draw range
* @param {Integer} start (Optional)
* @param {Integer} count (Optional)
* @return {Integer} Index of the processed accessor on the "accessors" array
*/
function processAccessor( attribute, geometry ) {
function processAccessor( attribute, geometry, start, count ) {
if ( ! outputJSON.accessors ) {
......@@ -434,27 +438,33 @@ THREE.GLTFExporter.prototype = {
}
var minMax = getMinMax( attribute );
var start = 0;
var count = attribute.count;
if ( start === undefined ) start = 0;
if ( count === undefined ) count = attribute.count;
// @TODO Indexed buffer geometry with drawRange not supported yet
if ( options.truncateDrawRange && geometry !== undefined && geometry.index === null ) {
start = geometry.drawRange.start;
count = geometry.drawRange.count !== Infinity ? geometry.drawRange.count : attribute.count;
var end = start + count;
var end2 = geometry.drawRange.count === Infinity
? attribute.count
: geometry.drawRange.start + geometry.drawRange.count;
start = Math.max( start, geometry.drawRange.start );
count = Math.min( end, end2 ) - start;
if ( count < 0 ) count = 0;
}
var minMax = getMinMax( attribute, start, count );
var bufferViewTarget;
// If geometry isn't provided, don't infer the target usage of the bufferView. For
// animation samplers, target must not be set.
if ( geometry !== undefined ) {
var isVertexAttributes = componentType === WEBGL_CONSTANTS.FLOAT;
bufferViewTarget = isVertexAttributes ? WEBGL_CONSTANTS.ARRAY_BUFFER : WEBGL_CONSTANTS.ELEMENT_ARRAY_BUFFER;
bufferViewTarget = attribute === geometry.index ? WEBGL_CONSTANTS.ELEMENT_ARRAY_BUFFER : WEBGL_CONSTANTS.ARRAY_BUFFER;
}
......@@ -888,43 +898,11 @@ THREE.GLTFExporter.prototype = {
}
var gltfMesh = {
primitives: [
{
mode: mode,
attributes: {},
}
]
};
var material = processMaterial( mesh.material );
if ( material !== null ) {
gltfMesh.primitives[ 0 ].material = material;
}
if ( geometry.index ) {
gltfMesh.primitives[ 0 ].indices = processAccessor( geometry.index, geometry );
} else if ( options.forceIndices ) {
var numFaces = geometry.attributes.position.count;
var indices = new Uint32Array( numFaces );
for ( var i = 0; i < numFaces; i ++ ) {
var gltfMesh = {};
indices[ i ] = i;
}
gltfMesh.primitives[ 0 ].indices = processAccessor( new THREE.Uint32BufferAttribute( indices, 1 ), geometry );
}
// We've just one primitive per mesh
var gltfAttributes = gltfMesh.primitives[ 0 ].attributes;
var attributes = {};
var primitives = [];
var targets = [];
// Conversion between attributes names in threejs and gltf spec
var nameConversion = {
......@@ -946,7 +924,7 @@ THREE.GLTFExporter.prototype = {
if ( attributeName.substr( 0, 5 ) !== 'MORPH' ) {
gltfAttributes[ attributeName ] = processAccessor( attribute, geometry );
attributes[ attributeName ] = processAccessor( attribute, geometry );
}
......@@ -969,8 +947,6 @@ THREE.GLTFExporter.prototype = {
}
gltfMesh.primitives[ 0 ].targets = [];
for ( var i = 0; i < mesh.morphTargetInfluences.length; ++ i ) {
var target = {};
......@@ -1021,7 +997,7 @@ THREE.GLTFExporter.prototype = {
}
gltfMesh.primitives[ 0 ].targets.push( target );
targets.push( target );
weights.push( mesh.morphTargetInfluences[ i ] );
if ( mesh.morphTargetDictionary !== undefined ) targetNames.push( reverseDictionary[ i ] );
......@@ -1039,6 +1015,73 @@ THREE.GLTFExporter.prototype = {
}
var forceIndices = options.forceIndices;
var isMultiMaterial = Array.isArray( mesh.material );
if ( ! forceIndices && geometry.index === null && isMultiMaterial ) {
// temporal workaround.
console.warn( 'THREE.GLTFExporter: Creating index for non-indexed multi-material mesh.' );
forceIndices = true;
}
var didForceIndices = false;
if ( geometry.index === null && forceIndices ) {
var indices = [];
for ( var i = 0, il = geometry.attributes.position.count; i < il; i ++ ) {
indices[ i ] = i;
}
geometry.setIndex( indices );
didForceIndices = true;
}
var materials = isMultiMaterial ? mesh.material : [ mesh.material ] ;
var groups = isMultiMaterial ? mesh.geometry.groups : [ { materialIndex: 0, start: undefined, count: undefined } ];
for ( var i = 0, il = groups.length; i < il; i ++ ) {
var primitive = {
mode: mode,
attributes: attributes,
};
if ( targets.length > 0 ) primitive.targets = targets;
var material = processMaterial( materials[ groups[ i ].materialIndex ] );
if ( material !== null ) {
primitive.material = material;
}
if ( geometry.index !== null ) {
primitive.indices = processAccessor( geometry.index, geometry, groups[ i ].start, groups[ i ].count );
}
primitives.push( primitive );
}
if ( didForceIndices ) {
geometry.setIndex( null );
}
gltfMesh.primitives = primitives;
outputJSON.meshes.push( gltfMesh );
return outputJSON.meshes.length - 1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册