Spaces:
Sleeping
Sleeping
File size: 5,794 Bytes
265686c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | # G-code 3D Preview
## Overview
G-code preview renders CNC toolpaths as 3D lines/tubes in a WebGL viewport. The toolpath visualization shows rapid moves, cutting moves, and arcs with distinct colors, allowing the operator to verify the machining strategy before running on a real machine.
## Libraries Comparison
### gcode-preview (npm)
Full-featured Three.js-based G-code renderer:
- `npm install gcode-preview`
- MIT license, active development (v2.18+)
- Supports G0/G1/G2/G3, tool changes (T0-T7)
- Tube rendering via BatchedMesh (Three.js r159+)
- Layer controls (startLayer/endLayer), animation
- Progressive loading for large files
```javascript
const preview = new GCodePreview.WebGLPreview({
canvas: document.querySelector('canvas'),
extrusionColor: ['#0088FF', '#00CC66', '#FF4444'],
travelColor: '#FF000040',
renderTubes: true,
buildVolume: { x: 500, y: 500, z: 200 },
});
preview.processGCode(gcodeString);
```
**Limitation**: Designed for 3D printing. No spindle/coolant M-code handling, no per-speed coloring built in.
### Three.js GCodeLoader (built-in)
Minimal loader included with Three.js:
- Located at `three/examples/jsm/loaders/GCodeLoader.js`
- Supports G0/G1 only (no G2/G3 arcs)
- Returns `THREE.Group` with green (cutting) and red (rapid) `LineSegments`
- Colors hardcoded, no tool changes, no animation
- Simple to integrate into existing Three.js scene
### gcode-toolpath (npm, by cncjs)
Parser library, not a renderer:
- Parses full G-code grammar including G2/G3 arcs
- Tracks modal state (motion, WCS, plane, units, feed, spindle, tool)
- Callbacks: `addLine(modal, v1, v2)`, `addArcCurve(modal, v1, v2, v0)`
- Pair with custom Three.js rendering for CNC-specific visualization
## Custom Implementation (NeuralCAD Approach)
For CNC-specific needs, a custom parser + Three.js renderer provides the most control:
### G-code Parser
```javascript
function parseGCode(gcodeString) {
const segments = [];
let pos = { x: 0, y: 0, z: 0 };
let mode = 'G0';
let feed = 0;
let tool = 0;
for (const line of gcodeString.split('\n')) {
const cleaned = line.split(';')[0].split('(')[0].trim();
if (!cleaned) continue;
// Extract commands
const g = cleaned.match(/G(\d+)/)?.[1];
const x = cleaned.match(/X([-\d.]+)/)?.[1];
const y = cleaned.match(/Y([-\d.]+)/)?.[1];
const z = cleaned.match(/Z([-\d.]+)/)?.[1];
const f = cleaned.match(/F([-\d.]+)/)?.[1];
const t = cleaned.match(/T(\d+)/)?.[1];
const i = cleaned.match(/I([-\d.]+)/)?.[1];
const j = cleaned.match(/J([-\d.]+)/)?.[1];
if (g) mode = 'G' + g;
if (f) feed = parseFloat(f);
if (t) tool = parseInt(t);
const newPos = {
x: x ? parseFloat(x) : pos.x,
y: y ? parseFloat(y) : pos.y,
z: z ? parseFloat(z) : pos.z,
};
if (mode === 'G0' || mode === 'G1') {
if (x || y || z) {
segments.push({
type: mode, start: {...pos}, end: {...newPos},
feed, tool
});
}
} else if (mode === 'G2' || mode === 'G3') {
segments.push({
type: mode, start: {...pos}, end: {...newPos},
center: { x: pos.x + (i ? parseFloat(i) : 0),
y: pos.y + (j ? parseFloat(j) : 0) },
feed, tool
});
}
pos = newPos;
}
return segments;
}
```
### Three.js Renderer
```javascript
function renderToolpath(segments, scene) {
const rapids = [], cuts = [];
for (const seg of segments) {
const arr = seg.type === 'G0' ? rapids : cuts;
if (seg.type === 'G2' || seg.type === 'G3') {
// Tessellate arc to line segments
const points = tessellateArc(seg);
for (let i = 0; i < points.length - 1; i++) {
cuts.push(points[i].x, points[i].y, points[i].z,
points[i+1].x, points[i+1].y, points[i+1].z);
}
} else {
arr.push(seg.start.x, seg.start.y, seg.start.z,
seg.end.x, seg.end.y, seg.end.z);
}
}
// Rapid moves -- red, semi-transparent
const rapidGeo = new THREE.BufferGeometry();
rapidGeo.setAttribute('position',
new THREE.Float32BufferAttribute(rapids, 3));
scene.add(new THREE.LineSegments(rapidGeo,
new THREE.LineBasicMaterial({ color: 0xFF0000, opacity: 0.3,
transparent: true })));
// Cutting moves -- blue
const cutGeo = new THREE.BufferGeometry();
cutGeo.setAttribute('position',
new THREE.Float32BufferAttribute(cuts, 3));
scene.add(new THREE.LineSegments(cutGeo,
new THREE.LineBasicMaterial({ color: 0x0088FF })));
}
```
### View Toggle
```javascript
const stlGroup = new THREE.Group();
const gcodeGroup = new THREE.Group();
scene.add(stlGroup);
scene.add(gcodeGroup);
function showPartView() { stlGroup.visible = true; gcodeGroup.visible = false; }
function showToolpathView() { stlGroup.visible = false; gcodeGroup.visible = true; }
function showOverlay() {
stlGroup.visible = true;
gcodeGroup.visible = true;
stlGroup.traverse(child => {
if (child.material) {
child.material.transparent = true;
child.material.opacity = 0.3;
}
});
}
```
## Material Removal Simulation
### Heightmap/Dexel (Best for 3-axis)
Workpiece represented as a 2D grid of height values. Tool carving lowers heights along path. O(n^2) memory, GPU-friendly, cannot represent undercuts.
### Voxel Grid (Multi-axis)
3D occupancy grid. Tool clears voxels along path. O(n^3) memory, handles undercuts. Marching cubes for mesh extraction.
### CSG (three-bvh-csg)
Boolean subtraction of tool shape from stock mesh. 100x faster than BSP-based alternatives. Expensive per operation -- best for final result view, not animation.
For NeuralCAD's 3-axis scope, the heightmap approach is optimal if material removal simulation is needed in the future.
|