Skip to content

Commit f972284

Browse files
authored
DRACOLoader: Implement data alignment for WebGPU (#31991)
* DRACOLoader: Implement data alignment for WebGPU * clean up * fix typo
1 parent 2b5ea30 commit f972284

File tree

1 file changed

+71
-20
lines changed

1 file changed

+71
-20
lines changed

examples/jsm/loaders/DRACOLoader.js

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import {
66
FileLoader,
77
Loader,
88
LinearSRGBColorSpace,
9-
SRGBColorSpace
9+
SRGBColorSpace,
10+
InterleavedBuffer,
11+
InterleavedBufferAttribute
1012
} from 'three';
1113

1214
const _taskCache = new WeakMap();
@@ -273,16 +275,25 @@ class DRACOLoader extends Loader {
273275

274276
for ( let i = 0; i < geometryData.attributes.length; i ++ ) {
275277

276-
const result = geometryData.attributes[ i ];
277-
const name = result.name;
278-
const array = result.array;
279-
const itemSize = result.itemSize;
278+
const { name, array, itemSize, stride, vertexColorSpace } = geometryData.attributes[ i ];
280279

281-
const attribute = new BufferAttribute( array, itemSize );
280+
let attribute;
281+
282+
if ( itemSize === stride ) {
283+
284+
attribute = new BufferAttribute( array, itemSize );
285+
286+
} else {
287+
288+
const buffer = new InterleavedBuffer( array, stride );
289+
290+
attribute = new InterleavedBufferAttribute( buffer, itemSize, 0 );
291+
292+
}
282293

283294
if ( name === 'color' ) {
284295

285-
this._assignVertexColorSpace( attribute, result.vertexColorSpace );
296+
this._assignVertexColorSpace( attribute, vertexColorSpace );
286297

287298
attribute.normalized = ( array instanceof Float32Array ) === false;
288299

@@ -646,30 +657,70 @@ function DRACOWorker() {
646657

647658
}
648659

649-
function decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) {
660+
function decodeAttribute( draco, decoder, dracoGeometry, attributeName, TypedArray, attribute ) {
650661

651-
const numComponents = attribute.num_components();
652-
const numPoints = dracoGeometry.num_points();
653-
const numValues = numPoints * numComponents;
654-
const byteLength = numValues * attributeType.BYTES_PER_ELEMENT;
655-
const dataType = getDracoDataType( draco, attributeType );
662+
const count = dracoGeometry.num_points();
663+
const itemSize = attribute.num_components();
664+
const dracoDataType = getDracoDataType( draco, TypedArray );
665+
666+
// Reference: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#data-alignment
667+
const srcByteStride = itemSize * TypedArray.BYTES_PER_ELEMENT;
668+
const dstByteStride = Math.ceil( srcByteStride / 4 ) * 4;
669+
670+
const dstStride = dstByteStride / TypedArray.BYTES_PER_ELEMENT
671+
672+
const srcByteLength = count * srcByteStride;
673+
const dstByteLength = count * dstByteStride;
674+
675+
const ptr = draco._malloc( srcByteLength );
676+
decoder.GetAttributeDataArrayForAllPoints( dracoGeometry, attribute, dracoDataType, srcByteLength, ptr );
677+
678+
const srcArray = new TypedArray( draco.HEAPF32.buffer, ptr, srcByteLength / TypedArray.BYTES_PER_ELEMENT );
679+
let dstArray;
680+
681+
if ( srcByteStride === dstByteStride ) {
682+
683+
// THREE.BufferAttribute
684+
685+
dstArray = srcArray.slice();
686+
687+
} else {
688+
689+
// THREE.InterleavedBufferAttribute
690+
691+
dstArray = new TypedArray( dstByteLength / TypedArray.BYTES_PER_ELEMENT );
692+
693+
let dstOffset = 0
694+
695+
for ( let i = 0, il = srcArray.length; i < il; i++ ) {
696+
697+
for ( let j = 0; j < itemSize; j++ ) {
698+
699+
dstArray[ dstOffset + j ] = srcArray[ i * itemSize + j ]
700+
701+
}
702+
703+
dstOffset += dstStride;
704+
705+
}
706+
707+
}
656708

657-
const ptr = draco._malloc( byteLength );
658-
decoder.GetAttributeDataArrayForAllPoints( dracoGeometry, attribute, dataType, byteLength, ptr );
659-
const array = new attributeType( draco.HEAPF32.buffer, ptr, numValues ).slice();
660709
draco._free( ptr );
661710

662711
return {
663712
name: attributeName,
664-
array: array,
665-
itemSize: numComponents
713+
count: count,
714+
itemSize: itemSize,
715+
array: dstArray,
716+
stride: dstStride
666717
};
667718

668719
}
669720

670-
function getDracoDataType( draco, attributeType ) {
721+
function getDracoDataType( draco, TypedArray ) {
671722

672-
switch ( attributeType ) {
723+
switch ( TypedArray ) {
673724

674725
case Float32Array: return draco.DT_FLOAT32;
675726
case Int8Array: return draco.DT_INT8;

0 commit comments

Comments
 (0)