genGeometry method

dynamic genGeometry(
  1. Map geoNode,
  2. dynamic skeleton,
  3. dynamic morphTargets,
  4. dynamic preTransform,
)

Implementation

genGeometry(Map geoNode, skeleton, morphTargets, preTransform) {
  var geo = new BufferGeometry();
  if (geoNode["attrName"] != null) geo.name = geoNode["attrName"];

  var geoInfo = this.parseGeoNode(geoNode, skeleton);
  var buffers = this.genBuffers(geoInfo);

  var positionAttribute = new Float32BufferAttribute(
      Float32Array.fromList(List<double>.from(buffers["vertex"])), 3);

  positionAttribute.applyMatrix4(preTransform);

  geo.setAttribute('position', positionAttribute);

  if (buffers["colors"].length > 0) {
    geo.setAttribute(
        'color', new Float32BufferAttribute(buffers["colors"], 3));
  }

  if (skeleton != null) {
    geo.setAttribute(
        'skinIndex',
        new Uint16BufferAttribute(
            Uint16Array.fromList(List<int>.from(buffers["weightsIndices"])),
            4));

    geo.setAttribute(
        'skinWeight',
        new Float32BufferAttribute(
            Float32Array.fromList(List<double>.from(
                buffers["vertexWeights"].map((e) => e.toDouble()))),
            4));

    // used later to bind the skeleton to the model
    geo.userData["FBX_Deformer"] = skeleton;
  }

  if (buffers["normal"].length > 0) {
    var normalMatrix = new Matrix3().getNormalMatrix(preTransform);

    var normalAttribute = new Float32BufferAttribute(
        Float32Array.fromList(List<double>.from(buffers["normal"])), 3);
    normalAttribute.applyNormalMatrix(normalMatrix);

    geo.setAttribute('normal', normalAttribute);
  }

  buffers["uvs"].asMap().forEach((i, uvBuffer) {
    // subsequent uv buffers are called 'uv1', 'uv2', ...
    var name = 'uv' + (i + 1).toString();

    // the first uv buffer is just called 'uv'
    if (i == 0) {
      name = 'uv';
    }

    geo.setAttribute(
        name,
        new Float32BufferAttribute(
            Float32Array.fromList(List<double>.from(buffers["uvs"][i])), 2));
  });

  if (geoInfo["material"] != null &&
      geoInfo["material"]["mappingType"] != 'AllSame') {
    // Convert the material indices of each vertex into rendering groups on the geometry.
    var prevMaterialIndex = buffers["materialIndex"][0];
    var startIndex = 0;

    buffers["materialIndex"].asMap().forEach((i, currentIndex) {
      if (currentIndex != prevMaterialIndex) {
        geo.addGroup(startIndex, i - startIndex, prevMaterialIndex);

        prevMaterialIndex = currentIndex;
        startIndex = i;
      }
    });

    // the loop above doesn't add the last group, do that here.
    if (geo.groups.length > 0) {
      var lastGroup = geo.groups[geo.groups.length - 1];
      var lastIndex = lastGroup["start"] + lastGroup["count"];

      if (lastIndex != buffers["materialIndex"].length) {
        geo.addGroup(lastIndex, buffers["materialIndex"].length - lastIndex,
            prevMaterialIndex);
      }
    }

    // case where there are multiple materials but the whole geometry is only
    // using one of them
    if (geo.groups.length == 0) {
      geo.addGroup(0, buffers["materialIndex"].length,
          buffers["materialIndex"][0].toInt());
    }
  }

  this.addMorphTargets(geo, geoNode, morphTargets, preTransform);

  return geo;
}