three-stdlib
Version:
stand-alone library of threejs examples
282 lines (281 loc) • 11.5 kB
JavaScript
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
;