Complete 3axis tutorial native and Web/WASM parity tools
This commit is contained in:
@@ -2,7 +2,7 @@ import { useEffect, useRef } from "react";
|
||||
import * as THREE from "three";
|
||||
|
||||
type ViewMode = "z" | "z2" | "x" | "y" | "y2" | "p";
|
||||
type Segment = { start?: Record<string, number>; end?: Record<string, number> };
|
||||
type Segment = { id?: number; source_line?: number | null; active?: boolean; rapid?: boolean; start?: Record<string, number>; end?: Record<string, number> };
|
||||
type Props = { axes: number[]; view?: ViewMode; zoom?: number; rotateMode?: boolean; segments?: Segment[]; showGrid?: boolean; showTool?: boolean; showPath?: boolean; showLive?: boolean; showLimits?: boolean; showVelocity?: boolean; showOffsets?: boolean; showExtents?: boolean };
|
||||
|
||||
export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = false, segments = [], showGrid = true, showTool = true, showPath = true, showLive = true, showLimits = false, showVelocity = false, showOffsets = false, showExtents = false }: Props) {
|
||||
@@ -36,15 +36,32 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals
|
||||
grid.name = "axis-grid";
|
||||
scene.add(grid);
|
||||
scene.add(new THREE.AxesHelper(2.2));
|
||||
const table = new THREE.Mesh(new THREE.BoxGeometry(5.2, 0.18, 3.6), new THREE.MeshStandardMaterial({ color: 0x263740, roughness: 0.8 }));
|
||||
table.position.y = -0.1;
|
||||
scene.add(table);
|
||||
const gantry = new THREE.Mesh(new THREE.BoxGeometry(0.18, 2.2, 0.18), new THREE.MeshStandardMaterial({ color: 0x647c88 }));
|
||||
gantry.position.set(0, 1, 0);
|
||||
scene.add(gantry);
|
||||
const tool = new THREE.Mesh(new THREE.ConeGeometry(0.12, 0.55, 16), new THREE.MeshStandardMaterial({ color: 0xc9e86d, emissive: 0x243200 }));
|
||||
scene.add(tool);
|
||||
const machine = new THREE.Group();
|
||||
machine.name = "axis-3axis-tutorial-model";
|
||||
const frameMaterial = new THREE.MeshStandardMaterial({ color: 0x7d8b91, roughness: 0.82 });
|
||||
const xMaterial = new THREE.MeshStandardMaterial({ color: 0x3d6fc4, roughness: 0.72 });
|
||||
const yMaterial = new THREE.MeshStandardMaterial({ color: 0x3f9b69, roughness: 0.72 });
|
||||
const zMaterial = new THREE.MeshStandardMaterial({ color: 0xd3ba45, roughness: 0.7 });
|
||||
const toolMaterial = new THREE.MeshStandardMaterial({ color: 0xc9e86d, emissive: 0x243200 });
|
||||
const sourceScale = 0.01;
|
||||
const frameAssembly = new THREE.Group(); frameAssembly.name = "frame"; machine.add(frameAssembly);
|
||||
const base = new THREE.Mesh(new THREE.BoxGeometry(2, 0.2, 5.6), frameMaterial); base.position.set(0, -0.1, 0); frameAssembly.add(base);
|
||||
const column = new THREE.Mesh(new THREE.BoxGeometry(1.2, 4, 0.6), frameMaterial); column.position.set(0, 2, -2.3); frameAssembly.add(column);
|
||||
const top = new THREE.Mesh(new THREE.BoxGeometry(1.6, 0.4, 1.2), frameMaterial); top.position.set(0, 4.2, -2.2); frameAssembly.add(top);
|
||||
const yAssembly = new THREE.Group(); yAssembly.name = "yassembly"; machine.add(yAssembly);
|
||||
const yBase = new THREE.Mesh(new THREE.BoxGeometry(2, 0.1, 2), yMaterial); yBase.position.set(0, 0.25, 0); yAssembly.add(yBase);
|
||||
const xAssembly = new THREE.Group(); xAssembly.name = "xassembly"; yAssembly.add(xAssembly);
|
||||
const xBase = new THREE.Mesh(new THREE.BoxGeometry(10, 0.3, 2), xMaterial); xBase.position.set(0, 0.35, 0); xAssembly.add(xBase);
|
||||
const work = new THREE.Mesh(new THREE.BoxGeometry(1.4, 0.12, 1.2), new THREE.MeshStandardMaterial({ color: 0x8f9da4, roughness: 0.9 }));
|
||||
work.position.set(0, 0.56, 0); xAssembly.add(work);
|
||||
const zAssembly = new THREE.Group(); zAssembly.name = "zassembly"; machine.add(zAssembly);
|
||||
const zBody = new THREE.Mesh(new THREE.BoxGeometry(0.6, 1.0, 0.9), zMaterial); zBody.position.set(0, 3.4, 0); zAssembly.add(zBody);
|
||||
const spindle = new THREE.Mesh(new THREE.CylinderGeometry(0.3, 0.3, 1.0, 24), zMaterial); spindle.position.set(0, 2.9, 0); zAssembly.add(spindle);
|
||||
const cat30 = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.3, 0.35, 20), new THREE.MeshStandardMaterial({ color: 0xd15a52 })); cat30.position.set(0, 2.35, 0); zAssembly.add(cat30);
|
||||
const tool = new THREE.Mesh(new THREE.ConeGeometry(0.12, 0.8, 16), toolMaterial); tool.position.set(0, 1.85, 0); zAssembly.add(tool);
|
||||
scene.add(machine);
|
||||
const pathGroup = new THREE.Group(); pathGroup.name = "axis-toolpath"; scene.add(pathGroup);
|
||||
const livePathGroup = new THREE.Group(); livePathGroup.name = "axis-live-toolpath"; scene.add(livePathGroup);
|
||||
const overlayGroup = new THREE.Group(); overlayGroup.name = "axis-overlays"; scene.add(overlayGroup);
|
||||
const ambient = new THREE.HemisphereLight(0xc8e4ec, 0x111820, 1.8);
|
||||
scene.add(ambient);
|
||||
@@ -65,16 +82,34 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals
|
||||
let frame = 0;
|
||||
const render = () => {
|
||||
const [x = 0, y = 0, z = 0] = axesRef.current;
|
||||
tool.position.set(THREE.MathUtils.clamp(Number(x) || 0, -2.3, 2.3), 0.35 + THREE.MathUtils.clamp(Number(z) || 0, -1, 2), THREE.MathUtils.clamp(Number(y) || 0, -1.4, 1.4));
|
||||
const bounds = segmentsRef.current.reduce((box, segment) => {
|
||||
for (const point of [segment.start ?? {}, segment.end ?? {}]) {
|
||||
for (const axis of ["x", "y", "z"] as const) {
|
||||
const value = Number(point[axis] ?? 0);
|
||||
if (Number.isFinite(value)) { box.min[axis] = Math.min(box.min[axis], value); box.max[axis] = Math.max(box.max[axis], value); }
|
||||
}
|
||||
}
|
||||
return box;
|
||||
}, { min: { x: 0, y: 0, z: 0 }, max: { x: 0, y: 0, z: 0 } });
|
||||
const span = Math.max(bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, bounds.max.z - bounds.min.z, 1);
|
||||
const scale = Math.min(0.12, 4.2 / span);
|
||||
const center = { x: (bounds.min.x + bounds.max.x) / 2, y: (bounds.min.y + bounds.max.y) / 2, z: (bounds.min.z + bounds.max.z) / 2 };
|
||||
xAssembly.position.x = Number(x || 0) * sourceScale;
|
||||
yAssembly.position.z = Number(y || 0) * sourceScale;
|
||||
zAssembly.position.y = Number(z || 0) * sourceScale;
|
||||
grid.visible = layersRef.current.showGrid;
|
||||
tool.visible = layersRef.current.showTool;
|
||||
pathGroup.visible = layersRef.current.showPath || layersRef.current.showLive;
|
||||
pathGroup.visible = layersRef.current.showPath;
|
||||
livePathGroup.visible = layersRef.current.showLive;
|
||||
pathGroup.clear();
|
||||
const material = new THREE.LineBasicMaterial({ color: layersRef.current.showLive ? 0x5fc4d8 : 0x5c80a0 });
|
||||
livePathGroup.clear();
|
||||
const completedMaterial = new THREE.LineBasicMaterial({ color: 0x5c80a0 });
|
||||
const liveMaterial = new THREE.LineBasicMaterial({ color: 0x5fc4d8 });
|
||||
for (const segment of segmentsRef.current) {
|
||||
const start = segment.start ?? {}; const end = segment.end ?? {};
|
||||
const points = [new THREE.Vector3(Number(start.x ?? 0), Number(start.z ?? 0), Number(start.y ?? 0)), new THREE.Vector3(Number(end.x ?? 0), Number(end.z ?? 0), Number(end.y ?? 0))];
|
||||
pathGroup.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), material));
|
||||
const points = [new THREE.Vector3((Number(start.x ?? 0) - center.x) * scale, (Number(start.z ?? 0) - center.z) * scale, (Number(start.y ?? 0) - center.y) * scale), new THREE.Vector3((Number(end.x ?? 0) - center.x) * scale, (Number(end.z ?? 0) - center.z) * scale, (Number(end.y ?? 0) - center.y) * scale)];
|
||||
const target = segment.active ? livePathGroup : pathGroup;
|
||||
target.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), segment.active ? liveMaterial : completedMaterial));
|
||||
}
|
||||
if (layersRef.current.showLimits) {
|
||||
const limits = new THREE.LineSegments(new THREE.EdgesGeometry(new THREE.BoxGeometry(5, 2, 3.5)), new THREE.LineBasicMaterial({ color: 0xd87d6c }));
|
||||
@@ -89,7 +124,7 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals
|
||||
else if (selectedView === "y") camera.position.set(0.01, 2, distance);
|
||||
else if (selectedView === "y2") camera.position.set(0.01, 2, -distance);
|
||||
else camera.position.set(6 / Math.max(0.5, zoomRef.current), 5 / Math.max(0.5, zoomRef.current), 7 / Math.max(0.5, zoomRef.current));
|
||||
camera.lookAt(0, 1, 0);
|
||||
camera.lookAt(0, 1.8, 0);
|
||||
scene.rotation.y = rotateRef.current ? (performance.now() / 5000) % (Math.PI * 2) : 0;
|
||||
renderer.render(scene, camera);
|
||||
frame = requestAnimationFrame(render);
|
||||
|
||||
Reference in New Issue
Block a user