mergeVertices static method

BufferGeometry mergeVertices(
  1. BufferGeometry geometry, [
  2. double tolerance = 1e-4
])

@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;
}