|
@@ -5,7 +5,6 @@ import {
|
|
|
InstancedBufferAttribute,
|
|
|
InterleavedBuffer,
|
|
|
InterleavedBufferAttribute,
|
|
|
- MathUtils,
|
|
|
TriangleFanDrawMode,
|
|
|
TriangleStripDrawMode,
|
|
|
TrianglesDrawMode,
|
|
@@ -36,17 +35,16 @@ function computeMikkTSpaceTangents( geometry, MikkTSpace, negateSign = true ) {
|
|
|
|
|
|
if ( attribute.normalized || attribute.isInterleavedBufferAttribute ) {
|
|
|
|
|
|
- const srcArray = attribute.isInterleavedBufferAttribute ? attribute.data.array : attribute.array;
|
|
|
const dstArray = new Float32Array( attribute.getCount() * attribute.itemSize );
|
|
|
|
|
|
for ( let i = 0, j = 0; i < attribute.getCount(); i ++ ) {
|
|
|
|
|
|
- dstArray[ j ++ ] = MathUtils.denormalize( attribute.getX( i ), srcArray );
|
|
|
- dstArray[ j ++ ] = MathUtils.denormalize( attribute.getY( i ), srcArray );
|
|
|
+ dstArray[ j ++ ] = attribute.getX( i );
|
|
|
+ dstArray[ j ++ ] = attribute.getY( i );
|
|
|
|
|
|
if ( attribute.itemSize > 2 ) {
|
|
|
|
|
|
- dstArray[ j ++ ] = MathUtils.denormalize( attribute.getZ( i ), srcArray );
|
|
|
+ dstArray[ j ++ ] = attribute.getZ( i );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -573,22 +571,33 @@ function mergeVertices( geometry, tolerance = 1e-4 ) {
|
|
|
|
|
|
// attributes and new attribute arrays
|
|
|
const attributeNames = Object.keys( geometry.attributes );
|
|
|
- const attrArrays = {};
|
|
|
- const morphAttrsArrays = {};
|
|
|
+ const tmpAttributes = {};
|
|
|
+ const tmpMorphAttributes = {};
|
|
|
const newIndices = [];
|
|
|
const getters = [ 'getX', 'getY', 'getZ', 'getW' ];
|
|
|
+ const setters = [ 'setX', 'setY', 'setZ', 'setW' ];
|
|
|
|
|
|
- // initialize the arrays
|
|
|
+ // Initialize the arrays, allocating space conservatively. Extra
|
|
|
+ // space will be trimmed in the last step.
|
|
|
for ( let i = 0, l = attributeNames.length; i < l; i ++ ) {
|
|
|
|
|
|
const name = attributeNames[ i ];
|
|
|
+ const attr = geometry.attributes[ name ];
|
|
|
|
|
|
- attrArrays[ name ] = [];
|
|
|
+ tmpAttributes[ name ] = new BufferAttribute(
|
|
|
+ new attr.array.constructor( attr.count * attr.itemSize ),
|
|
|
+ attr.itemSize,
|
|
|
+ attr.normalized
|
|
|
+ );
|
|
|
|
|
|
const morphAttr = geometry.morphAttributes[ name ];
|
|
|
if ( morphAttr ) {
|
|
|
|
|
|
- morphAttrsArrays[ name ] = new Array( morphAttr.length ).fill().map( () => [] );
|
|
|
+ tmpMorphAttributes[ name ] = new BufferAttribute(
|
|
|
+ new morphAttr.array.constructor( morphAttr.count * morphAttr.itemSize ),
|
|
|
+ morphAttr.itemSize,
|
|
|
+ morphAttr.normalized
|
|
|
+ );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -626,26 +635,27 @@ function mergeVertices( geometry, tolerance = 1e-4 ) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- // copy data to the new index in the attribute arrays
|
|
|
+ // copy data to the new index in the temporary attributes
|
|
|
for ( let j = 0, l = attributeNames.length; j < l; j ++ ) {
|
|
|
|
|
|
const name = attributeNames[ j ];
|
|
|
const attribute = geometry.getAttribute( name );
|
|
|
const morphAttr = geometry.morphAttributes[ name ];
|
|
|
const itemSize = attribute.itemSize;
|
|
|
- const newarray = attrArrays[ name ];
|
|
|
- const newMorphArrays = morphAttrsArrays[ name ];
|
|
|
+ const newarray = tmpAttributes[ name ];
|
|
|
+ const newMorphArrays = tmpMorphAttributes[ name ];
|
|
|
|
|
|
for ( let k = 0; k < itemSize; k ++ ) {
|
|
|
|
|
|
const getterFunc = getters[ k ];
|
|
|
- newarray.push( attribute[ getterFunc ]( index ) );
|
|
|
+ const setterFunc = setters[ k ];
|
|
|
+ newarray[ setterFunc ]( nextIndex, attribute[ getterFunc ]( index ) );
|
|
|
|
|
|
if ( morphAttr ) {
|
|
|
|
|
|
for ( let m = 0, ml = morphAttr.length; m < ml; m ++ ) {
|
|
|
|
|
|
- newMorphArrays[ m ].push( morphAttr[ m ][ getterFunc ]( index ) );
|
|
|
+ newMorphArrays[ m ][ setterFunc ]( nextIndex, morphAttr[ m ][ getterFunc ]( index ) );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -663,31 +673,29 @@ function mergeVertices( geometry, tolerance = 1e-4 ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- // Generate typed arrays from new attribute arrays and update
|
|
|
- // the attributeBuffers
|
|
|
+ // generate result BufferGeometry
|
|
|
const result = geometry.clone();
|
|
|
- for ( let i = 0, l = attributeNames.length; i < l; i ++ ) {
|
|
|
-
|
|
|
- const name = attributeNames[ i ];
|
|
|
- const oldAttribute = geometry.getAttribute( name );
|
|
|
-
|
|
|
- const buffer = new oldAttribute.array.constructor( attrArrays[ name ] );
|
|
|
- const attribute = new BufferAttribute( buffer, oldAttribute.itemSize, oldAttribute.normalized );
|
|
|
+ for ( const name in geometry.attributes ) {
|
|
|
|
|
|
- result.setAttribute( name, attribute );
|
|
|
+ const tmpAttribute = tmpAttributes[ name ];
|
|
|
|
|
|
- // Update the attribute arrays
|
|
|
- if ( name in morphAttrsArrays ) {
|
|
|
+ result.setAttribute( name, new BufferAttribute(
|
|
|
+ tmpAttribute.array.slice( 0, nextIndex * tmpAttribute.itemSize ),
|
|
|
+ tmpAttribute.itemSize,
|
|
|
+ tmpAttribute.normalized,
|
|
|
+ ) );
|
|
|
|
|
|
- for ( let j = 0; j < morphAttrsArrays[ name ].length; j ++ ) {
|
|
|
+ if ( ! ( name in tmpMorphAttributes ) ) continue;
|
|
|
|
|
|
- const oldMorphAttribute = geometry.morphAttributes[ name ][ j ];
|
|
|
+ for ( let j = 0; j < tmpMorphAttributes[ name ].length; j ++ ) {
|
|
|
|
|
|
- const buffer = new oldMorphAttribute.array.constructor( morphAttrsArrays[ name ][ j ] );
|
|
|
- const morphAttribute = new BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized );
|
|
|
- result.morphAttributes[ name ][ j ] = morphAttribute;
|
|
|
+ const tmpMorphAttribute = tmpMorphAttributes[ name ][ j ];
|
|
|
|
|
|
- }
|
|
|
+ result.morphAttributes[ name ][ j ] = new BufferAttribute(
|
|
|
+ tmpMorphAttribute.array.slice( 0, nextIndex * tmpMorphAttribute.itemSize ),
|
|
|
+ tmpMorphAttribute.itemSize,
|
|
|
+ tmpMorphAttribute.normalized,
|
|
|
+ );
|
|
|
|
|
|
}
|
|
|
|