Skip to content

Commit 66ee44e

Browse files
authored
Merge pull request #13681 from fernandojsg/fixempty
GLTFExporter: Prevent exporting empty geometry
2 parents a51d774 + 7eff795 commit 66ee44e

File tree

2 files changed

+85
-23
lines changed

2 files changed

+85
-23
lines changed

examples/js/exporters/GLTFExporter.js

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ THREE.GLTFExporter.prototype = {
149149
var value = text.charCodeAt( i );
150150

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

154154
}
155155

@@ -425,12 +425,6 @@ THREE.GLTFExporter.prototype = {
425425
*/
426426
function processAccessor( attribute, geometry, start, count ) {
427427

428-
if ( ! outputJSON.accessors ) {
429-
430-
outputJSON.accessors = [];
431-
432-
}
433-
434428
var types = {
435429

436430
1: 'SCALAR',
@@ -484,6 +478,13 @@ THREE.GLTFExporter.prototype = {
484478

485479
}
486480

481+
// Skip creating an accessor if the attribute doesn't have data to export
482+
if ( count === 0 ) {
483+
484+
return null;
485+
486+
}
487+
487488
var minMax = getMinMax( attribute, start, count );
488489

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

511512
};
512513

514+
if ( ! outputJSON.accessors ) {
515+
516+
outputJSON.accessors = [];
517+
518+
}
519+
513520
outputJSON.accessors.push( gltfAccessor );
514521

515522
return outputJSON.accessors.length - 1;
@@ -872,12 +879,6 @@ THREE.GLTFExporter.prototype = {
872879
*/
873880
function processMesh( mesh ) {
874881

875-
if ( ! outputJSON.meshes ) {
876-
877-
outputJSON.meshes = [];
878-
879-
}
880-
881882
var geometry = mesh.geometry;
882883

883884
var mode;
@@ -963,12 +964,24 @@ THREE.GLTFExporter.prototype = {
963964

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

966-
attributes[ attributeName ] = processAccessor( attribute, geometry );
967+
var accessor = processAccessor( attribute, geometry );
968+
if ( accessor !== null ) {
969+
970+
attributes[ attributeName ] = accessor;
971+
972+
}
967973

968974
}
969975

970976
}
971977

978+
// Skip if no exportable attributes found
979+
if ( Object.keys( attributes ).length === 0 ) {
980+
981+
return null;
982+
983+
}
984+
972985
// Morph targets
973986
if ( mesh.morphTargetInfluences !== undefined && mesh.morphTargetInfluences.length > 0 ) {
974987

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

1073+
if ( isMultiMaterial && mesh.geometry.groups.length === 0 ) return null;
1074+
10601075
if ( ! forceIndices && geometry.index === null && isMultiMaterial ) {
10611076

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

10841099
}
10851100

1086-
var materials = isMultiMaterial ? mesh.material : [ mesh.material ] ;
1101+
var materials = isMultiMaterial ? mesh.material : [ mesh.material ];
10871102
var groups = isMultiMaterial ? mesh.geometry.groups : [ { materialIndex: 0, start: undefined, count: undefined } ];
10881103

10891104
for ( var i = 0, il = groups.length; i < il; i ++ ) {
@@ -1095,17 +1110,17 @@ THREE.GLTFExporter.prototype = {
10951110

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

1098-
var material = processMaterial( materials[ groups[ i ].materialIndex ] );
1099-
1100-
if ( material !== null ) {
1113+
if ( geometry.index !== null ) {
11011114

1102-
primitive.material = material;
1115+
primitive.indices = processAccessor( geometry.index, geometry, groups[ i ].start, groups[ i ].count );
11031116

11041117
}
11051118

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

1108-
primitive.indices = processAccessor( geometry.index, geometry, groups[ i ].start, groups[ i ].count );
1121+
if ( material !== null ) {
1122+
1123+
primitive.material = material;
11091124

11101125
}
11111126

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

11221137
gltfMesh.primitives = primitives;
11231138

1139+
if ( ! outputJSON.meshes ) {
1140+
1141+
outputJSON.meshes = [];
1142+
1143+
}
1144+
11241145
outputJSON.meshes.push( gltfMesh );
11251146

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

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

1423-
gltfNode.mesh = processMesh( object );
1444+
var mesh = processMesh( object );
1445+
1446+
if ( mesh !== null ) {
1447+
1448+
gltfNode.mesh = mesh;
1449+
1450+
}
14241451

14251452
} else if ( object.isCamera ) {
14261453

test/unit/example/exporters/GLTFExporter.tests.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default QUnit.module( 'Exporters', () => {
1919

2020
var done = assert.async();
2121

22-
var object = new THREE.Object3D()
22+
var object = new THREE.Object3D();
2323

2424
var exporter = new THREE.GLTFExporter();
2525

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

121121
} );
122122

123+
QUnit.test( 'parse - empty buffergeometry', ( assert ) => {
124+
125+
var done = assert.async();
126+
127+
var scene = new THREE.Scene();
128+
var geometry = new THREE.BufferGeometry();
129+
var numElements = 6;
130+
131+
var positions = new Float32Array( ( numElements ) * 3 );
132+
var colors = new Float32Array( ( numElements ) * 3 );
133+
134+
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
135+
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
136+
geometry.setDrawRange( 0, 0 );
137+
138+
var empty = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, vertexColors: THREE.VertexColors } ) );
139+
empty.name = 'Custom buffered empty (drawrange)';
140+
scene.add( empty );
141+
142+
var exporter = new THREE.GLTFExporter();
143+
144+
exporter.parse( scene, function ( gltf ) {
145+
146+
assert.equal( gltf.meshes, undefined, 'empty meshes');
147+
assert.equal( gltf.materials, undefined, 'empty materials');
148+
assert.equal( gltf.bufferViews, undefined, 'empty bufferViews');
149+
assert.equal( gltf.buffers, undefined, 'buffers');
150+
assert.equal( gltf.accessors, undefined, 'accessors');
151+
assert.equal( gltf.nodes[0].mesh, undefined, 'nodes[0].mesh');
152+
153+
done();
154+
155+
});
156+
157+
} );
123158

124159
} );
125160

0 commit comments

Comments
 (0)