fix: cleanup
This commit is contained in:
parent
c3f71f8be1
commit
352b17071c
|
|
@ -1,6 +1,6 @@
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { exportTo3MF } from "three-3mf-exporter";
|
import { exportTo3MF } from "three-3mf-exporter";
|
||||||
import type { TraceResult, PathData } from "./image-tracer";
|
import type { TraceResult } from "./image-tracer";
|
||||||
|
|
||||||
export interface ExtrusionSettings {
|
export interface ExtrusionSettings {
|
||||||
size: number; // 模型整体尺寸 (mm)
|
size: number; // 模型整体尺寸 (mm)
|
||||||
|
|
@ -57,41 +57,13 @@ export async function generate3MF(
|
||||||
const layer = traceResult.layers.find((l) => l.id === layerSetting.id);
|
const layer = traceResult.layers.find((l) => l.id === layerSetting.id);
|
||||||
if (!layer) continue;
|
if (!layer) continue;
|
||||||
|
|
||||||
// 为该图层的所有路径创建形状
|
|
||||||
const shapes: THREE.Shape[] = [];
|
|
||||||
|
|
||||||
for (const path of layer.paths) {
|
|
||||||
if (path.points.length < 2) continue;
|
|
||||||
|
|
||||||
const shape = createShapeFromPath(path, scale, offsetX, offsetY);
|
|
||||||
if (shape) {
|
|
||||||
shapes.push(shape);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shapes.length === 0) continue;
|
|
||||||
|
|
||||||
// 创建挤压几何体
|
// 创建挤压几何体
|
||||||
const extrudeSettings: THREE.ExtrudeGeometryOptions = {
|
const extrudeSettings: THREE.ExtrudeGeometryOptions = {
|
||||||
depth: layerSetting.thickness,
|
depth: layerSetting.thickness,
|
||||||
curveSegments: 36,
|
curveSegments: 36,
|
||||||
bevelEnabled: false,
|
bevelEnabled: false,
|
||||||
};
|
};
|
||||||
|
const geometry: THREE.ExtrudeGeometry = new THREE.ExtrudeGeometry(layer.paths, extrudeSettings);
|
||||||
// 如果有多个形状,创建多个几何体并合并
|
|
||||||
const geometries: THREE.ExtrudeGeometry[] = [];
|
|
||||||
for (const shape of shapes) {
|
|
||||||
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
|
|
||||||
geometries.push(geometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 合并同一图层的几何体
|
|
||||||
let combinedGeometry;
|
|
||||||
if (geometries.length === 1) {
|
|
||||||
combinedGeometry = geometries[0];
|
|
||||||
} else {
|
|
||||||
combinedGeometry = mergeGeometries(geometries);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为该图层生成颜色
|
// 为该图层生成颜色
|
||||||
const color = generateLayerColor(layerIndex);
|
const color = generateLayerColor(layerIndex);
|
||||||
|
|
@ -101,7 +73,7 @@ export async function generate3MF(
|
||||||
roughness: 0.7,
|
roughness: 0.7,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mesh = new THREE.Mesh(combinedGeometry, material);
|
const mesh = new THREE.Mesh(geometry, material);
|
||||||
|
|
||||||
// 设置图层高度(堆叠)
|
// 设置图层高度(堆叠)
|
||||||
mesh.position.y = currentHeight;
|
mesh.position.y = currentHeight;
|
||||||
|
|
@ -134,100 +106,4 @@ export async function generate3MF(
|
||||||
});
|
});
|
||||||
|
|
||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 从路径数据创建 Three.js 形状
|
|
||||||
*/
|
|
||||||
function createShapeFromPath(
|
|
||||||
path: PathData,
|
|
||||||
scale: number,
|
|
||||||
offsetX: number,
|
|
||||||
offsetY: number
|
|
||||||
): THREE.Shape | null {
|
|
||||||
if (path.points.length < 2) return null;
|
|
||||||
|
|
||||||
const shape = new THREE.Shape();
|
|
||||||
|
|
||||||
// 移动到起点
|
|
||||||
const startPoint = path.points[0];
|
|
||||||
shape.moveTo(
|
|
||||||
(startPoint.x + offsetX) * scale,
|
|
||||||
(startPoint.y + offsetY) * scale
|
|
||||||
);
|
|
||||||
|
|
||||||
// 绘制线段到后续点
|
|
||||||
for (let i = 1; i < path.points.length; i++) {
|
|
||||||
const point = path.points[i];
|
|
||||||
shape.lineTo(
|
|
||||||
(point.x + offsetX) * scale,
|
|
||||||
(point.y + offsetY) * scale
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果是闭合路径,闭合形状
|
|
||||||
if (path.isClosed) {
|
|
||||||
shape.closePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并多个几何体
|
|
||||||
*/
|
|
||||||
function mergeGeometries(
|
|
||||||
geometries: THREE.ExtrudeGeometry[]
|
|
||||||
): THREE.ExtrudeGeometry {
|
|
||||||
const mergedGeometry = geometries[0].clone();
|
|
||||||
|
|
||||||
for (let i = 1; i < geometries.length; i++) {
|
|
||||||
const geometry = geometries[i];
|
|
||||||
|
|
||||||
const positionAttribute = geometry.getAttribute("position");
|
|
||||||
const normalAttribute = geometry.getAttribute("normal");
|
|
||||||
const uvAttribute = geometry.getAttribute("uv");
|
|
||||||
|
|
||||||
if (positionAttribute) {
|
|
||||||
const positions = mergedGeometry.getAttribute("position");
|
|
||||||
const newPositions = new Float32Array(
|
|
||||||
positions.array.length + positionAttribute.array.length
|
|
||||||
);
|
|
||||||
newPositions.set(positions.array);
|
|
||||||
newPositions.set(positionAttribute.array, positions.array.length);
|
|
||||||
mergedGeometry.setAttribute(
|
|
||||||
"position",
|
|
||||||
new THREE.BufferAttribute(newPositions, 3)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (normalAttribute) {
|
|
||||||
const normals = mergedGeometry.getAttribute("normal");
|
|
||||||
const newNormals = new Float32Array(
|
|
||||||
normals.array.length + normalAttribute.array.length
|
|
||||||
);
|
|
||||||
newNormals.set(normals.array);
|
|
||||||
newNormals.set(normalAttribute.array, normals.array.length);
|
|
||||||
mergedGeometry.setAttribute(
|
|
||||||
"normal",
|
|
||||||
new THREE.BufferAttribute(newNormals, 3)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uvAttribute) {
|
|
||||||
const uvs = mergedGeometry.getAttribute("uv");
|
|
||||||
const newUvs = new Float32Array(
|
|
||||||
uvs.array.length + uvAttribute.array.length
|
|
||||||
);
|
|
||||||
newUvs.set(uvs.array);
|
|
||||||
newUvs.set(uvAttribute.array, uvs.array.length);
|
|
||||||
mergedGeometry.setAttribute(
|
|
||||||
"uv",
|
|
||||||
new THREE.BufferAttribute(newUvs, 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mergedGeometry.computeVertexNormals();
|
|
||||||
return mergedGeometry;
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ImageTracer, type TraceData, type OutlinedArea, type SvgLineAttributes, Options } from "@image-tracer-ts/core";
|
import { ImageTracer, Options } from "@image-tracer-ts/core";
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
import {SVGLoader, SVGResult} from "three/examples/jsm/loaders/SVGLoader";
|
import {SVGLoader, SVGResult} from "three/examples/jsm/loaders/SVGLoader";
|
||||||
import {Color, ShapePath, Shape} from "three";
|
import {Color, ShapePath, Shape} from "three";
|
||||||
|
|
@ -26,12 +26,6 @@ export interface TraceResult {
|
||||||
layers: TracedLayer[];
|
layers: TracedLayer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SvgPath {
|
|
||||||
color: string;
|
|
||||||
d: string;
|
|
||||||
path: PathData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将图像转换为矢量路径
|
* 将图像转换为矢量路径
|
||||||
* @param image - 要追踪的图片元素
|
* @param image - 要追踪的图片元素
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue