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 = BufferGeometry();
  if (geoNode["attrName"] != null) geo.name = geoNode["attrName"];

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

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

  positionAttribute.applyMatrix4(preTransform);

  geo.setAttribute('position', positionAttribute);

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

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

    geo.setAttribute(
        'skinWeight',
        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 = Matrix3().getNormalMatrix(preTransform);

    var normalAttribute = 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}';

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

    geo.setAttribute(name, 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.isNotEmpty) {
      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.isEmpty) {
      geo.addGroup(0, buffers["materialIndex"].length, buffers["materialIndex"][0].toInt());
    }
  }

  addMorphTargets(geo, geoNode, morphTargets, preTransform);

  return geo;
}