Make machine configuration authoritative and restore native checkpoints exactly
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,4 +1,7 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { WEB_SETTINGS } from "../../workspace/web-settings.mjs";
|
||||
const VIEWER = WEB_SETTINGS.viewer;
|
||||
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";
|
||||
@@ -11,7 +14,7 @@ type Segment = { id?: number; active?: boolean; motion_type?: number; samples?:
|
||||
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 Controller = Record<string, () => void>;
|
||||
type Host = HTMLDivElement & { xyzacMachineController?: Controller };
|
||||
const toView = (point: Point) => new THREE.Vector3(Number(point.x ?? 0) * .01, Number(point.z ?? 0) * .01, Number(point.y ?? 0) * .01);
|
||||
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) {
|
||||
const host = useRef<Host>(null);
|
||||
@@ -23,7 +26,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
const element = host.current;
|
||||
if (!element) return;
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false, preserveDrawingBuffer: true });
|
||||
renderer.setPixelRatio(Math.min(globalThis.devicePixelRatio || 1, 2));
|
||||
renderer.setPixelRatio(Math.min(globalThis.devicePixelRatio || 1, VIEWER.pixel_ratio_limit));
|
||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
renderer.toneMappingExposure = 1;
|
||||
renderer.shadowMap.enabled = true;
|
||||
@@ -31,7 +34,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
renderer.domElement.dataset.engine = "three.js r185 / xyzac-trt-vismach";
|
||||
element.appendChild(renderer.domElement);
|
||||
|
||||
const scene = new THREE.Scene(); scene.background = new THREE.Color(0x252b2c);
|
||||
const scene = new THREE.Scene(); scene.background = new THREE.Color(VIEWER.colors.background);
|
||||
const studio = new RoomEnvironment();
|
||||
const pmrem = new THREE.PMREMGenerator(renderer);
|
||||
const environment = pmrem.fromScene(studio, .04);
|
||||
@@ -60,11 +63,11 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
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);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(36, 1, .02, 150);
|
||||
const camera = new THREE.PerspectiveCamera(CAMERA.fov, 1, CAMERA.near, CAMERA.far);
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true; controls.dampingFactor = .12;
|
||||
controls.enableDamping = true; controls.dampingFactor = CAMERA.damping;
|
||||
controls.enableRotate = true;
|
||||
controls.screenSpacePanning = true; controls.minDistance = .25; controls.maxDistance = 65;
|
||||
controls.screenSpacePanning = true; controls.minDistance = CAMERA.min_distance; controls.maxDistance = CAMERA.max_distance;
|
||||
// Keep the standard Three.js mouse contract: left-drag orbits, middle
|
||||
// drag zooms, right-drag pans, and the wheel zooms. The machine canvas
|
||||
// must remain directly navigable without first toggling a mode button.
|
||||
@@ -96,7 +99,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
const point = new THREE.Vector3(x, y, z).sub(modelCenter);
|
||||
distance = Math.max(distance, point.dot(direction) + Math.max(Math.abs(point.dot(right)) / (tanV * camera.aspect), Math.abs(point.dot(up)) / tanV));
|
||||
}
|
||||
controls.target.copy(modelCenter); camera.position.copy(modelCenter).addScaledVector(direction, distance * 1.12 / Math.max(.5, scale));
|
||||
controls.target.copy(modelCenter); camera.position.copy(modelCenter).addScaledVector(direction, distance * CAMERA.fit_margin / Math.max(.5, scale));
|
||||
camera.lookAt(controls.target); controls.update();
|
||||
};
|
||||
const resize = () => {
|
||||
@@ -106,7 +109,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
};
|
||||
const observer = new ResizeObserver(resize); observer.observe(element); resize();
|
||||
const pan = (x: number, y: number) => {
|
||||
const amount = camera.position.distanceTo(controls.target) * .035;
|
||||
const amount = camera.position.distanceTo(controls.target) * CAMERA.pan_fraction;
|
||||
camera.updateMatrix();
|
||||
const offset = new THREE.Vector3().setFromMatrixColumn(camera.matrix, 0).multiplyScalar(x * amount)
|
||||
.addScaledVector(new THREE.Vector3().setFromMatrixColumn(camera.matrix, 1), y * amount);
|
||||
@@ -118,12 +121,12 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
camera.position.copy(controls.target).add(offset); controls.update();
|
||||
};
|
||||
element.xyzacMachineController = {
|
||||
zoomIn: () => zoomCamera(.8), zoomOut: () => zoomCamera(1.25),
|
||||
zoomIn: () => zoomCamera(CAMERA.zoom_in), zoomOut: () => zoomCamera(CAMERA.zoom_out),
|
||||
panLeft: () => pan(-1, 0), panRight: () => pan(1, 0), panUp: () => pan(0, 1), panDown: () => pan(0, -1),
|
||||
rotateLeft: () => { controls.rotateLeft(Math.PI / 12); controls.update(); },
|
||||
rotateRight: () => { controls.rotateLeft(-Math.PI / 12); controls.update(); },
|
||||
rotateUp: () => { controls.rotateUp(Math.PI / 12); controls.update(); },
|
||||
rotateDown: () => { controls.rotateUp(-Math.PI / 12); controls.update(); },
|
||||
rotateLeft: () => { controls.rotateLeft(THREE.MathUtils.degToRad(CAMERA.rotate_degrees)); controls.update(); },
|
||||
rotateRight: () => { controls.rotateLeft(-THREE.MathUtils.degToRad(CAMERA.rotate_degrees)); controls.update(); },
|
||||
rotateUp: () => { controls.rotateUp(THREE.MathUtils.degToRad(CAMERA.rotate_degrees)); controls.update(); },
|
||||
rotateDown: () => { controls.rotateUp(-THREE.MathUtils.degToRad(CAMERA.rotate_degrees)); controls.update(); },
|
||||
reset: () => { lastPreset = ""; },
|
||||
tool: () => {
|
||||
const target = assembly.toolTip.getWorldPosition(new THREE.Vector3()).add(new THREE.Vector3(0, .2, 0));
|
||||
@@ -136,11 +139,11 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
// workpiece path together with the physical table.
|
||||
const pathGroup = new THREE.Group(); pathGroup.name = "xyzac-toolpath"; assembly.joints.rotate.add(pathGroup);
|
||||
const liveGroup = new THREE.Group(); liveGroup.name = "xyzac-live-toolpath"; assembly.joints.rotate.add(liveGroup);
|
||||
const pathMaterials = [0xffff00, 0xff9a55, 0x5c9d9a].map((color) => new THREE.LineBasicMaterial({ color }));
|
||||
const pathMaterials = [VIEWER.colors.path, VIEWER.colors.live, VIEWER.colors.rapid].map((color) => new THREE.LineBasicMaterial({ color }));
|
||||
const clearLines = (group: THREE.Group) => { group.children.forEach((child) => (child as THREE.Line).geometry.dispose()); group.clear(); };
|
||||
const limits = new THREE.Box3Helper(new THREE.Box3(), 0xdd7566); scene.add(limits);
|
||||
const limits = new THREE.Box3Helper(new THREE.Box3(), VIEWER.colors.limits); scene.add(limits);
|
||||
const offsets = new THREE.AxesHelper(.8); scene.add(offsets);
|
||||
const extents = new THREE.Box3Helper(initialBounds, 0xe6c56b); scene.add(extents);
|
||||
const extents = new THREE.Box3Helper(initialBounds, VIEWER.colors.extents); scene.add(extents);
|
||||
const render = () => {
|
||||
const state = visualRef.current, config = settings.current;
|
||||
assembly.update(state);
|
||||
@@ -165,7 +168,7 @@ export function XyzacMachineView({ visual, toolpath, view = "p", zoom = 1, rotat
|
||||
}
|
||||
offsets.visible = config.showOffsets;
|
||||
const coordinates = state.machineModel?.coordinate_system ?? "XYZAC";
|
||||
offsets.position.set(coordinates === "XYZBC" ? Number(state.offsets.x_offset ?? 0) * .01 : 0, state.offsets.z_offset * .01, state.offsets.y_offset * .01);
|
||||
offsets.position.set(coordinates === "XYZBC" ? Number(state.offsets.x_offset ?? 0) * VIEWER.mm_scale : 0, state.offsets.z_offset * VIEWER.mm_scale, state.offsets.y_offset * VIEWER.mm_scale);
|
||||
extents.visible = config.showExtents;
|
||||
const preset = `${config.view}:${config.zoom}`;
|
||||
if (preset !== lastPreset) { presetCamera(); lastPreset = preset; }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { WEB_SETTINGS } from "../../workspace/web-settings.mjs";
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import { projectXyzacVisual, type XyzacVisualSource, type XyzacVisualState } from "./xyzac-visual-adapter";
|
||||
@@ -8,7 +9,7 @@ type Segment = { id?: number; source_line?: number | null; active?: boolean; kin
|
||||
type Props = { visual: XyzacVisualState; view?: "z" | "z2" | "x" | "y" | "y2" | "p"; zoom?: number; rotateMode?: boolean; showPath?: boolean; showLive?: boolean; showLimits?: boolean; showVelocity?: boolean; showOffsets?: boolean; showExtents?: boolean };
|
||||
|
||||
const DEG = Math.PI / 180;
|
||||
const MM = 0.01;
|
||||
const MM = WEB_SETTINGS.viewer.mm_scale;
|
||||
const sourcePoint = (point: Point) => new THREE.Vector3(Number(point.x ?? 0) * MM, Number(point.z ?? 0) * MM, Number(point.y ?? 0) * MM);
|
||||
|
||||
export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = false, showPath = true, showLive = true, showLimits = false, showVelocity = false, showOffsets = false, showExtents = false }: Props) {
|
||||
@@ -24,11 +25,11 @@ export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = fa
|
||||
const element = host.current;
|
||||
if (!element) return;
|
||||
const scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(0x050a0e);
|
||||
scene.background = new THREE.Color(WEB_SETTINGS.viewer.toolpath_colors.background);
|
||||
scene.add(new THREE.HemisphereLight(0xdcecff, 0x121820, 1.4));
|
||||
let camera: THREE.PerspectiveCamera | THREE.OrthographicCamera = new THREE.PerspectiveCamera(40, 1, 0.001, 100);
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false, preserveDrawingBuffer: true });
|
||||
renderer.setPixelRatio(Math.min(globalThis.devicePixelRatio || 1, 2));
|
||||
renderer.setPixelRatio(Math.min(globalThis.devicePixelRatio || 1, WEB_SETTINGS.viewer.pixel_ratio_limit));
|
||||
renderer.domElement.dataset.engine = "three.js r185 / xyzac-tool-preview";
|
||||
element.appendChild(renderer.domElement);
|
||||
let controls: OrbitControls<THREE.PerspectiveCamera | THREE.OrthographicCamera> = new OrbitControls(camera, renderer.domElement);
|
||||
@@ -85,12 +86,12 @@ export function XyzacToolPreview({ visual, view = "p", zoom = 1, rotateMode = fa
|
||||
}
|
||||
group.clear();
|
||||
};
|
||||
const completed = new THREE.LineBasicMaterial({ color: 0xd8dfe3, depthTest: false });
|
||||
const rapid = new THREE.LineDashedMaterial({ color: 0xa85d5d, dashSize: .025, gapSize: .018, depthTest: false });
|
||||
const completed = new THREE.LineBasicMaterial({ color: WEB_SETTINGS.viewer.toolpath_colors.completed, depthTest: false });
|
||||
const rapid = new THREE.LineDashedMaterial({ color: WEB_SETTINGS.viewer.toolpath_colors.rapid, dashSize: .025, gapSize: .018, depthTest: false });
|
||||
// LinuxCNC uses yellow for jog backplot. Coordinated program execution is
|
||||
// red (live plot), while an unambiguous current program block is cyan.
|
||||
const live = new THREE.LineBasicMaterial({ color: 0x00ffff, depthTest: false });
|
||||
const liveHistory = new THREE.LineBasicMaterial({ color: 0xff6b4a, depthTest: false });
|
||||
const live = new THREE.LineBasicMaterial({ color: WEB_SETTINGS.viewer.toolpath_colors.active, depthTest: false });
|
||||
const liveHistory = new THREE.LineBasicMaterial({ color: WEB_SETTINGS.viewer.toolpath_colors.live, depthTest: false });
|
||||
let frame = 0;
|
||||
let liveTick = -1;
|
||||
let liveTrace: THREE.Vector3[] = [];
|
||||
|
||||
2
web/react/src/legacy.d.ts
vendored
2
web/react/src/legacy.d.ts
vendored
@@ -1,4 +1,6 @@
|
||||
declare module "*.mjs" {
|
||||
export const WEB_SETTINGS: typeof import("../../workspace/web-settings.json");
|
||||
export function axisImagePath(name: string, base?: string): string;
|
||||
export const TRT_GEOMETRY_KEYS: readonly string[];
|
||||
export function readTrtGeometry(configuration: { entrypoint: string; files: Record<string, string> }): { coordinates: string; offsets: Record<string, number>; sources: Record<string, { path: string; line: number; value: string }>; unsupported: string; state_hash: string };
|
||||
export function writeTrtGeometry<T extends { entrypoint: string; files: Record<string, string> }>(configuration: T, values: Record<string, string | number>): T;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// AXIS ships these exact 21/22/24px bitmap assets in the source tree.
|
||||
export const LINUXCNC_AXIS_ASSETS = "/linuxcnc/share/axis/images";
|
||||
import { axisImagePath, WEB_SETTINGS } from "../../workspace/web-settings.mjs";
|
||||
export const LINUXCNC_AXIS_ASSETS = `${import.meta.env.BASE_URL}${WEB_SETTINGS.assets.axis_images}`;
|
||||
|
||||
export function axisIcon(name: string): string {
|
||||
return `${LINUXCNC_AXIS_ASSETS}/${name}`;
|
||||
return axisImagePath(name, import.meta.env.BASE_URL);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ async function execute(bundle, source) {
|
||||
const beforeRecovery = session.xyzacKinematics.snapshot();
|
||||
assert.equal(session.restoreCheckpoint(savedCheckpoint).status, "blocked");
|
||||
assert.equal(session.restoreCompactPowerOff(savedCompact, seq + 1).status, "blocked");
|
||||
assert.throws(() => session.importTrace(savedTrace), /trt_recovery_geometry_mismatch/);
|
||||
assert.throws(() => session.importTrace(savedTrace), /trt_recovery_(geometry|configuration)_mismatch/);
|
||||
assert.deepEqual(session.xyzacKinematics.snapshot(), beforeRecovery);
|
||||
assert.equal(session.wasmHomeLimit.read().state.homed, false);
|
||||
return { trace, offsets: expected, final: trace.at(-1), preview_hash: fnv1a64(preview.payload.preview), trace_hash: fnv1a64(trace), model_samples: samples.length };
|
||||
|
||||
@@ -42,7 +42,7 @@ assert.equal(visual.source, "linuxcnc-wasm-worker");
|
||||
assert.equal(visual.machineModel?.id, "xyzac-trt");
|
||||
assert.equal(visual.machineModel?.source_hash, "fnv1a64:model");
|
||||
assert.deepEqual(XYZAC_MACHINE_GROUPS, ["xyzac-machine", "table-x", "saddle-y", "spindle-z", "tilt-a", "rotate-c", "tool-offset", "xyzac-toolpath", "xyzac-live-toolpath"]);
|
||||
for (const token of ["table-x", "saddle-y", "spindle-z", "tilt-a", "rotate-c", "tool-offset", "tableX.position.x = -tableXJoint * MM", "saddle.position.z = -saddleYJoint * MM", "zslide.position.y = (200 - spindleZJoint) * MM", "tilt.rotation.x = -tiltAJoint * DEG", "rotate.rotation.y = -rotateCJoint * DEG", "tool.position.y = -state.offsets.tool_offset * MM", "assembly.joints.rotate.add(pathGroup)", "assembly.joints.rotate.add(liveGroup)", "dataset.xyzacToolpathFrame", "dataset.xyzacToolpathAttached", "data-xyzac-tick", "data-xyzac-state-hash", "data-xyzac-active-segment", "data-xyzac-joints", "data-xyzac-offsets"]) assert.ok(source.includes(token), token);
|
||||
for (const token of ["table-x", "saddle-y", "spindle-z", "tilt-a", "rotate-c", "tool-offset", "tableX.position.x = -tableXJoint * MM", "saddle.position.z = -saddleYJoint * MM", "zslide.position.y = (datum - spindleZJoint) * MM", "tilt.rotation.x = -tiltAJoint * DEG", "rotate.rotation.y = -rotateCJoint * DEG", "tool.position.y = -state.offsets.tool_offset * MM", "assembly.joints.rotate.add(pathGroup)", "assembly.joints.rotate.add(liveGroup)", "dataset.xyzacToolpathFrame", "dataset.xyzacToolpathAttached", "data-xyzac-tick", "data-xyzac-state-hash", "data-xyzac-active-segment", "data-xyzac-joints", "data-xyzac-offsets"]) assert.ok(source.includes(token), token);
|
||||
for (const forbidden of [/accept\s*\(/, /postMessage\s*\(/, /_sim_/, /_malloc/, /navigator\.storage/, /HAL_SET/, /KINEMATICS_SELECT/]) assert.equal(forbidden.test(source), false, String(forbidden));
|
||||
assert.ok(adapter.includes("source: \"linuxcnc-wasm-worker\""));
|
||||
assert.equal(source.includes("axis-preview-hud xyzac-machine-hud"), false, "machine preview HUD must stay empty");
|
||||
|
||||
@@ -2,27 +2,18 @@ import * as THREE from "three";
|
||||
import { RoundedBoxGeometry } from "three/examples/jsm/geometries/RoundedBoxGeometry.js";
|
||||
import type { XyzacVisualState } from "./xyzac-visual-adapter";
|
||||
|
||||
const MM = .01;
|
||||
import { WEB_SETTINGS } from "../../workspace/web-settings.mjs";
|
||||
const MM = WEB_SETTINGS.viewer.mm_scale;
|
||||
const DEG = Math.PI / 180;
|
||||
|
||||
// Source coordinates remain millimetres, Z up. The existing viewer uses Y up.
|
||||
function buildTrtMachine(coordinates = "XYZAC") {
|
||||
const isXyzbc = coordinates === "XYZBC";
|
||||
const datum = WEB_SETTINGS.viewer.models[isXyzbc ? "XYZBC" : "XYZAC"].datum_z_mm;
|
||||
// Separate source identities: XYZAC uses tilt-a, XYZBC uses tilt-b.
|
||||
const rotaryAxis = isXyzbc ? "b" : "a";
|
||||
const geometries = new Map<string, THREE.BufferGeometry>();
|
||||
const materials = {
|
||||
enamel: new THREE.MeshStandardMaterial({ color: 0xd9e1e1, roughness: .32, metalness: .25 }),
|
||||
teal: new THREE.MeshStandardMaterial({ color: 0x167f79, roughness: .3, metalness: .3 }),
|
||||
dark: new THREE.MeshStandardMaterial({ color: 0x303638, roughness: .42, metalness: .35 }),
|
||||
steel: new THREE.MeshStandardMaterial({ color: 0xb2bdc4, roughness: .27, metalness: .85 }),
|
||||
polished: new THREE.MeshStandardMaterial({ color: 0xe2e8ec, roughness: .19, metalness: .9 }),
|
||||
recess: new THREE.MeshStandardMaterial({ color: 0x111718, roughness: .66, metalness: .2 }),
|
||||
rubber: new THREE.MeshStandardMaterial({ color: 0x222729, roughness: .88 }),
|
||||
carbide: new THREE.MeshStandardMaterial({ color: 0xb9aa79, roughness: .29, metalness: .8 }),
|
||||
warning: new THREE.MeshStandardMaterial({ color: 0xe7bd48, roughness: .48, metalness: .12 }),
|
||||
lamp: new THREE.MeshStandardMaterial({ color: 0xe2f8ff, emissive: 0xd4f2ff, emissiveIntensity: 1.5 }),
|
||||
};
|
||||
const materials = Object.fromEntries(Object.entries(WEB_SETTINGS.viewer.materials).map(([name, properties]) => [name, new THREE.MeshStandardMaterial(properties)])) as Record<keyof typeof WEB_SETTINGS.viewer.materials, THREE.MeshStandardMaterial>;
|
||||
type Finish = keyof typeof materials;
|
||||
const geometry = (key: string, create: () => THREE.BufferGeometry) => {
|
||||
if (!geometries.has(key)) geometries.set(key, create());
|
||||
@@ -84,7 +75,7 @@ function buildTrtMachine(coordinates = "XYZAC") {
|
||||
box(machine, "z-servo", 0, -105, -169, 49, 21, 50, "dark", 3);
|
||||
box(machine, "z-servo-cover", 0, -117, -169, 40, 3, 38, "teal", 2);
|
||||
|
||||
const head = group(machine, "head", 0, 0, isXyzbc ? 150 : 200);
|
||||
const head = group(machine, "head", 0, 0, datum);
|
||||
// XYZAC has the long moving knee bridge; XYZBC has the shorter moving
|
||||
// spindle head from xyzbc-trt-gui.py.
|
||||
const headDepth = isXyzbc ? 130 : 270;
|
||||
@@ -175,8 +166,8 @@ function buildTrtMachine(coordinates = "XYZAC") {
|
||||
}
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const slot = box(rotate, "radial-t-slot", 0, 0, .14, 3, 42, .3, "recess", .1);
|
||||
slot.position.x = Math.sin(i * Math.PI / 2) * .28;
|
||||
slot.position.z = Math.cos(i * Math.PI / 2) * .28;
|
||||
slot.position.x = Math.sin(i * Math.PI / 2) * (28 * MM);
|
||||
slot.position.z = Math.cos(i * Math.PI / 2) * (28 * MM);
|
||||
slot.rotation.y = i * Math.PI / 2;
|
||||
}
|
||||
for (let i = 0; i < 72; i++) {
|
||||
@@ -197,18 +188,18 @@ function buildTrtMachine(coordinates = "XYZAC") {
|
||||
tableX.position.x = -tableXJoint * MM;
|
||||
saddle.position.z = -saddleYJoint * MM;
|
||||
if (coordinates === "XYZBC") {
|
||||
head.position.y = (150 + spindleZJoint) * MM;
|
||||
head.position.y = (datum + spindleZJoint) * MM;
|
||||
// XYZBC is a table tilt: the source model rotates the B assembly
|
||||
// around machine Y. The Web scene maps source Y to Three.js Z.
|
||||
head.rotation.set(0, 0, 0);
|
||||
zslide.position.y = 150 * MM;
|
||||
zslide.position.y = datum * MM;
|
||||
tilt.rotation.z = -tiltAJoint * DEG;
|
||||
tilt.position.set(xOffset * MM, zOffset * MM, 0).add(pivot);
|
||||
brackets.position.copy(tilt.position);
|
||||
rotaryBase.position.set(-xOffset * MM, -zOffset * MM, 0);
|
||||
} else {
|
||||
zslide.position.y = (200 - spindleZJoint) * MM;
|
||||
head.position.y = 2;
|
||||
zslide.position.y = (datum - spindleZJoint) * MM;
|
||||
head.position.y = datum * MM;
|
||||
head.rotation.set(0, 0, 0);
|
||||
// XYZAC source transform: tilt.rotation.x = -tiltAJoint * DEG.
|
||||
tilt.rotation.x = -tiltAJoint * DEG;
|
||||
@@ -251,8 +242,8 @@ function createFlutedCutter() {
|
||||
const angle = col / radial * Math.PI * 2;
|
||||
const phase = (angle * 4 - t * Math.PI * 2 + Math.PI * 4) % (Math.PI * 2);
|
||||
const relief = Math.pow(Math.max(0, Math.sin(phase / 2)), 2);
|
||||
const radius = (3 - 1.35 * relief) * .01;
|
||||
positions.push(radius * Math.cos(angle), t * .08, radius * Math.sin(angle));
|
||||
const radius = (3 - 1.35 * relief) * MM;
|
||||
positions.push(radius * Math.cos(angle), t * 8 * MM, radius * Math.sin(angle));
|
||||
if (row < axial && col < radial) {
|
||||
const a = row * (radial + 1) + col, b = a + radial + 1;
|
||||
indices.push(a, b, a + 1, a + 1, b, b + 1);
|
||||
@@ -260,7 +251,7 @@ function createFlutedCutter() {
|
||||
}
|
||||
}
|
||||
const bottom = positions.length / 3; positions.push(0, 0, 0);
|
||||
const top = positions.length / 3; positions.push(0, .08, 0);
|
||||
const top = positions.length / 3; positions.push(0, 8 * MM, 0);
|
||||
for (let col = 0; col < radial; col++) {
|
||||
indices.push(bottom, col, col + 1);
|
||||
const a = axial * (radial + 1) + col;
|
||||
|
||||
Reference in New Issue
Block a user