@damienmortini/three 0.1.172 → 0.1.173
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.
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
FrontSide,
|
|
13
13
|
Group,
|
|
14
14
|
ImageBitmapLoader,
|
|
15
|
+
InstancedMesh,
|
|
15
16
|
InterleavedBuffer,
|
|
16
17
|
InterleavedBufferAttribute,
|
|
17
18
|
Interpolant,
|
|
@@ -147,6 +148,12 @@ class GLTFLoader extends Loader {
|
|
|
147
148
|
|
|
148
149
|
} );
|
|
149
150
|
|
|
151
|
+
this.register( function ( parser ) {
|
|
152
|
+
|
|
153
|
+
return new GLTFMeshGpuInstancing( parser );
|
|
154
|
+
|
|
155
|
+
} );
|
|
156
|
+
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
load( url, onLoad, onProgress, onError ) {
|
|
@@ -277,15 +284,15 @@ class GLTFLoader extends Loader {
|
|
|
277
284
|
|
|
278
285
|
parse( data, path, onLoad, onError ) {
|
|
279
286
|
|
|
280
|
-
let
|
|
287
|
+
let json;
|
|
281
288
|
const extensions = {};
|
|
282
289
|
const plugins = {};
|
|
283
290
|
|
|
284
291
|
if ( typeof data === 'string' ) {
|
|
285
292
|
|
|
286
|
-
|
|
293
|
+
json = JSON.parse( data );
|
|
287
294
|
|
|
288
|
-
} else {
|
|
295
|
+
} else if ( data instanceof ArrayBuffer ) {
|
|
289
296
|
|
|
290
297
|
const magic = LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );
|
|
291
298
|
|
|
@@ -302,17 +309,19 @@ class GLTFLoader extends Loader {
|
|
|
302
309
|
|
|
303
310
|
}
|
|
304
311
|
|
|
305
|
-
|
|
312
|
+
json = JSON.parse( extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content );
|
|
306
313
|
|
|
307
314
|
} else {
|
|
308
315
|
|
|
309
|
-
|
|
316
|
+
json = JSON.parse( LoaderUtils.decodeText( new Uint8Array( data ) ) );
|
|
310
317
|
|
|
311
318
|
}
|
|
312
319
|
|
|
313
|
-
}
|
|
320
|
+
} else {
|
|
321
|
+
|
|
322
|
+
json = data;
|
|
314
323
|
|
|
315
|
-
|
|
324
|
+
}
|
|
316
325
|
|
|
317
326
|
if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
|
|
318
327
|
|
|
@@ -468,7 +477,8 @@ const EXTENSIONS = {
|
|
|
468
477
|
KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
|
|
469
478
|
KHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength',
|
|
470
479
|
EXT_TEXTURE_WEBP: 'EXT_texture_webp',
|
|
471
|
-
EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression'
|
|
480
|
+
EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
|
|
481
|
+
EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'
|
|
472
482
|
};
|
|
473
483
|
|
|
474
484
|
/**
|
|
@@ -1384,6 +1394,160 @@ class GLTFMeshoptCompression {
|
|
|
1384
1394
|
|
|
1385
1395
|
}
|
|
1386
1396
|
|
|
1397
|
+
/**
|
|
1398
|
+
* GPU Instancing Extension
|
|
1399
|
+
*
|
|
1400
|
+
* Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
|
|
1401
|
+
*
|
|
1402
|
+
*/
|
|
1403
|
+
class GLTFMeshGpuInstancing {
|
|
1404
|
+
|
|
1405
|
+
constructor( parser ) {
|
|
1406
|
+
|
|
1407
|
+
this.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;
|
|
1408
|
+
this.parser = parser;
|
|
1409
|
+
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
createNodeMesh( nodeIndex ) {
|
|
1413
|
+
|
|
1414
|
+
const json = this.parser.json;
|
|
1415
|
+
const nodeDef = json.nodes[ nodeIndex ];
|
|
1416
|
+
|
|
1417
|
+
if ( ! nodeDef.extensions || ! nodeDef.extensions[ this.name ] ||
|
|
1418
|
+
nodeDef.mesh === undefined ) {
|
|
1419
|
+
|
|
1420
|
+
return null;
|
|
1421
|
+
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const meshDef = json.meshes[ nodeDef.mesh ];
|
|
1425
|
+
|
|
1426
|
+
// No Points or Lines + Instancing support yet
|
|
1427
|
+
|
|
1428
|
+
for ( const primitive of meshDef.primitives ) {
|
|
1429
|
+
|
|
1430
|
+
if ( primitive.mode !== WEBGL_CONSTANTS.TRIANGLES &&
|
|
1431
|
+
primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP &&
|
|
1432
|
+
primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN &&
|
|
1433
|
+
primitive.mode !== undefined ) {
|
|
1434
|
+
|
|
1435
|
+
return null;
|
|
1436
|
+
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
const extensionDef = nodeDef.extensions[ this.name ];
|
|
1442
|
+
const attributesDef = extensionDef.attributes;
|
|
1443
|
+
|
|
1444
|
+
// @TODO: Can we support InstancedMesh + SkinnedMesh?
|
|
1445
|
+
|
|
1446
|
+
const pending = [];
|
|
1447
|
+
const attributes = {};
|
|
1448
|
+
|
|
1449
|
+
for ( const key in attributesDef ) {
|
|
1450
|
+
|
|
1451
|
+
pending.push( this.parser.getDependency( 'accessor', attributesDef[ key ] ).then( accessor => {
|
|
1452
|
+
|
|
1453
|
+
attributes[ key ] = accessor;
|
|
1454
|
+
return attributes[ key ];
|
|
1455
|
+
|
|
1456
|
+
} ) );
|
|
1457
|
+
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
if ( pending.length < 1 ) {
|
|
1461
|
+
|
|
1462
|
+
return null;
|
|
1463
|
+
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
pending.push( this.parser.createNodeMesh( nodeIndex ) );
|
|
1467
|
+
|
|
1468
|
+
return Promise.all( pending ).then( results => {
|
|
1469
|
+
|
|
1470
|
+
const nodeObject = results.pop();
|
|
1471
|
+
const meshes = nodeObject.isGroup ? nodeObject.children : [ nodeObject ];
|
|
1472
|
+
const count = results[ 0 ].count; // All attribute counts should be same
|
|
1473
|
+
const instancedMeshes = [];
|
|
1474
|
+
|
|
1475
|
+
for ( const mesh of meshes ) {
|
|
1476
|
+
|
|
1477
|
+
// Temporal variables
|
|
1478
|
+
const m = new Matrix4();
|
|
1479
|
+
const p = new Vector3();
|
|
1480
|
+
const q = new Quaternion();
|
|
1481
|
+
const s = new Vector3( 1, 1, 1 );
|
|
1482
|
+
|
|
1483
|
+
const instancedMesh = new InstancedMesh( mesh.geometry, mesh.material, count );
|
|
1484
|
+
|
|
1485
|
+
for ( let i = 0; i < count; i ++ ) {
|
|
1486
|
+
|
|
1487
|
+
if ( attributes.TRANSLATION ) {
|
|
1488
|
+
|
|
1489
|
+
p.fromBufferAttribute( attributes.TRANSLATION, i );
|
|
1490
|
+
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
if ( attributes.ROTATION ) {
|
|
1494
|
+
|
|
1495
|
+
q.fromBufferAttribute( attributes.ROTATION, i );
|
|
1496
|
+
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
if ( attributes.SCALE ) {
|
|
1500
|
+
|
|
1501
|
+
s.fromBufferAttribute( attributes.SCALE, i );
|
|
1502
|
+
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
instancedMesh.setMatrixAt( i, m.compose( p, q, s ) );
|
|
1506
|
+
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
// Add instance attributes to the geometry, excluding TRS.
|
|
1510
|
+
for ( const attributeName in attributes ) {
|
|
1511
|
+
|
|
1512
|
+
if ( attributeName !== 'TRANSLATION' &&
|
|
1513
|
+
attributeName !== 'ROTATION' &&
|
|
1514
|
+
attributeName !== 'SCALE' ) {
|
|
1515
|
+
|
|
1516
|
+
mesh.geometry.setAttribute( attributeName, attributes[ attributeName ] );
|
|
1517
|
+
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
// Just in case
|
|
1523
|
+
Object3D.prototype.copy.call( instancedMesh, mesh );
|
|
1524
|
+
|
|
1525
|
+
// https://github.com/mrdoob/three.js/issues/18334
|
|
1526
|
+
instancedMesh.frustumCulled = false;
|
|
1527
|
+
this.parser.assignFinalMaterial( instancedMesh );
|
|
1528
|
+
|
|
1529
|
+
instancedMeshes.push( instancedMesh );
|
|
1530
|
+
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
if ( nodeObject.isGroup ) {
|
|
1534
|
+
|
|
1535
|
+
nodeObject.clear();
|
|
1536
|
+
|
|
1537
|
+
nodeObject.add( ... instancedMeshes );
|
|
1538
|
+
|
|
1539
|
+
return nodeObject;
|
|
1540
|
+
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
return instancedMeshes[ 0 ];
|
|
1544
|
+
|
|
1545
|
+
} );
|
|
1546
|
+
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1387
1551
|
/* BINARY EXTENSION */
|
|
1388
1552
|
const BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
|
|
1389
1553
|
const BINARY_EXTENSION_HEADER_LENGTH = 12;
|
|
@@ -3026,7 +3190,7 @@ class GLTFParser {
|
|
|
3026
3190
|
|
|
3027
3191
|
texture.flipY = false;
|
|
3028
3192
|
|
|
3029
|
-
|
|
3193
|
+
texture.name = textureDef.name || sourceDef.name || '';
|
|
3030
3194
|
|
|
3031
3195
|
const samplers = json.samplers || {};
|
|
3032
3196
|
const sampler = samplers[ textureDef.sampler ] || {};
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
CompressedTexture,
|
|
16
|
+
CompressedArrayTexture,
|
|
16
17
|
Data3DTexture,
|
|
17
18
|
DataTexture,
|
|
18
19
|
FileLoader,
|
|
@@ -35,7 +36,7 @@ import {
|
|
|
35
36
|
RGBAFormat,
|
|
36
37
|
RGFormat,
|
|
37
38
|
sRGBEncoding,
|
|
38
|
-
UnsignedByteType
|
|
39
|
+
UnsignedByteType,
|
|
39
40
|
} from '../../../../three/src/Three.js';
|
|
40
41
|
import { WorkerPool } from '../utils/WorkerPool.js';
|
|
41
42
|
import {
|
|
@@ -236,16 +237,21 @@ class KTX2Loader extends Loader {
|
|
|
236
237
|
|
|
237
238
|
}
|
|
238
239
|
|
|
239
|
-
_createTextureFrom( transcodeResult ) {
|
|
240
|
+
_createTextureFrom( transcodeResult, container ) {
|
|
240
241
|
|
|
241
242
|
const { mipmaps, width, height, format, type, error, dfdTransferFn, dfdFlags } = transcodeResult;
|
|
242
243
|
|
|
243
244
|
if ( type === 'error' ) return Promise.reject( error );
|
|
244
245
|
|
|
245
|
-
const texture =
|
|
246
|
+
const texture = container.layerCount > 1
|
|
247
|
+
? new CompressedArrayTexture( mipmaps, width, height, container.layerCount, format, UnsignedByteType )
|
|
248
|
+
: new CompressedTexture( mipmaps, width, height, format, UnsignedByteType );
|
|
249
|
+
|
|
250
|
+
|
|
246
251
|
texture.minFilter = mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter;
|
|
247
252
|
texture.magFilter = LinearFilter;
|
|
248
253
|
texture.generateMipmaps = false;
|
|
254
|
+
|
|
249
255
|
texture.needsUpdate = true;
|
|
250
256
|
texture.encoding = dfdTransferFn === KHR_DF_TRANSFER_SRGB ? sRGBEncoding : LinearEncoding;
|
|
251
257
|
texture.premultiplyAlpha = !! ( dfdFlags & KHR_DF_FLAG_ALPHA_PREMULTIPLIED );
|
|
@@ -257,9 +263,9 @@ class KTX2Loader extends Loader {
|
|
|
257
263
|
/**
|
|
258
264
|
* @param {ArrayBuffer} buffer
|
|
259
265
|
* @param {object?} config
|
|
260
|
-
* @return {Promise<CompressedTexture|DataTexture|Data3DTexture>}
|
|
266
|
+
* @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
|
|
261
267
|
*/
|
|
262
|
-
_createTexture( buffer, config = {} ) {
|
|
268
|
+
async _createTexture( buffer, config = {} ) {
|
|
263
269
|
|
|
264
270
|
const container = read( new Uint8Array( buffer ) );
|
|
265
271
|
|
|
@@ -270,13 +276,12 @@ class KTX2Loader extends Loader {
|
|
|
270
276
|
}
|
|
271
277
|
|
|
272
278
|
//
|
|
273
|
-
|
|
274
279
|
const taskConfig = config;
|
|
275
280
|
const texturePending = this.init().then( () => {
|
|
276
281
|
|
|
277
282
|
return this.workerPool.postMessage( { type: 'transcode', buffer, taskConfig: taskConfig }, [ buffer ] );
|
|
278
283
|
|
|
279
|
-
} ).then( ( e ) => this._createTextureFrom( e.data ) );
|
|
284
|
+
} ).then( ( e ) => this._createTextureFrom( e.data, container ) );
|
|
280
285
|
|
|
281
286
|
// Cache the task result.
|
|
282
287
|
_taskCache.set( buffer, { promise: texturePending } );
|
|
@@ -437,6 +442,7 @@ KTX2Loader.BasisWorker = function () {
|
|
|
437
442
|
const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
|
|
438
443
|
const width = ktx2File.getWidth();
|
|
439
444
|
const height = ktx2File.getHeight();
|
|
445
|
+
const layers = ktx2File.getLayers() || 1;
|
|
440
446
|
const levels = ktx2File.getLevels();
|
|
441
447
|
const hasAlpha = ktx2File.getHasAlpha();
|
|
442
448
|
const dfdTransferFn = ktx2File.getDFDTransferFunc();
|
|
@@ -462,30 +468,39 @@ KTX2Loader.BasisWorker = function () {
|
|
|
462
468
|
|
|
463
469
|
for ( let mip = 0; mip < levels; mip ++ ) {
|
|
464
470
|
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
0,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
471
|
+
const layerMips = [];
|
|
472
|
+
|
|
473
|
+
let mipWidth, mipHeight;
|
|
474
|
+
|
|
475
|
+
for ( let layer = 0; layer < layers; layer ++ ) {
|
|
476
|
+
|
|
477
|
+
const levelInfo = ktx2File.getImageLevelInfo( mip, layer, 0 );
|
|
478
|
+
mipWidth = levelInfo.origWidth;
|
|
479
|
+
mipHeight = levelInfo.origHeight;
|
|
480
|
+
const dst = new Uint8Array( ktx2File.getImageTranscodedSizeInBytes( mip, layer, 0, transcoderFormat ) );
|
|
481
|
+
const status = ktx2File.transcodeImage(
|
|
482
|
+
dst,
|
|
483
|
+
mip,
|
|
484
|
+
layer,
|
|
485
|
+
0,
|
|
486
|
+
transcoderFormat,
|
|
487
|
+
0,
|
|
488
|
+
- 1,
|
|
489
|
+
- 1,
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
if ( ! status ) {
|
|
480
493
|
|
|
481
|
-
|
|
494
|
+
cleanup();
|
|
495
|
+
throw new Error( 'THREE.KTX2Loader: .transcodeImage failed.' );
|
|
482
496
|
|
|
483
|
-
|
|
484
|
-
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
layerMips.push( dst );
|
|
485
500
|
|
|
486
501
|
}
|
|
487
502
|
|
|
488
|
-
mipmaps.push( { data:
|
|
503
|
+
mipmaps.push( { data: concat( layerMips ), width: mipWidth, height: mipHeight } );
|
|
489
504
|
|
|
490
505
|
}
|
|
491
506
|
|
|
@@ -612,6 +627,33 @@ KTX2Loader.BasisWorker = function () {
|
|
|
612
627
|
|
|
613
628
|
}
|
|
614
629
|
|
|
630
|
+
/** Concatenates N byte arrays. */
|
|
631
|
+
function concat( arrays ) {
|
|
632
|
+
|
|
633
|
+
let totalByteLength = 0;
|
|
634
|
+
|
|
635
|
+
for ( const array of arrays ) {
|
|
636
|
+
|
|
637
|
+
totalByteLength += array.byteLength;
|
|
638
|
+
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const result = new Uint8Array( totalByteLength );
|
|
642
|
+
|
|
643
|
+
let byteOffset = 0;
|
|
644
|
+
|
|
645
|
+
for ( const array of arrays ) {
|
|
646
|
+
|
|
647
|
+
result.set( array, byteOffset );
|
|
648
|
+
|
|
649
|
+
byteOffset += array.byteLength;
|
|
650
|
+
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
return result;
|
|
654
|
+
|
|
655
|
+
}
|
|
656
|
+
|
|
615
657
|
};
|
|
616
658
|
|
|
617
659
|
//
|
|
@@ -673,8 +715,6 @@ async function createDataTexture( container ) {
|
|
|
673
715
|
|
|
674
716
|
}
|
|
675
717
|
|
|
676
|
-
//
|
|
677
|
-
|
|
678
718
|
const level = container.levels[ 0 ];
|
|
679
719
|
|
|
680
720
|
let levelData;
|
|
@@ -731,7 +771,6 @@ async function createDataTexture( container ) {
|
|
|
731
771
|
view = levelData;
|
|
732
772
|
|
|
733
773
|
}
|
|
734
|
-
|
|
735
774
|
//
|
|
736
775
|
|
|
737
776
|
const texture = pixelDepth === 0
|
|
@@ -192,11 +192,6 @@ function mergeBufferGeometries( geometries, useGroups = false ) {
|
|
|
192
192
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
// gather .userData
|
|
196
|
-
|
|
197
|
-
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || [];
|
|
198
|
-
mergedGeometry.userData.mergedUserData.push( geometry.userData );
|
|
199
|
-
|
|
200
195
|
if ( useGroups ) {
|
|
201
196
|
|
|
202
197
|
let count;
|
|
@@ -371,6 +366,28 @@ function mergeBufferAttributes( attributes ) {
|
|
|
371
366
|
|
|
372
367
|
}
|
|
373
368
|
|
|
369
|
+
/**
|
|
370
|
+
* @param {BufferAttribute}
|
|
371
|
+
* @return {BufferAttribute}
|
|
372
|
+
*/
|
|
373
|
+
export function deepCloneAttribute( attribute ) {
|
|
374
|
+
|
|
375
|
+
if ( attribute.isInstancedInterleavedBufferAttribute || attribute.isInterleavedBufferAttribute ) {
|
|
376
|
+
|
|
377
|
+
return deinterleaveAttribute( attribute );
|
|
378
|
+
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if ( attribute.isInstancedBufferAttribute ) {
|
|
382
|
+
|
|
383
|
+
return new InstancedBufferAttribute().copy( attribute );
|
|
384
|
+
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return new BufferAttribute().copy( attribute );
|
|
388
|
+
|
|
389
|
+
}
|
|
390
|
+
|
|
374
391
|
/**
|
|
375
392
|
* @param {Array<BufferAttribute>} attributes
|
|
376
393
|
* @return {Array<InterleavedBufferAttribute>}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@damienmortini/three",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.173",
|
|
4
4
|
"description": "Three.js helpers",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"install": "npm run copyexamples",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"bugs": "https://github.com/damienmortini/lib/issues",
|
|
26
26
|
"homepage": "https://github.com/damienmortini/lib/tree/main/packages/three",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@damienmortini/core": "^0.2.
|
|
28
|
+
"@damienmortini/core": "^0.2.135",
|
|
29
29
|
"fs-extra": "^10.1.0",
|
|
30
|
-
"three": "0.
|
|
30
|
+
"three": "0.146.0"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "2eeafcaa9fe81bdec2dc81d847962be4a821f5eb"
|
|
33
33
|
}
|