hyperbook 0.93.1 → 0.94.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,411 +0,0 @@
1
- import {
2
- BufferAttribute,
3
- BufferGeometry,
4
- Color,
5
- FileLoader,
6
- Float32BufferAttribute,
7
- Loader,
8
- Vector3,
9
- SRGBColorSpace
10
- } from './three.module.js';
11
-
12
- /**
13
- * Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.
14
- *
15
- * Supports both binary and ASCII encoded files, with automatic detection of type.
16
- *
17
- * The loader returns a non-indexed buffer geometry.
18
- *
19
- * Limitations:
20
- * Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
21
- * There is perhaps some question as to how valid it is to always assume little-endian-ness.
22
- * ASCII decoding assumes file is UTF-8.
23
- *
24
- * Usage:
25
- * const loader = new STLLoader();
26
- * loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {
27
- * scene.add( new THREE.Mesh( geometry ) );
28
- * });
29
- *
30
- * For binary STLs geometry might contain colors for vertices. To use it:
31
- * // use the same code to load STL as above
32
- * if (geometry.hasColors) {
33
- * material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true });
34
- * } else { .... }
35
- * const mesh = new THREE.Mesh( geometry, material );
36
- *
37
- * For ASCII STLs containing multiple solids, each solid is assigned to a different group.
38
- * Groups can be used to assign a different color by defining an array of materials with the same length of
39
- * geometry.groups and passing it to the Mesh constructor:
40
- *
41
- * const mesh = new THREE.Mesh( geometry, material );
42
- *
43
- * For example:
44
- *
45
- * const materials = [];
46
- * const nGeometryGroups = geometry.groups.length;
47
- *
48
- * const colorMap = ...; // Some logic to index colors.
49
- *
50
- * for (let i = 0; i < nGeometryGroups; i++) {
51
- *
52
- * const material = new THREE.MeshPhongMaterial({
53
- * color: colorMap[i],
54
- * wireframe: false
55
- * });
56
- *
57
- * }
58
- *
59
- * materials.push(material);
60
- * const mesh = new THREE.Mesh(geometry, materials);
61
- */
62
-
63
-
64
- class STLLoader extends Loader {
65
-
66
- constructor( manager ) {
67
-
68
- super( manager );
69
-
70
- }
71
-
72
- load( url, onLoad, onProgress, onError ) {
73
-
74
- const scope = this;
75
-
76
- const loader = new FileLoader( this.manager );
77
- loader.setPath( this.path );
78
- loader.setResponseType( 'arraybuffer' );
79
- loader.setRequestHeader( this.requestHeader );
80
- loader.setWithCredentials( this.withCredentials );
81
-
82
- loader.load( url, function ( text ) {
83
-
84
- try {
85
-
86
- onLoad( scope.parse( text ) );
87
-
88
- } catch ( e ) {
89
-
90
- if ( onError ) {
91
-
92
- onError( e );
93
-
94
- } else {
95
-
96
- console.error( e );
97
-
98
- }
99
-
100
- scope.manager.itemError( url );
101
-
102
- }
103
-
104
- }, onProgress, onError );
105
-
106
- }
107
-
108
- parse( data ) {
109
-
110
- function isBinary( data ) {
111
-
112
- const reader = new DataView( data );
113
- const face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 );
114
- const n_faces = reader.getUint32( 80, true );
115
- const expect = 80 + ( 32 / 8 ) + ( n_faces * face_size );
116
-
117
- if ( expect === reader.byteLength ) {
118
-
119
- return true;
120
-
121
- }
122
-
123
- // An ASCII STL data must begin with 'solid ' as the first six bytes.
124
- // However, ASCII STLs lacking the SPACE after the 'd' are known to be
125
- // plentiful. So, check the first 5 bytes for 'solid'.
126
-
127
- // Several encodings, such as UTF-8, precede the text with up to 5 bytes:
128
- // https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
129
- // Search for "solid" to start anywhere after those prefixes.
130
-
131
- // US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
132
-
133
- const solid = [ 115, 111, 108, 105, 100 ];
134
-
135
- for ( let off = 0; off < 5; off ++ ) {
136
-
137
- // If "solid" text is matched to the current offset, declare it to be an ASCII STL.
138
-
139
- if ( matchDataViewAt( solid, reader, off ) ) return false;
140
-
141
- }
142
-
143
- // Couldn't find "solid" text at the beginning; it is binary STL.
144
-
145
- return true;
146
-
147
- }
148
-
149
- function matchDataViewAt( query, reader, offset ) {
150
-
151
- // Check if each byte in query matches the corresponding byte from the current offset
152
-
153
- for ( let i = 0, il = query.length; i < il; i ++ ) {
154
-
155
- if ( query[ i ] !== reader.getUint8( offset + i ) ) return false;
156
-
157
- }
158
-
159
- return true;
160
-
161
- }
162
-
163
- function parseBinary( data ) {
164
-
165
- const reader = new DataView( data );
166
- const faces = reader.getUint32( 80, true );
167
-
168
- let r, g, b, hasColors = false, colors;
169
- let defaultR, defaultG, defaultB, alpha;
170
-
171
- // process STL header
172
- // check for default color in header ("COLOR=rgba" sequence).
173
-
174
- for ( let index = 0; index < 80 - 10; index ++ ) {
175
-
176
- if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) &&
177
- ( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) &&
178
- ( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) {
179
-
180
- hasColors = true;
181
- colors = new Float32Array( faces * 3 * 3 );
182
-
183
- defaultR = reader.getUint8( index + 6 ) / 255;
184
- defaultG = reader.getUint8( index + 7 ) / 255;
185
- defaultB = reader.getUint8( index + 8 ) / 255;
186
- alpha = reader.getUint8( index + 9 ) / 255;
187
-
188
- }
189
-
190
- }
191
-
192
- const dataOffset = 84;
193
- const faceLength = 12 * 4 + 2;
194
-
195
- const geometry = new BufferGeometry();
196
-
197
- const vertices = new Float32Array( faces * 3 * 3 );
198
- const normals = new Float32Array( faces * 3 * 3 );
199
-
200
- const color = new Color();
201
-
202
- for ( let face = 0; face < faces; face ++ ) {
203
-
204
- const start = dataOffset + face * faceLength;
205
- const normalX = reader.getFloat32( start, true );
206
- const normalY = reader.getFloat32( start + 4, true );
207
- const normalZ = reader.getFloat32( start + 8, true );
208
-
209
- if ( hasColors ) {
210
-
211
- const packedColor = reader.getUint16( start + 48, true );
212
-
213
- if ( ( packedColor & 0x8000 ) === 0 ) {
214
-
215
- // facet has its own unique color
216
-
217
- r = ( packedColor & 0x1F ) / 31;
218
- g = ( ( packedColor >> 5 ) & 0x1F ) / 31;
219
- b = ( ( packedColor >> 10 ) & 0x1F ) / 31;
220
-
221
- } else {
222
-
223
- r = defaultR;
224
- g = defaultG;
225
- b = defaultB;
226
-
227
- }
228
-
229
- }
230
-
231
- for ( let i = 1; i <= 3; i ++ ) {
232
-
233
- const vertexstart = start + i * 12;
234
- const componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 );
235
-
236
- vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
237
- vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
238
- vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
239
-
240
- normals[ componentIdx ] = normalX;
241
- normals[ componentIdx + 1 ] = normalY;
242
- normals[ componentIdx + 2 ] = normalZ;
243
-
244
- if ( hasColors ) {
245
-
246
- color.setRGB( r, g, b, SRGBColorSpace );
247
-
248
- colors[ componentIdx ] = color.r;
249
- colors[ componentIdx + 1 ] = color.g;
250
- colors[ componentIdx + 2 ] = color.b;
251
-
252
- }
253
-
254
- }
255
-
256
- }
257
-
258
- geometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) );
259
- geometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) );
260
-
261
- if ( hasColors ) {
262
-
263
- geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
264
- geometry.hasColors = true;
265
- geometry.alpha = alpha;
266
-
267
- }
268
-
269
- return geometry;
270
-
271
- }
272
-
273
- function parseASCII( data ) {
274
-
275
- const geometry = new BufferGeometry();
276
- const patternSolid = /solid([\s\S]*?)endsolid/g;
277
- const patternFace = /facet([\s\S]*?)endfacet/g;
278
- const patternName = /solid\s(.+)/;
279
- let faceCounter = 0;
280
-
281
- const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source;
282
- const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' );
283
- const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' );
284
-
285
- const vertices = [];
286
- const normals = [];
287
- const groupNames = [];
288
-
289
- const normal = new Vector3();
290
-
291
- let result;
292
-
293
- let groupCount = 0;
294
- let startVertex = 0;
295
- let endVertex = 0;
296
-
297
- while ( ( result = patternSolid.exec( data ) ) !== null ) {
298
-
299
- startVertex = endVertex;
300
-
301
- const solid = result[ 0 ];
302
-
303
- const name = ( result = patternName.exec( solid ) ) !== null ? result[ 1 ] : '';
304
- groupNames.push( name );
305
-
306
- while ( ( result = patternFace.exec( solid ) ) !== null ) {
307
-
308
- let vertexCountPerFace = 0;
309
- let normalCountPerFace = 0;
310
-
311
- const text = result[ 0 ];
312
-
313
- while ( ( result = patternNormal.exec( text ) ) !== null ) {
314
-
315
- normal.x = parseFloat( result[ 1 ] );
316
- normal.y = parseFloat( result[ 2 ] );
317
- normal.z = parseFloat( result[ 3 ] );
318
- normalCountPerFace ++;
319
-
320
- }
321
-
322
- while ( ( result = patternVertex.exec( text ) ) !== null ) {
323
-
324
- vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
325
- normals.push( normal.x, normal.y, normal.z );
326
- vertexCountPerFace ++;
327
- endVertex ++;
328
-
329
- }
330
-
331
- // every face have to own ONE valid normal
332
-
333
- if ( normalCountPerFace !== 1 ) {
334
-
335
- console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
336
-
337
- }
338
-
339
- // each face have to own THREE valid vertices
340
-
341
- if ( vertexCountPerFace !== 3 ) {
342
-
343
- console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
344
-
345
- }
346
-
347
- faceCounter ++;
348
-
349
- }
350
-
351
- const start = startVertex;
352
- const count = endVertex - startVertex;
353
-
354
- geometry.userData.groupNames = groupNames;
355
-
356
- geometry.addGroup( start, count, groupCount );
357
- groupCount ++;
358
-
359
- }
360
-
361
- geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
362
- geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
363
-
364
- return geometry;
365
-
366
- }
367
-
368
- function ensureString( buffer ) {
369
-
370
- if ( typeof buffer !== 'string' ) {
371
-
372
- return new TextDecoder().decode( buffer );
373
-
374
- }
375
-
376
- return buffer;
377
-
378
- }
379
-
380
- function ensureBinary( buffer ) {
381
-
382
- if ( typeof buffer === 'string' ) {
383
-
384
- const array_buffer = new Uint8Array( buffer.length );
385
- for ( let i = 0; i < buffer.length; i ++ ) {
386
-
387
- array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
388
-
389
- }
390
-
391
- return array_buffer.buffer || array_buffer;
392
-
393
- } else {
394
-
395
- return buffer;
396
-
397
- }
398
-
399
- }
400
-
401
- // start
402
-
403
- const binData = ensureBinary( data );
404
-
405
- return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) );
406
-
407
- }
408
-
409
- }
410
-
411
- export { STLLoader };