Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLTFExporter: Prevent exporting empty geometry #13681

Merged
merged 9 commits into from
Mar 27, 2018
71 changes: 49 additions & 22 deletions examples/js/exporters/GLTFExporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ THREE.GLTFExporter.prototype = {
var value = text.charCodeAt( i );

// Replacing multi-byte character with space(0x20).
array[ i ] = value > 0xFF ? 0x20 : value
array[ i ] = value > 0xFF ? 0x20 : value;

}

Expand Down Expand Up @@ -425,12 +425,6 @@ THREE.GLTFExporter.prototype = {
*/
function processAccessor( attribute, geometry, start, count ) {

if ( ! outputJSON.accessors ) {

outputJSON.accessors = [];

}

var types = {

1: 'SCALAR',
Expand Down Expand Up @@ -484,6 +478,13 @@ THREE.GLTFExporter.prototype = {

}

// Skip creating an accessor if the attribute doesn't have data to export
if ( count === 0 ) {

return null;

}

var minMax = getMinMax( attribute, start, count );

var bufferViewTarget;
Expand All @@ -510,6 +511,12 @@ THREE.GLTFExporter.prototype = {

};

if ( ! outputJSON.accessors ) {

outputJSON.accessors = [];

}

outputJSON.accessors.push( gltfAccessor );

return outputJSON.accessors.length - 1;
Expand Down Expand Up @@ -872,12 +879,6 @@ THREE.GLTFExporter.prototype = {
*/
function processMesh( mesh ) {

if ( ! outputJSON.meshes ) {

outputJSON.meshes = [];

}

var geometry = mesh.geometry;

var mode;
Expand Down Expand Up @@ -963,12 +964,24 @@ THREE.GLTFExporter.prototype = {

if ( attributeName.substr( 0, 5 ) !== 'MORPH' ) {

attributes[ attributeName ] = processAccessor( attribute, geometry );
var accessor = processAccessor( attribute, geometry );
if ( accessor !== null ) {

attributes[ attributeName ] = accessor;

}

}

}

// Skip if no exportable attributes found
if ( Object.keys( attributes ).length === 0 ) {

return null;

}

// Morph targets
if ( mesh.morphTargetInfluences !== undefined && mesh.morphTargetInfluences.length > 0 ) {

Expand Down Expand Up @@ -1057,6 +1070,8 @@ THREE.GLTFExporter.prototype = {
var forceIndices = options.forceIndices;
var isMultiMaterial = Array.isArray( mesh.material );

if ( isMultiMaterial && mesh.geometry.groups.length === 0 ) return null;

if ( ! forceIndices && geometry.index === null && isMultiMaterial ) {

// temporal workaround.
Expand All @@ -1083,7 +1098,7 @@ THREE.GLTFExporter.prototype = {

}

var materials = isMultiMaterial ? mesh.material : [ mesh.material ] ;
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 ++ ) {
Expand All @@ -1095,17 +1110,17 @@ THREE.GLTFExporter.prototype = {

if ( targets.length > 0 ) primitive.targets = targets;

var material = processMaterial( materials[ groups[ i ].materialIndex ] );

if ( material !== null ) {
if ( geometry.index !== null ) {

primitive.material = material;
primitive.indices = processAccessor( geometry.index, geometry, groups[ i ].start, groups[ i ].count );

}

if ( geometry.index !== null ) {
var material = processMaterial( materials[ groups[ i ].materialIndex ] );

primitive.indices = processAccessor( geometry.index, geometry, groups[ i ].start, groups[ i ].count );
if ( material !== null ) {

primitive.material = material;

}

Expand All @@ -1121,6 +1136,12 @@ THREE.GLTFExporter.prototype = {

gltfMesh.primitives = primitives;

if ( ! outputJSON.meshes ) {

outputJSON.meshes = [];

}

outputJSON.meshes.push( gltfMesh );

return outputJSON.meshes.length - 1;
Expand Down Expand Up @@ -1420,7 +1441,13 @@ THREE.GLTFExporter.prototype = {

if ( object.isMesh || object.isLine || object.isPoints ) {

gltfNode.mesh = processMesh( object );
var mesh = processMesh( object );

if ( mesh !== null ) {

gltfNode.mesh = mesh;

}

} else if ( object.isCamera ) {

Expand Down
37 changes: 36 additions & 1 deletion test/unit/example/exporters/GLTFExporter.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default QUnit.module( 'Exporters', () => {

var done = assert.async();

var object = new THREE.Object3D()
var object = new THREE.Object3D();

var exporter = new THREE.GLTFExporter();

Expand Down Expand Up @@ -120,6 +120,41 @@ export default QUnit.module( 'Exporters', () => {

} );

QUnit.test( 'parse - empty buffergeometry', ( assert ) => {

var done = assert.async();

var scene = new THREE.Scene();
var geometry = new THREE.BufferGeometry();
var numElements = 6;

var positions = new Float32Array( ( numElements ) * 3 );
var colors = new Float32Array( ( numElements ) * 3 );

geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.setDrawRange( 0, 0 );

var empty = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, vertexColors: THREE.VertexColors } ) );
empty.name = 'Custom buffered empty (drawrange)';
scene.add( empty );

var exporter = new THREE.GLTFExporter();

exporter.parse( scene, function ( gltf ) {

assert.equal( gltf.meshes, undefined, 'empty meshes');
assert.equal( gltf.materials, undefined, 'empty materials');
assert.equal( gltf.bufferViews, undefined, 'empty bufferViews');
assert.equal( gltf.buffers, undefined, 'buffers');
assert.equal( gltf.accessors, undefined, 'accessors');
assert.equal( gltf.nodes[0].mesh, undefined, 'nodes[0].mesh');

done();

});

} );

} );

Expand Down