lmcad user guide
Overview
lmcad is a native host for lmscript bytecode. Its schema exposes OpenCASCADE solids, a headless software renderer, PNG and APNG output, and STL/OBJ export. The schema is embedded in the executable, so every bytecode file passed to one invocation is checked against the same schema.
Install
Download the latest Linux x64 or Linux arm64 binary from GitHub Releases. To build from source, install C++17, CMake and Ninja, build OpenCASCADE 8.0.1 as a static prefix, then configure lmcad with -DLMCAD_OCCT_PREFIX=/path/to/prefix and -DLMCAD_FULL_STATIC=ON. The README build section has the exact build commands. Install lmscript with npm i -g @lmctl-ai/lmctl to compile examples.
Concepts
- Schema: the embedded JSON declares typed context, functions and methods. lmcad --schema --json prints those bytes.
- Solid: methods on Shape return handles to edited OpenCASCADE shapes; volume and bounding-box accessors query the solid.
- Sketch: chain point(x,y) calls, close the polygon, then extrude or revolve it.
- Animation: create an Animation, render the current scene with add_frame(), then call finish() to write APNG.
- Collections: CSV input returns Keyframes; iterate with for (key in keys) or an indexed range and at(i).
Reference
The following canonical member list is the output of lmcad --schema; it is grouped by declared type.
Context
scene: Scene
Functions
material() -> Material
read_keyframes_csv(string) -> Keyframes
Animation
Animation.add_frame() -> Animation
Animation.finish() -> void
Camera
Camera.clipping(float, float) -> Camera
Camera.look_at(float, float, float, float, float, float) -> Camera
Keyframe
Keyframe.b() -> float
Keyframe.g() -> float
Keyframe.r() -> float
Keyframe.time() -> float
Keyframe.x() -> float
Keyframe.y() -> float
Keyframe.z() -> float
Keyframes
Keyframes.at(int) -> Keyframe
Keyframes.len() -> int
Light
Light.intensity(float) -> Light
Material
Material.color(float, float, float) -> Material
Material.roughness(float) -> Material
Scene
Scene.ambient(float) -> Scene
Scene.animation(string, int, int, int) -> Animation
Scene.assert_close(float, float, float) -> void
Scene.background(float, float, float) -> Scene
Scene.box(float, float, float, Material) -> Shape
Scene.camera(float, float, float, float, float, float, float) -> Camera
Scene.cylinder(float, float, Material) -> Shape
Scene.directional_light(float, float, float, float) -> Light
Scene.export_obj(string) -> void
Scene.export_stl(string) -> void
Scene.extrude(Sketch, float, Material) -> Shape
Scene.fill_light(float, float, float, float) -> Light
Scene.fit_camera(float, float) -> Camera
Scene.render_png(string, int, int) -> void
Scene.render_ppm(string, int, int) -> void
Scene.revolve_y(Sketch, Material) -> Shape
Scene.sketch() -> Sketch
Scene.sphere(float, Material) -> Shape
Scene.supersample(int) -> Scene
Shape
Shape.chamfer(float) -> Shape
Shape.color(float, float, float) -> Shape
Shape.cut(Shape) -> Shape
Shape.fillet(float) -> Shape
Shape.hollow(float) -> Shape
Shape.hollow_top(float) -> Shape
Shape.intersect(Shape) -> Shape
Shape.max_x() -> float
Shape.max_y() -> float
Shape.max_z() -> float
Shape.min_x() -> float
Shape.min_y() -> float
Shape.min_z() -> float
Shape.mirror(string) -> Shape
Shape.name(string) -> Shape
Shape.position(float, float, float) -> Shape
Shape.rotate(float, float, float) -> Shape
Shape.scale(float, float, float) -> Shape
Shape.translate(float, float, float) -> Shape
Shape.union(Shape) -> Shape
Shape.visible(bool) -> Shape
Shape.volume() -> float
Sketch
Sketch.close() -> Sketch
Sketch.point(float, float) -> Sketch
CLI contract:
- lmcad --schema
- Prints a compact registry-derived summary, context first and then functions and type members.
- lmcad --schema --json
- Prints the embedded schema bytes, byte-for-byte.
- lmcad --dsl-signatures
- Prints canonical registry signatures for comparison with lmscript --dsl-signatures schema.json.
- lmcad --dsl FILE [FILE ...]
- Runs bytecode files in order. Objects and scene state persist between files; VM locals are fresh for each file. The first failure stops execution.
Exit 0 means success; exit 2 means invalid command-line syntax; exit 3 means bytecode load or DSL/host run failure; exit 4 is an application failure. Successful runs emit one JSON result line per completed block.
Output formats
- PNG: still images and numbered animation frames.
- APNG: animated PNG with frame count and playback timing stored in the file.
- STL: binary triangle mesh for solid-printing workflows.
- OBJ: text mesh output.
- PPM: simple RGB raster output.
Tasks
- Render an image: make a camera, add lights, then call scene.render_png(path, width, height).
- Fit a camera: call scene.fit_camera(fov, margin); explicit camera look-at or clipping settings turn off automatic fitting.
- Assert a model value: call shape.volume() and scene.assert_close(actual, expected, tolerance).
- Export a solid: call scene.export_stl(path) or scene.export_obj(path).
- Create an animation: use scene.animation(path, width, height, fps), add frames after each scene update, and finish the writer.
Limits
Host-side checks require finite, positive geometry dimensions and valid cameras. Render dimensions must be positive and bounded. Supersampling is limited to 1–4; each high-resolution raster dimension is at most 8192 and the working image has at most 16,777,216 pixels. APNG output is limited to 240 frames and 64,000,000 total frame pixels. A 36-frame 1920×1080 animation exceeds that total-pixel bound. The VM itself does not impose execution, stack, local-variable or string-size budgets; scripts should be treated as trusted inputs.
Troubleshooting
- Schema mismatch: compile with the schema file matching this executable; inspect lmcad --schema --json.
- No camera: every render needs a camera or a successful camera fit.
- Compiler rejects names or types: compare against the canonical signatures above and use explicit float(i) when passing an integer to a float parameter.
- OCCT operation fails: reduce fillet or shell size and check that the model has valid positive dimensions.
- Animation output is absent: call finish(); an unfinished animation is discarded.