Buckets:
| import { Mesh, Vector3, Matrix3 } from "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 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 Vector3(); | |
| const normalMatrixWorld = new 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 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); | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| export { | |
| PLYExporter | |
| }; | |
| //# sourceMappingURL=PLYExporter.js.map | |
Xet Storage Details
- Size:
- 11.4 kB
- Xet hash:
- 646f7d923e4cece2ee49b2d77bbfa3f14116434557caa1ea48381e55fc6ca1c8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.