Add AC/BC RTCP programs and 3D machine manager
This commit is contained in:
@@ -5,18 +5,19 @@ const CAMERA = VIEWER.camera;
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment.js";
|
||||
import { buildImportedMachine, type ImportedMachine } from "./imported-machine";
|
||||
import { axisIcon } from "./sourceAssets";
|
||||
import { buildXyzacMachine, buildXyzbcMachine } from "./xyzac-machine-model";
|
||||
import { projectXyzacVisual, type XyzacVisualSource, type XyzacVisualState } from "./xyzac-visual-adapter";
|
||||
|
||||
type Point = Record<string, number>;
|
||||
type Segment = { id?: number; active?: boolean; motion_type?: number; samples?: Point[]; start?: Point; end?: Point };
|
||||
type Props = { visual: XyzacVisualState; toolpath?: Segment[]; view?: "z" | "z2" | "x" | "y" | "y2" | "p"; zoom?: number; rotateMode?: boolean; showPath?: boolean; showLive?: boolean; showLimits?: boolean; showVelocity?: boolean; showOffsets?: boolean; showExtents?: boolean };
|
||||
type Props = { importedMachine?: ImportedMachine | null; visual: XyzacVisualState; toolpath?: Segment[]; view?: "z" | "z2" | "x" | "y" | "y2" | "p"; zoom?: number; rotateMode?: boolean; showPath?: boolean; showLive?: boolean; showLimits?: boolean; showVelocity?: boolean; showOffsets?: boolean; showExtents?: boolean };
|
||||
type Controller = Record<string, () => void>;
|
||||
type Host = HTMLDivElement & { xyzacMachineController?: Controller };
|
||||
const toView = (point: Point) => new THREE.Vector3(Number(point.x ?? 0) * VIEWER.mm_scale, Number(point.z ?? 0) * VIEWER.mm_scale, Number(point.y ?? 0) * VIEWER.mm_scale);
|
||||
|
||||
export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotateMode = false, showPath = false, showLive = false, showLimits = false, showVelocity = false, showOffsets = false, showExtents = false }: Props) {
|
||||
export function XyzacMachineView({ importedMachine, visual, toolpath, view = "p", zoom = 1, rotateMode = false, showPath = false, showLive = false, showLimits = false, showVelocity = false, showOffsets = false, showExtents = false }: Props) {
|
||||
const host = useRef<Host>(null);
|
||||
const visualRef = useRef(visual); visualRef.current = visual;
|
||||
const settings = useRef({ toolpath, view, zoom, rotateMode, showPath, showLive, showLimits, showOffsets, showExtents });
|
||||
@@ -30,7 +31,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
renderer.toneMappingExposure = 1;
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
renderer.shadowMap.type = THREE.PCFShadowMap;
|
||||
renderer.domElement.dataset.engine = "three.js r185 / xyzac-trt-vismach";
|
||||
element.appendChild(renderer.domElement);
|
||||
|
||||
@@ -50,7 +51,9 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
floor.rotation.x = -Math.PI / 2; floor.position.y = -2.64; floor.receiveShadow = true; scene.add(floor);
|
||||
|
||||
const coordinates = visualRef.current.machineModel?.coordinate_system ?? "XYZAC";
|
||||
const assembly = coordinates === "XYZBC" ? buildXyzbcMachine() : buildXyzacMachine(); scene.add(assembly.machine);
|
||||
const assembly = importedMachine ? buildImportedMachine(importedMachine) : coordinates === "XYZBC" ? buildXyzbcMachine() : buildXyzacMachine();
|
||||
const pathPoint = importedMachine ? (point: Point) => new THREE.Vector3(Number(point.x ?? 0), Number(point.y ?? 0), Number(point.z ?? 0)).multiplyScalar(.001) : toView;
|
||||
scene.add(assembly.machine);
|
||||
assembly.update(visualRef.current);
|
||||
const nameplateCanvas = document.createElement("canvas"); nameplateCanvas.width = 512; nameplateCanvas.height = 128;
|
||||
const label = nameplateCanvas.getContext("2d");
|
||||
@@ -61,7 +64,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
}
|
||||
const nameplateTexture = new THREE.CanvasTexture(nameplateCanvas); nameplateTexture.colorSpace = THREE.SRGBColorSpace;
|
||||
const nameplate = new THREE.Mesh(new THREE.PlaneGeometry(.84, .21), new THREE.MeshBasicMaterial({ map: nameplateTexture }));
|
||||
nameplate.position.set(-.57, -1.48, -1.046); nameplate.rotation.y = Math.PI; assembly.machine.add(nameplate);
|
||||
nameplate.position.set(-.57, -1.48, -1.046); nameplate.rotation.y = Math.PI; if (!importedMachine) assembly.machine.add(nameplate);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(CAMERA.fov, 1, CAMERA.near, CAMERA.far);
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
@@ -78,6 +81,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
controls.touches.TWO = THREE.TOUCH.DOLLY_PAN;
|
||||
let frame = 0, lastPreset = "", lastGeometry: Segment[] | null = null, lastPathKey = "";
|
||||
const initialBounds = new THREE.Box3().setFromObject(assembly.machine);
|
||||
if (importedMachine) floor.position.y = initialBounds.min.y - .03;
|
||||
const modelCenter = initialBounds.getCenter(new THREE.Vector3());
|
||||
const presetCamera = () => {
|
||||
const { view: selected, zoom: scale } = settings.current;
|
||||
@@ -156,7 +160,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
if (config.showPath || config.showLive) for (const raw of paths) {
|
||||
const live = raw.active || raw.id === state.activeSegmentId;
|
||||
if (live ? !config.showLive : !config.showPath) continue;
|
||||
const points = raw.samples?.length ? raw.samples.map(toView) : [toView(raw.start ?? {}), toView(raw.end ?? {})];
|
||||
const points = raw.samples?.length ? raw.samples.map(pathPoint) : [pathPoint(raw.start ?? {}), pathPoint(raw.end ?? {})];
|
||||
(live ? liveGroup : pathGroup).add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), pathMaterials[live ? 1 : raw.motion_type === 0 ? 2 : 0]));
|
||||
}
|
||||
lastGeometry = paths; lastPathKey = pathKey;
|
||||
@@ -188,12 +192,13 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
floor.geometry.dispose(); floor.material.dispose(); key.shadow.map?.dispose(); environment.dispose();
|
||||
renderer.dispose(); renderer.domElement.remove();
|
||||
};
|
||||
}, []);
|
||||
}, [importedMachine]);
|
||||
|
||||
const model = visual.machineModel;
|
||||
const coordinates = model?.coordinate_system ?? "XYZAC";
|
||||
const managerGeometry = importedMachine?.scene.userData.linuxcncMachineGeometry;
|
||||
const controllerButton = (action: string, label: string, asset?: string, glyph?: string) => <button type="button" data-axis-control={`machine-${action}`} data-xyzac-machine-controller={action} title={label} aria-label={label} onClick={() => host.current?.xyzacMachineController?.[action]?.()}>{asset ? <img src={axisIcon(asset)} alt="" /> : glyph}</button>;
|
||||
return <div className="three-viewer xyzac-machine-view" ref={host} data-xyzac-preview="machine" data-xyzac-model-source="linuxcnc-wasm" data-xyzac-mouse-controls="left-rotate-middle-zoom-right-pan-wheel-zoom" data-xyzac-model-id={model?.id ?? ""} data-xyzac-model-source-path={model?.source_path ?? ""} data-xyzac-model-source-hash={model?.source_hash ?? ""} data-xyzac-authoritative={String(visual.authoritative)} data-xyzac-tick={visual.tick} data-xyzac-state-hash={visual.stateHash} data-xyzac-active-segment={visual.activeSegmentId ?? ""} data-xyzac-joints={JSON.stringify(visual.joints)} data-xyzac-offsets={JSON.stringify(visual.offsets)} aria-label={`${coordinates} TRT Vismach machine model`}>
|
||||
return <div className="three-viewer xyzac-machine-view" ref={host} data-xyzac-preview="machine" data-machine-glb={importedMachine?.hash ?? ""} data-machine-manager-schema={managerGeometry?.schema ?? ""} data-machine-manager-geometry={managerGeometry ? JSON.stringify(managerGeometry) : ""} data-xyzac-model-source={importedMachine ? "glb-urdf/linuxcnc-wasm" : "linuxcnc-wasm"} data-xyzac-mouse-controls="left-rotate-middle-zoom-right-pan-wheel-zoom" data-xyzac-model-id={model?.id ?? ""} data-xyzac-model-source-path={importedMachine?.filename ?? model?.source_path ?? ""} data-xyzac-model-source-hash={importedMachine?.hash ?? model?.source_hash ?? ""} data-xyzac-authoritative={String(visual.authoritative)} data-xyzac-tick={visual.tick} data-xyzac-state-hash={visual.stateHash} data-xyzac-active-segment={visual.activeSegmentId ?? ""} data-xyzac-joints={JSON.stringify(visual.joints)} data-xyzac-offsets={JSON.stringify(visual.offsets)} aria-label={`${coordinates} ${importedMachine ? "URDF" : "TRT Vismach"} machine model`}>
|
||||
<div className="xyzac-view-controller xyzac-machine-controller" role="toolbar" aria-label="Machine 3D view controller">
|
||||
{controllerButton("zoomIn", "Zoom in", "tool_zoomin.gif")}{controllerButton("zoomOut", "Zoom out", "tool_zoomout.gif")}
|
||||
{controllerButton("panLeft", "Pan left", undefined, "\u2190")}{controllerButton("panRight", "Pan right", undefined, "\u2192")}
|
||||
|
||||
Reference in New Issue
Block a user