assignFinalMaterial method

dynamic assignFinalMaterial(
  1. dynamic mesh
)

Assigns final material to a Mesh, Line, or Points instance. The instance already has a material (generated from the glTF material options alone) but reuse of the same glTF material may require multiple threejs materials to accomodate different primitive types, defines, etc. New materials will be created if necessary, and reused from a cache. @param {Object3D} mesh Mesh, Line, or Points instance.

Implementation

assignFinalMaterial(mesh) {
  var geometry = mesh.geometry;
  var material = mesh.material;

  bool useVertexTangents = geometry.attributes["tangent"] != null;
  bool useVertexColors = geometry.attributes["color"] != null;
  bool useFlatShading = geometry.attributes["normal"] == null;

  if (mesh is Points) {
    var cacheKey = 'PointsMaterial: ${material.uuid}';

    var pointsMaterial = cache.get(cacheKey);

    if (pointsMaterial == null) {
      pointsMaterial = PointsMaterial({});
      pointsMaterial.copy(material);
      pointsMaterial.color.copy(material.color);
      pointsMaterial.map = material.map;
      pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px

      cache.add(cacheKey, pointsMaterial);
    }

    material = pointsMaterial;
  } else if (mesh is Line) {
    var cacheKey = 'LineBasicMaterial: ${material.uuid}';

    var lineMaterial = cache.get(cacheKey);

    if (lineMaterial == null) {
      lineMaterial = LineBasicMaterial({});
      lineMaterial.copy(material);
      lineMaterial.color.copy(material.color);

      cache.add(cacheKey, lineMaterial);
    }

    material = lineMaterial;
  }

  // Clone the material if it will be modified
  if (useVertexTangents || useVertexColors || useFlatShading) {
    var cacheKey = 'ClonedMaterial: ${material.uuid}:';

    if (material.type == "GLTFSpecularGlossinessMaterial") cacheKey += 'specular-glossiness:';
    if (useVertexTangents) cacheKey += 'vertex-tangents:';
    if (useVertexColors) cacheKey += 'vertex-colors:';
    if (useFlatShading) cacheKey += 'flat-shading:';

    var cachedMaterial = cache.get(cacheKey);

    if (cachedMaterial == null) {
      cachedMaterial = material.clone();

      if (useVertexTangents) cachedMaterial.vertexTangents = true;
      if (useVertexColors) cachedMaterial.vertexColors = true;
      if (useFlatShading) cachedMaterial.flatShading = true;

      cache.add(cacheKey, cachedMaterial);

      associations[cachedMaterial] = associations[material];
    }

    material = cachedMaterial;
  }

  // workarounds for mesh and geometry

  if (material.aoMap != null && geometry.attributes["uv2"] == null && geometry.attributes["uv"] != null) {
    geometry.setAttribute('uv2', geometry.attributes["uv"]);
  }

  // https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
  if (material.normalScale != null && !useVertexTangents) {
    material.normalScale.y = -material.normalScale.y;
  }

  if (material.clearcoatNormalScale != null && !useVertexTangents) {
    material.clearcoatNormalScale.y = -material.clearcoatNormalScale.y;
  }

  mesh.material = material;
}