mergeVertices static method
@param {BufferGeometry} geometry @param {number} tolerance @return {BufferGeometry>}
Implementation
static BufferGeometry mergeVertices(BufferGeometry geometry, [double tolerance = 1e-4 ]) {
tolerance = Math.max(tolerance, Math.EPSILON);
// Generate an index buffer if the geometry doesn't have one, or optimize it
// if it's already available.
Map<String,dynamic> hashToIndex = {};
final indices = geometry.getIndex();
final Float32BufferAttribute positions = geometry.getAttribute('position');
final vertexCount = indices != null? indices.count : positions.count;
// next value for triangle indices
int nextIndex = 0;
// attributes and new attribute arrays
Map<String,dynamic> attrArrays = {};
Map<String,dynamic> morphAttrsArrays = {};
final List<int> newIndices = [];
final getters = [ 'getX', 'getY', 'getZ', 'getW' ];
// initialize the arrays
for (String name in geometry.attributes.keys) {
attrArrays[ name ] = [];
final morphAttr = geometry.morphAttributes[ name ];
if (morphAttr != null) {
morphAttrsArrays[ name ] = List.filled(morphAttr.length, []);//Array( morphAttr.length ).fill().map( () => [] );
}
}
// convert the error tolerance to an amount of decimal places to truncate to
final decimalShift = Math.log10( 1 / tolerance );
final shiftMultiplier = Math.pow( 10, decimalShift );
for (int i = 0; i < vertexCount; i ++ ) {
final int index = indices != null? indices.getX(i)!.toInt() : i;
// Generate a hash for the vertex attributes at the current index 'i'
String hash = '';
for (String name in geometry.attributes.keys) {
final Float32BufferAttribute attribute = geometry.getAttribute( name );
final itemSize = attribute.itemSize;
for (int k = 0; k < itemSize; k ++ ) {
// double tilde truncates the decimal value
hash += '${_getters(attribute,index,getters[k])! * shiftMultiplier},';
}
}
// Add another reference to the vertex if it's already
// used by another index
if(hashToIndex.containsKey(hash)){
newIndices.add(hashToIndex[hash]);
}
else {
// copy data to the new index in the attribute arrays
for (String name in geometry.attributes.keys) {
final attribute = geometry.getAttribute(name);
final morphAttr = geometry.morphAttributes[name];
final itemSize = attribute.itemSize;
final newarray = attrArrays[name];
final newMorphArrays = morphAttrsArrays[name];
for ( int k = 0; k < itemSize; k ++ ) {
final getterFunc = getters[k];
newarray.add(_getters(attribute, index, getterFunc));//attribute[ getterFunc ]( index ) );
if ( morphAttr != null) {
for (int m = 0, ml = morphAttr.length; m < ml; m ++ ) {
newMorphArrays[m].add(
morphAttr[m]//[getterFunc](index)
);
}
}
}
}
hashToIndex[hash] = nextIndex;
newIndices.add(nextIndex);
nextIndex++;
}
}
// Generate typed arrays from new attribute arrays and update
// the attributeBuffers
final result = geometry.clone();
for (String name in geometry.attributes.keys) {
final Float32BufferAttribute oldAttribute = geometry.getAttribute(name);
final Float32Array buffer = oldAttribute.array;
final attribute = Float32BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
result.setAttribute(name, attribute);
// Update the attribute arrays
if (morphAttrsArrays.containsKey(name)) {
for (int j = 0; j < morphAttrsArrays[ name ].length; j ++ ) {
final oldMorphAttribute = geometry.morphAttributes[name]![j];
final Float32Array buffer = oldMorphAttribute.array as Float32Array;//.constructor( morphAttrsArrays[ name ][ j ] );
final morphAttribute = Float32BufferAttribute( buffer, oldMorphAttribute.itemSize, oldMorphAttribute.normalized );
result.morphAttributes[name]![j] = morphAttribute;
}
}
}
// indices
result.setIndex( newIndices );
return result;
}