"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class PLYExporter {
  parse(object, onDone, options) {
    if (onDone && typeof onDone === "object") {
      console.warn(
        'THREE.PLYExporter: The options parameter is now the third argument to the "parse" function. See the documentation for the new API.'
      );
      options = onDone;
      onDone = void 0;
    }
    const defaultOptions = {
      binary: false,
      excludeAttributes: [],
      // normal, uv, color, index
      littleEndian: false
    };
    options = Object.assign(defaultOptions, options);
    const excludeAttributes = options.excludeAttributes;
    let includeNormals = false;
    let includeColors = false;
    let includeUVs = false;
    let vertexCount = 0;
    let faceCount = 0;
    object.traverse(function(child) {
      if (child instanceof THREE.Mesh && child.isMesh) {
        const mesh = child;
        const geometry = mesh.geometry;
        if (!geometry.isBufferGeometry) {
          throw new Error("THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.");
        }
        const vertices = geometry.getAttribute("position");
        const normals = geometry.getAttribute("normal");
        const uvs = geometry.getAttribute("uv");
        const colors = geometry.getAttribute("color");
        const indices = geometry.getIndex();
        if (vertices === void 0) {
          return;
        }
        vertexCount += vertices.count;
        faceCount += indices ? indices.count / 3 : vertices.count / 3;
        if (normals !== void 0)
          includeNormals = true;
        if (uvs !== void 0)
          includeUVs = true;
        if (colors !== void 0)
          includeColors = true;
      }
    });
    const includeIndices = (excludeAttributes == null ? void 0 : excludeAttributes.indexOf("index")) === -1;
    includeNormals = includeNormals && (excludeAttributes == null ? void 0 : excludeAttributes.indexOf("normal")) === -1;
    includeColors = includeColors && (excludeAttributes == null ? void 0 : excludeAttributes.indexOf("color")) === -1;
    includeUVs = includeUVs && (excludeAttributes == null ? void 0 : excludeAttributes.indexOf("uv")) === -1;
    if (includeIndices && faceCount !== Math.floor(faceCount)) {
      console.error(
        "PLYExporter: Failed to generate a valid PLY file with triangle indices because the number of indices is not divisible by 3."
      );
      return null;
    }
    const indexByteCount = 4;
    let header = `ply
format ${options.binary ? options.littleEndian ? "binary_little_endian" : "binary_big_endian" : "ascii"} 1.0
element vertex ${vertexCount}
property float x
property float y
property float z
`;
    if (includeNormals) {
      header += "property float nx\nproperty float ny\nproperty float nz\n";
    }
    if (includeUVs) {
      header += "property float s\nproperty float t\n";
    }
    if (includeColors) {
      header += "property uchar red\nproperty uchar green\nproperty uchar blue\n";
    }
    if (includeIndices) {
      header += `${`element face ${faceCount}
`}property list uchar int vertex_index
`;
    }
    header += "end_header\n";
    const vertex = new THREE.Vector3();
    const normalMatrixWorld = new THREE.Matrix3();
    let result = null;
    if (options.binary) {
      const headerBin = new TextEncoder().encode(header);
      const vertexListLength = vertexCount * (4 * 3 + (includeNormals ? 4 * 3 : 0) + (includeColors ? 3 : 0) + (includeUVs ? 4 * 2 : 0));
      const faceListLength = includeIndices ? faceCount * (indexByteCount * 3 + 1) : 0;
      const output = new DataView(new ArrayBuffer(headerBin.length + vertexListLength + faceListLength));
      new Uint8Array(output.buffer).set(headerBin, 0);
      let vOffset = headerBin.length;
      let fOffset = headerBin.length + vertexListLength;
      let writtenVertices = 0;
      this.traverseMeshes(object, function(mesh, geometry) {
        const vertices = geometry.getAttribute("position");
        const normals = geometry.getAttribute("normal");
        const uvs = geometry.getAttribute("uv");
        const colors = geometry.getAttribute("color");
        const indices = geometry.getIndex();
        normalMatrixWorld.getNormalMatrix(mesh.matrixWorld);
        for (let i = 0, l = vertices.count; i < l; i++) {
          vertex.x = vertices.getX(i);
          vertex.y = vertices.getY(i);
          vertex.z = vertices.getZ(i);
          vertex.applyMatrix4(mesh.matrixWorld);
          output.setFloat32(vOffset, vertex.x, options.littleEndian);
          vOffset += 4;
          output.setFloat32(vOffset, vertex.y, options.littleEndian);
          vOffset += 4;
          output.setFloat32(vOffset, vertex.z, options.littleEndian);
          vOffset += 4;
          if (includeNormals) {
            if (normals != null) {
              vertex.x = normals.getX(i);
              vertex.y = normals.getY(i);
              vertex.z = normals.getZ(i);
              vertex.applyMatrix3(normalMatrixWorld).normalize();
              output.setFloat32(vOffset, vertex.x, options.littleEndian);
              vOffset += 4;
              output.setFloat32(vOffset, vertex.y, options.littleEndian);
              vOffset += 4;
              output.setFloat32(vOffset, vertex.z, options.littleEndian);
              vOffset += 4;
            } else {
              output.setFloat32(vOffset, 0, options.littleEndian);
              vOffset += 4;
              output.setFloat32(vOffset, 0, options.littleEndian);
              vOffset += 4;
              output.setFloat32(vOffset, 0, options.littleEndian);
              vOffset += 4;
            }
          }
          if (includeUVs) {
            if (uvs != null) {
              output.setFloat32(vOffset, uvs.getX(i), options.littleEndian);
              vOffset += 4;
              output.setFloat32(vOffset, uvs.getY(i), options.littleEndian);
              vOffset += 4;
            } else if (!includeUVs) {
              output.setFloat32(vOffset, 0, options.littleEndian);
              vOffset += 4;
              output.setFloat32(vOffset, 0, options.littleEndian);
              vOffset += 4;
            }
          }
          if (includeColors) {
            if (colors != null) {
              output.setUint8(vOffset, Math.floor(colors.getX(i) * 255));
              vOffset += 1;
              output.setUint8(vOffset, Math.floor(colors.getY(i) * 255));
              vOffset += 1;
              output.setUint8(vOffset, Math.floor(colors.getZ(i) * 255));
              vOffset += 1;
            } else {
              output.setUint8(vOffset, 255);
              vOffset += 1;
              output.setUint8(vOffset, 255);
              vOffset += 1;
              output.setUint8(vOffset, 255);
              vOffset += 1;
            }
          }
        }
        if (includeIndices) {
          if (indices !== null) {
            for (let i = 0, l = indices.count; i < l; i += 3) {
              output.setUint8(fOffset, 3);
              fOffset += 1;
              output.setUint32(fOffset, indices.getX(i + 0) + writtenVertices, options.littleEndian);
              fOffset += indexByteCount;
              output.setUint32(fOffset, indices.getX(i + 1) + writtenVertices, options.littleEndian);
              fOffset += indexByteCount;
              output.setUint32(fOffset, indices.getX(i + 2) + writtenVertices, options.littleEndian);
              fOffset += indexByteCount;
            }
          } else {
            for (let i = 0, l = vertices.count; i < l; i += 3) {
              output.setUint8(fOffset, 3);
              fOffset += 1;
              output.setUint32(fOffset, writtenVertices + i, options.littleEndian);
              fOffset += indexByteCount;
              output.setUint32(fOffset, writtenVertices + i + 1, options.littleEndian);
              fOffset += indexByteCount;
              output.setUint32(fOffset, writtenVertices + i + 2, options.littleEndian);
              fOffset += indexByteCount;
            }
          }
        }
        writtenVertices += vertices.count;
      });
      result = output.buffer;
    } else {
      let writtenVertices = 0;
      let vertexList = "";
      let faceList = "";
      this.traverseMeshes(object, function(mesh, geometry) {
        const vertices = geometry.getAttribute("position");
        const normals = geometry.getAttribute("normal");
        const uvs = geometry.getAttribute("uv");
        const colors = geometry.getAttribute("color");
        const indices = geometry.getIndex();
        normalMatrixWorld.getNormalMatrix(mesh.matrixWorld);
        for (let i = 0, l = vertices.count; i < l; i++) {
          vertex.x = vertices.getX(i);
          vertex.y = vertices.getY(i);
          vertex.z = vertices.getZ(i);
          vertex.applyMatrix4(mesh.matrixWorld);
          let line = vertex.x + " " + vertex.y + " " + vertex.z;
          if (includeNormals) {
            if (normals != null) {
              vertex.x = normals.getX(i);
              vertex.y = normals.getY(i);
              vertex.z = normals.getZ(i);
              vertex.applyMatrix3(normalMatrixWorld).normalize();
              line += " " + vertex.x + " " + vertex.y + " " + vertex.z;
            } else {
              line += " 0 0 0";
            }
          }
          if (includeUVs) {
            if (uvs != null) {
              line += " " + uvs.getX(i) + " " + uvs.getY(i);
            } else if (includeUVs) {
              line += " 0 0";
            }
          }
          if (includeColors) {
            if (colors != null) {
              line += " " + Math.floor(colors.getX(i) * 255) + " " + Math.floor(colors.getY(i) * 255) + " " + Math.floor(colors.getZ(i) * 255);
            } else {
              line += " 255 255 255";
            }
          }
          vertexList += line + "\n";
        }
        if (includeIndices) {
          if (indices !== null) {
            for (let i = 0, l = indices.count; i < l; i += 3) {
              faceList += `3 ${indices.getX(i + 0) + writtenVertices}`;
              faceList += ` ${indices.getX(i + 1) + writtenVertices}`;
              faceList += ` ${indices.getX(i + 2) + writtenVertices}
`;
            }
          } else {
            for (let i = 0, l = vertices.count; i < l; i += 3) {
              faceList += `3 ${writtenVertices + i} ${writtenVertices + i + 1} ${writtenVertices + i + 2}
`;
            }
          }
          faceCount += indices ? indices.count / 3 : vertices.count / 3;
        }
        writtenVertices += vertices.count;
      });
      result = `${header}${vertexList}${includeIndices ? `${faceList}
` : "\n"}`;
    }
    if (typeof onDone === "function") {
      requestAnimationFrame(() => onDone && onDone(typeof result === "string" ? result : ""));
    }
    return result;
  }
  // Iterate over the valid meshes in the object
  traverseMeshes(object, cb) {
    object.traverse(function(child) {
      if (child instanceof THREE.Mesh && child.isMesh) {
        const mesh = child;
        const geometry = mesh.geometry;
        if (!geometry.isBufferGeometry) {
          throw new Error("THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.");
        }
        if (geometry.hasAttribute("position")) {
          cb(mesh, geometry);
        }
      }
    });
  }
}
exports.PLYExporter = PLYExporter;
//# sourceMappingURL=PLYExporter.cjs.map
