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.