Permalink
Browse files

First cut of GCode viewer. Actually works!

Includes:
- Basic UI structure
- WebGL rendering (using three.js)
- Mouse operations to rotate (hold down 'S' and mouse move to zoom)
- GCode parser
- Interpretation of 'G1' GCode instruction, which is enough to show a
  pretty good model.
  • Loading branch information...
0 parents commit 973cb081defc875a612d02836ef21fccb069e60b Joe Walnes committed Mar 31, 2012
Showing with 76,052 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +4,476 −0 web/examples/15mm_cube.gcode
  3. +25,592 −0 web/examples/octocat.gcode
  4. +44,305 −0 web/examples/part.gcode
  5. +40 −0 web/index.html
  6. +794 −0 web/lib/Three.js
  7. +632 −0 web/lib/bootstrap.min.css
  8. +4 −0 web/lib/jquery-1.7.1.min.js
  9. +208 −0 web/viewer.js
@@ -0,0 +1 @@
+*.swp

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>GCode Viewer</title>
+ <link rel="stylesheet" href="lib/bootstrap.min.css">
+ <style>
+ #renderArea {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 40px;
+ }
+ </style>
+ <script src="lib/jquery-1.7.1.min.js"></script>
+ <script src="lib/Three.js"></script>
+ <script src="viewer.js"></script>
+ </head>
+ <body>
+
+ <div class="navbar navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container">
+ <span class="brand" href="#">GCode Viewer</span>
+ <ul class="nav">
+ <li><a href="#help">Open File</a></li>
+ <li><a href="#help">Help</a></li>
+ <li><a href="#help">GitHub</a></li>
+ </ul>
+ <ul class="nav pull-right">
+ <li><a href="http://twitter.com/joewalnes">@joewalnes</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <div id="renderArea"></div>
+ </body>
+</html>

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,208 @@
+function error(msg) {
+ alert(msg);
+}
+
+function loadFile(path, callback /* function(contents) */) {
+ $.get(path, null, callback, 'text')
+ .error(function() { error() });
+}
+
+function parseGCode(gcode, handlers) {
+ var abort = false;
+ gcode.split('\n').forEach(function(line, i) {
+ if (abort) {
+ return;
+ }
+ line = line.replace(/;.*$/, '').trim(); // Remove comments
+ if (line) {
+ var tokens = line.split(' ');
+ if (tokens) {
+ var cmd = tokens[0];
+ var args = {};
+ tokens.splice(1).forEach(function(token) {
+ var key = token[0].toLowerCase();
+ var value = parseFloat(token.substring(1));
+ args[key] = value;
+ });
+ var handler = handlers[tokens[0]];
+ if (handler) {
+ var result = handler(args, i + 1);
+ if (result === false) {
+ abort = true;
+ return;
+ }
+ } else {
+ error('Unsupported GCode command at line ' + (i + 1) + ': ' + tokens[0]);
+ abort = true;
+ return;
+ }
+ }
+ }
+ });
+}
+
+function createObjectFromGCode(gcode) {
+ // GCode descriptions come from:
+ // http://reprap.org/wiki/G-code
+ // http://en.wikipedia.org/wiki/G-code
+ // SprintRun source code
+
+ var object = new THREE.Object3D();
+
+ var geometry = new THREE.Geometry();
+
+ parseGCode(gcode, {
+
+ G1: function(args, line) {
+ // Example: G1 Z1.0 F3000
+ // G1 X99.9948 Y80.0611 Z15.0 F1500.0 E981.64869
+ // G1 E104.25841 F1800.0
+ // Go in a straight line from the current (X, Y) point
+ // to the point (90.6, 13.8), extruding material as the move
+ // happens from the current extruded length to a length of
+ // 22.4 mm.
+
+ if (args.x !== undefined && args.y !== undefined && args.z !== undefined) {
+ geometry.vertices.push(new THREE.Vertex(
+ new THREE.Vector3(args.x, args.y, args.z)));
+ }
+ },
+
+ G21: function(args) {
+ // G21: Set Units to Millimeters
+ // Example: G21
+ // Units from now on are in millimeters. (This is the RepRap default.)
+
+ // No-op: So long as G20 is not supported.
+ },
+
+ G90: function(args) {
+ // G90: Set to Absolute Positioning
+ // Example: G90
+ // All coordinates from now on are absolute relative to the
+ // origin of the machine. (This is the RepRap default.)
+
+ // TODO!
+ },
+
+ G91: function(args) {
+ // G91: Set to Relative Positioning
+ // Example: G91
+ // All coordinates from now on are relative to the last position.
+
+ // TODO!
+ },
+
+ G92: function(args) { // E0
+ // G92: Set Position
+ // Example: G92 E0
+ // Allows programming of absolute zero point, by reseting the
+ // current position to the values specified. This would set the
+ // machine's X coordinate to 10, and the extrude coordinate to 90.
+ // No physical motion will occur.
+
+ // TODO: Only support E0
+ },
+
+ M82: function(args) {
+ // M82: Set E codes absolute (default)
+ // Descriped in Sprintrun source code.
+
+ // No-op, so long as M83 is not supported.
+ },
+
+ M84: function(args) {
+ // M84: Stop idle hold
+ // Example: M84
+ // Stop the idle hold on all axis and extruder. In some cases the
+ // idle hold causes annoying noises, which can be stopped by
+ // disabling the hold. Be aware that by disabling idle hold during
+ // printing, you will get quality issues. This is recommended only
+ // in between or after printjobs.
+
+ // No-op
+ },
+ });
+
+ var lineMaterial = new THREE.LineBasicMaterial({color:0xFFFFFF, opacity:0.2, linewidth: 1});
+ object.add(new THREE.Line(geometry, lineMaterial));
+
+ // Center
+ geometry.computeBoundingBox();
+ var center = new THREE.Vector3()
+ .add(geometry.boundingBox.min, geometry.boundingBox.max)
+ .divideScalar(2);
+ var scale = 3; // TODO: Auto size
+ object.position = center.multiplyScalar(-scale);
+ object.scale.multiplyScalar(scale);
+
+ return object;
+}
+
+function createScene(element) {
+
+ // Renderer
+ var renderer = new THREE.WebGLRenderer({clearColor:0x000000, clearAlpha: 1});
+ renderer.setSize(element.width(), element.height());
+ element.append(renderer.domElement);
+ renderer.clear();
+
+ // Scene
+ var scene = new THREE.Scene();
+
+ // Lights...
+ [[0,0,1, 0xFFFFCC],
+ [0,1,0, 0xFFCCFF],
+ [1,0,0, 0xCCFFFF],
+ [0,0,-1, 0xCCCCFF],
+ [0,-1,0, 0xCCFFCC],
+ [-1,0,0, 0xFFCCCC]].forEach(function(position) {
+ var light = new THREE.DirectionalLight(position[3]);
+ light.position.set(position[0], position[1], position[2]).normalize();
+ scene.add(light);
+ });
+
+ // Camera...
+ var fov = 45,
+ aspect = element.width() / element.height(),
+ near = 1,
+ far = 10000,
+ camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
+ //camera.rotationAutoUpdate = true;
+ //camera.position.x = 0;
+ //camera.position.y = 500;
+ camera.position.z = 300;
+ //camera.lookAt(scene.position);
+ scene.add(camera);
+ controls = new THREE.TrackballControls(camera);
+ controls.noPan = true;
+ controls.dynamicDampingFactor = 0.15;
+
+ // Action!
+ function render() {
+ controls.update();
+ renderer.render(scene, camera);
+
+ requestAnimationFrame(render); // And repeat...
+ }
+ render();
+
+ // Fix coordinates up if window is resized.
+ $(window).on('resize', function() {
+ renderer.setSize(element.width(), element.height());
+ camera.aspect = element.width() / element.height();
+ camera.updateProjectionMatrix();
+ controls.screen.width = window.innerWidth;
+ controls.screen.height = window.innerHeight;
+ });
+
+ return scene;
+}
+
+$(function() {
+ var scene = createScene($('#renderArea'));
+ loadFile('./examples/octocat.gcode', function(gcode) {
+ scene.add(createObjectFromGCode(gcode));
+ });
+});
+

0 comments on commit 973cb08

Please sign in to comment.