-
-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce an interpreter to extract command interpretation logic #211
Conversation
Visit the preview URL for this PR (updated for commit 14b54ca): https://gcode-preview--pr211-interpreter-c5zpoxi1.web.app (expires Tue, 12 Nov 2024 15:01:07 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: 59bd114ae4847b32c2bba0b68620b9069a3e3531 |
0440ea1
to
73a2f0c
Compare
Nice work @sophiedeziel! So many improvements! Some dev process ideas that I want to throw out there:
At this point it would seem we can create a a separate PR for parser improvements. And another for splitting of a Renderer class. And then there can be PRs for improving logic or perf or cleanup. Most of this, except for the removal of layers, can all still be merged into V2. I know we said we were ready for V3 but I think now that we would be in a better place if we tackle some things like this refactor first. Your thoughts? |
It is such a challenge to keep small! I agree with you that some performance stuff should be left for later. But there are some breaking changes that are not simply about moving code around, unless we introduce some of the classes in an unused state in parallel with the old code. This PR should at a minimum be in a working state, which it is not 100%. It should also include some minimal tests to help us in the next iterations. Are you able to identify a part that could be it's own individual PR? That could be a start. I'll scope out some of the todos, to prioritize mergability. And how strongly do you feel about progressive rendering? |
e8cc295
to
b9a5e78
Compare
2c6a9f9
to
3efd947
Compare
3efd947
to
ac93091
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setup is a major improvement in many aspects. Indeed this is becoming a 'platform' we can build the next iteration of cool features on! I'm genuinely grateful for having such a brilliant contributor!! thank you for your hard work!
I did find some things that might deserve attention but nothing that stands in the way of merging this PR. I suggest your read through my remarks and then merge at will.
expect(result.parameters.lineWidth).toEqual(9); | ||
}); | ||
|
||
test('.geometry returns an ExtrusionGeometry with the path line height', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honest question: what are you testing here? I would expect that this is covered by the type system. As long as we're using the type checker I don't think you end up breaking this. Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wrestling with this test and other ones that are similar.
I wanted to make sure the geometry was passed the right attributes to the constructor. Sometimes it's valuable, sometimes it's not.
@@ -403,13 +304,20 @@ export class WebGLPreview { | |||
this.initScene(); | |||
|
|||
this.renderLayerIndex = 0; | |||
|
|||
if (this.job.layers() === null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you're executing job.layers()
multiple times within a single render pass. You prob want to avoid that by just keep a local variable or instance prop _layers or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fixed in #220 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok nvrnd, I've seen the indexers PR now :-)
} | ||
|
||
for (const color in this._geometries) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
brilliant!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very similar to what we have in v2. Current users already benefit from it!
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
* Interpreter prototype * arc support * units * Simplify toolchange * travelType * remove setInches * remove targetId * layers * render lines * extract machine * wip * Make it work with rerenders * Remove some layer references * Rename Machine to Job * Simplify parsing attributes * Am I going too far? * get rid of geometries once used * the geometries disposition is handled by the batchMesh * Fix tests * Bring back some code * Bring back progressive rendering * update dev-gui with job * Test Path * First interpreter tests * Test G0 and G1 * Test everything by G2 * Adding missing codes * Minimize diff on app.js * Leave G21 for a future PR * Job tests (and fixes!) * Keep G28 for a separate PR * Improve tests * Code improvements * Retractions are travel
This refactor is extracting responsibilities out of the parser and out of the webgl-preview class into an interpreter to produce job and paths primitives. The line used to be blurry in between the two classes. The interpreter is the missing piece that helps defining the boundaries in a clear way.
Key concepts
The parser
The parser's responsibility is only about converting a text file to an array of structured javascript objects that represents the list commands and their attributes. All the parser cares about is the syntax. It should never hold logic related to what the commands means and how they should be interpreted. If state has to be held based on the content of the gcode, it's a smell about code not belonging in there.
The interpreter
The interpreter takes the output of the parser. This is where the gcode commands are "implemented". It manages a virtual machine's state and generates a list of paths representing extrusions and travels. All it should care about is translating gcode into job and path primitives.
The Path
Represents a continuous travel of the tool, with specific attributes and type. It holds the coordinates and the logic to be rendered on a scene.
The job
Represents the state of a print or milling job. It holds info about current state and all the paths generated by the interpreter "running" the gcode on it.
The renderer
The webgl-preview class is the renderer. Maybe it should be renamed
renderer
? It takes the state of the virtual machine and the results from the interpreter and adds them to a 3D scene.Next steps
This PR is still a work in progress and there are a lot of things I am not satisfied with yet.
For example, I've put 3D objects logic into the paths objects. It does not seem right to me. It makes the materials management overly complicated.
I'm also annoyed by the gcode enum for supported commands. It should be simpler to implement a new command.
For some reason, it is not very performant at the moment. This will be investigated after the refactor gets into a more stable state.
Todo
Debug the CNC toolpath preset that does not render correctlyturns out it's an issue ondevelop
, it was not introduced by the changes of this PR.G21
)Nice to have
Interpreter
classPath
classJob
classNot in scope for this PR
This PR is already large enough. Some shortcuts and less than ideal implementations were used to minimize the size of it. Listing them here as an acknowledgment of them and we'll open PRs later to address them individually.
g1
/g01
and all theT
)