Skip to content

Commit 77240ec

Browse files
authored
Merge pull request #20494 from Mugen87/dev51
STLExporter: Use BufferGeometry, supported skeletons.
2 parents 420bfdd + ecdcdc1 commit 77240ec

File tree

2 files changed

+245
-162
lines changed

2 files changed

+245
-162
lines changed

examples/js/exporters/STLExporter.js

Lines changed: 122 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -14,149 +14,191 @@ THREE.STLExporter.prototype = {
1414

1515
constructor: THREE.STLExporter,
1616

17-
parse: ( function () {
17+
parse: function ( scene, options ) {
1818

19-
var vector = new THREE.Vector3();
20-
var normalMatrixWorld = new THREE.Matrix3();
19+
if ( options === undefined ) options = {};
2120

22-
return function parse( scene, options ) {
21+
var binary = options.binary !== undefined ? options.binary : false;
2322

24-
if ( options === undefined ) options = {};
23+
//
2524

26-
var binary = options.binary !== undefined ? options.binary : false;
25+
var objects = [];
26+
var triangles = 0;
2727

28-
//
28+
scene.traverse( function ( object ) {
2929

30-
var objects = [];
31-
var triangles = 0;
30+
if ( object.isMesh ) {
3231

33-
scene.traverse( function ( object ) {
32+
var geometry = object.geometry;
3433

35-
if ( object.isMesh ) {
34+
if ( geometry.isGeometry ) {
3635

37-
var geometry = object.geometry;
36+
geometry = new THREE.BufferGeometry().fromGeometry( geometry );
3837

39-
if ( geometry.isBufferGeometry ) {
40-
41-
geometry = new THREE.Geometry().fromBufferGeometry( geometry );
38+
}
4239

43-
}
40+
var index = geometry.index;
41+
var positionAttribute = geometry.getAttribute( 'position' );
4442

45-
if ( geometry.isGeometry ) {
43+
triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 );
4644

47-
triangles += geometry.faces.length;
45+
objects.push( {
46+
object3d: object,
47+
geometry: geometry
48+
} );
4849

49-
objects.push( {
50+
}
5051

51-
geometry: geometry,
52-
matrixWorld: object.matrixWorld
52+
} );
5353

54-
} );
54+
var output;
55+
var offset = 80; // skip header
5556

56-
}
57+
if ( binary === true ) {
5758

58-
}
59+
var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
60+
var arrayBuffer = new ArrayBuffer( bufferLength );
61+
output = new DataView( arrayBuffer );
62+
output.setUint32( offset, triangles, true ); offset += 4;
5963

60-
} );
64+
} else {
6165

62-
if ( binary ) {
66+
output = '';
67+
output += 'solid exported\n';
6368

64-
var offset = 80; // skip header
65-
var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
66-
var arrayBuffer = new ArrayBuffer( bufferLength );
67-
var output = new DataView( arrayBuffer );
68-
output.setUint32( offset, triangles, true ); offset += 4;
69+
}
6970

70-
for ( var i = 0, il = objects.length; i < il; i ++ ) {
71+
var vA = new THREE.Vector3();
72+
var vB = new THREE.Vector3();
73+
var vC = new THREE.Vector3();
74+
var cb = new THREE.Vector3();
75+
var ab = new THREE.Vector3();
76+
var normal = new THREE.Vector3();
7177

72-
var object = objects[ i ];
78+
for ( var i = 0, il = objects.length; i < il; i ++ ) {
7379

74-
var vertices = object.geometry.vertices;
75-
var faces = object.geometry.faces;
76-
var matrixWorld = object.matrixWorld;
80+
var object = objects[ i ].object3d;
81+
var geometry = objects[ i ].geometry;
7782

78-
normalMatrixWorld.getNormalMatrix( matrixWorld );
83+
var index = geometry.index;
84+
var positionAttribute = geometry.getAttribute( 'position' );
7985

80-
for ( var j = 0, jl = faces.length; j < jl; j ++ ) {
86+
if ( index !== null ) {
8187

82-
var face = faces[ j ];
88+
// indexed geometry
8389

84-
vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
90+
for ( var j = 0; j < index.count; j += 3 ) {
8591

86-
output.setFloat32( offset, vector.x, true ); offset += 4; // normal
87-
output.setFloat32( offset, vector.y, true ); offset += 4;
88-
output.setFloat32( offset, vector.z, true ); offset += 4;
92+
var a = index.getX( j + 0 );
93+
var b = index.getX( j + 1 );
94+
var c = index.getX( j + 2 );
8995

90-
var indices = [ face.a, face.b, face.c ];
96+
writeFace( a, b, c, positionAttribute, object );
9197

92-
for ( var k = 0; k < 3; k ++ ) {
98+
}
9399

94-
vector.copy( vertices[ indices[ k ] ] ).applyMatrix4( matrixWorld );
100+
} else {
95101

96-
output.setFloat32( offset, vector.x, true ); offset += 4; // vertices
97-
output.setFloat32( offset, vector.y, true ); offset += 4;
98-
output.setFloat32( offset, vector.z, true ); offset += 4;
102+
// non-indexed geometry
99103

100-
}
104+
for ( var j = 0; j < positionAttribute.count; j += 3 ) {
101105

102-
output.setUint16( offset, 0, true ); offset += 2; // attribute byte count
106+
var a = j + 0;
107+
var b = j + 1;
108+
var c = j + 2;
103109

104-
}
110+
writeFace( a, b, c, positionAttribute, object );
105111

106112
}
107113

108-
return output;
114+
}
115+
116+
}
109117

110-
} else {
118+
if ( binary === false ) {
111119

112-
var output = '';
120+
output += 'endsolid exported\n';
113121

114-
output += 'solid exported\n';
122+
}
115123

116-
for ( var i = 0, il = objects.length; i < il; i ++ ) {
124+
return output;
117125

118-
var object = objects[ i ];
126+
function writeFace( a, b, c, positionAttribute, object ) {
119127

120-
var vertices = object.geometry.vertices;
121-
var faces = object.geometry.faces;
122-
var matrixWorld = object.matrixWorld;
128+
vA.fromBufferAttribute( positionAttribute, a );
129+
vB.fromBufferAttribute( positionAttribute, b );
130+
vC.fromBufferAttribute( positionAttribute, c );
123131

124-
normalMatrixWorld.getNormalMatrix( matrixWorld );
132+
if ( object.isSkinnedMesh === true ) {
125133

126-
for ( var j = 0, jl = faces.length; j < jl; j ++ ) {
134+
object.boneTransform( a, vA );
135+
object.boneTransform( b, vB );
136+
object.boneTransform( c, vC );
127137

128-
var face = faces[ j ];
138+
}
129139

130-
vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
140+
vA.applyMatrix4( object.matrixWorld );
141+
vB.applyMatrix4( object.matrixWorld );
142+
vC.applyMatrix4( object.matrixWorld );
131143

132-
output += '\tfacet normal ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
133-
output += '\t\touter loop\n';
144+
writeNormal( vA, vB, vC );
134145

135-
var indices = [ face.a, face.b, face.c ];
146+
writeVertex( vA );
147+
writeVertex( vB );
148+
writeVertex( vC );
136149

137-
for ( var k = 0; k < 3; k ++ ) {
150+
if ( binary === true ) {
138151

139-
vector.copy( vertices[ indices[ k ] ] ).applyMatrix4( matrixWorld );
152+
output.setUint16( offset, 0, true ); offset += 2;
140153

141-
output += '\t\t\tvertex ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
154+
} else {
142155

143-
}
156+
output += '\t\tendloop\n';
157+
output += '\tendfacet\n';
144158

145-
output += '\t\tendloop\n';
146-
output += '\tendfacet\n';
159+
}
147160

148-
}
161+
}
149162

150-
}
163+
function writeNormal( vA, vB, vC ) {
164+
165+
cb.subVectors( vC, vB );
166+
ab.subVectors( vA, vB );
167+
cb.cross( ab ).normalize();
151168

152-
output += 'endsolid exported\n';
169+
normal.copy( cb ).normalize();
170+
171+
if ( binary === true ) {
172+
173+
output.setFloat32( offset, normal.x, true ); offset += 4;
174+
output.setFloat32( offset, normal.y, true ); offset += 4;
175+
output.setFloat32( offset, normal.z, true ); offset += 4;
176+
177+
} else {
178+
179+
output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
180+
output += '\t\touter loop\n';
181+
182+
}
183+
184+
}
185+
186+
function writeVertex( vertex ) {
187+
188+
if ( binary === true ) {
189+
190+
output.setFloat32( offset, vertex.x, true ); offset += 4;
191+
output.setFloat32( offset, vertex.y, true ); offset += 4;
192+
output.setFloat32( offset, vertex.z, true ); offset += 4;
193+
194+
} else {
153195

154-
return output;
196+
output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
155197

156198
}
157199

158-
};
200+
}
159201

160-
}() )
202+
}
161203

162204
};

0 commit comments

Comments
 (0)