All files / engine/Source/Scene getMeshPrimitives.js

95.45% Statements 21/22
94.11% Branches 16/17
100% Functions 1/1
95.45% Lines 21/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73                          1724x 1724x 1724x   1724x 1718x               6x 6x 6x   18x 18x       18x           18x         17x   1x     17x 33x       33x       4x     29x     13x     1x      
import addAllToArray from "../Core/addAllToArray.js";
import defined from "../Core/defined.js";
import Frozen from "../Core/Frozen.js";
import WebGLConstants from "../Core/WebGLConstants.js";
 
/**
 * Get an array of primitives for a given mesh. If the EXT_mesh_primitive_restart extension is present, use it to combine groups of primitives.
 * If the extension is not present or its spec is violated, return the original mesh.primitives.
 * @param {object} mesh A mesh from the glTF meshes array
 * @returns {object[]} An array of mesh primitives
 * @private
 */
function getMeshPrimitives(mesh) {
  const meshExtensions = mesh.extensions ?? Frozen.EMPTY_OBJECT;
  const primitiveRestartExtension = meshExtensions.EXT_mesh_primitive_restart;
  const meshPrimitives = mesh.primitives;
 
  if (!defined(primitiveRestartExtension)) {
    return meshPrimitives;
  }
 
  // Note: per the spec, any violation of the extension's specification should cause us to fall back to mesh.primitives, if detecting the violation is feasible.
 
  // Start with a copy of mesh.primitives. For each group, replace the first primitive in the group with a primitive representing the entire group,
  // and set the rest of the primitives in the group to `undefined`.
  // This allows us to identify which remaining primitives do not use primitive restart, and any errors involving a primitive appearing in more than one group.
  const primitives = [];
  addAllToArray(primitives, meshPrimitives);
  for (const group of primitiveRestartExtension.primitiveGroups) {
    // Spec: the group must not be empty and all indices must be valid array indices into mesh.primitives.
    const firstPrimitiveIndex = group.primitives[0];
    Iif (!defined(firstPrimitiveIndex) || !meshPrimitives[firstPrimitiveIndex]) {
      return meshPrimitives;
    }
 
    const primitive = {
      ...meshPrimitives[firstPrimitiveIndex],
      indices: group.indices,
    };
 
    // Spec: primitive restart only supported for these topologies.
    switch (primitive.mode) {
      case WebGLConstants.TRIANGLE_FAN:
      case WebGLConstants.TRIANGLE_STRIP:
      case WebGLConstants.LINE_STRIP:
      case WebGLConstants.LINE_LOOP:
        break;
      default:
        return meshPrimitives;
    }
 
    for (const primitiveIndex of group.primitives) {
      const thisPrimitive = primitives[primitiveIndex];
 
      // Spec: all primitives must use indexed geometry and a given primitive may appear in at most one group.
      // Spec: all primitives must have same topology.
      if (
        !defined(thisPrimitive?.indices) ||
        thisPrimitive.mode !== primitive.mode
      ) {
        return meshPrimitives;
      }
 
      primitives[primitiveIndex] = undefined;
    }
 
    primitives[firstPrimitiveIndex] = primitive;
  }
 
  return primitives.filter(defined);
}
export default getMeshPrimitives;