This page is a reference guide for converting OpenSCAD code to LuaCAD. While Lua is generally a very simple and approachable language, some syntax features might be a little surprising to OpenSCAD users and are highlighted in yellow here.
One of the biggest differences is that parentheses are optional when calling functions in Lua
and the argument is either a string or a {…} block (also called a table).
So following statements are equivalent:
circle({r = 5})andcircle{r = 5}
Furthermore code is usually written with a method chaining syntax, which puts the focus on the object being manipulated rather than the function being called. This makes it easier to read and understand the code.
- OpenSCAD:
translate([1, 2, 3]) rotate([0, 0, 90]) cube([1, 1, 1]) - LuaCAD:
cube{size={1, 1, 1}}:rotate(0, 0, 90):translate(1, 2, 3)
Syntax
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Variable assignment | x = value; |
x = value |
| Conditional expression | x = cond ? true_val : false_val; |
x = cond and true_val or false_val |
| Function definition | x = function (a) a + a; |
x = function (a) return a + a end |
| Module definition and usage | module name(…) { |
function name(…) |
| Function definition and usage | function name(…) = … |
function name(…) return … end |
| Include file | include <….scad> |
dofile("….lua") |
| Use file as module | use <….scad> |
local module = require "…" |
2D
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Create a circle |
circle(radius) |
circle(radius) |
| Create a rectangle | square([width, height], center) |
square{{width, height}, center=true} |
| Create a polygon from points | polygon([points]) |
polygon{points} |
| Create a polygon with paths | polygon([points], [paths]) |
polygon{points, paths} |
| Create text |
text(t, size, font,
|
text(t, {size=size, font=font, ...}) |
| Import 2D file (DXF/SVG) |
import("….extformats: DXF|SVG", convexity)
|
import("file.dxf", convexity) |
| Project 3D model to 2D | projection(cut) |
obj:projection(cut) |
3D
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Create a sphere |
sphere(radius) |
sphere(radius) |
| Create a rectangular prism | cube([width, depth, height], center) |
cube{{width, depth, height}, center=true} |
| Create a cylinder | cylinder(h, r|d, center) |
cylinder(h, r, center)cylinder{h=h, d=d, center=center} |
| Create a truncated cone | cylinder(h, r1|d1, r2|d2, center) |
cylinder(h, r1, r2, center)cylinder{h=h, d1=d1, d2=d2, center=center}
|
| Create a polyhedron | polyhedron(points, faces, convexity) |
polyhedron{points=pts, faces=fcs} |
| Import 3D file (STL/etc) |
import("….extformats: STL|OFF|AMF|3MF", convexity)
|
import("file.stl", convexity) |
| Extrude 2D shape into 3D | linear_extrude(height, center, convexity, twist, slices) |
obj:linear_extrude(height, {center=center, ...}) |
| Rotate 2D shape around Y axis | rotate_extrude(angle, convexity) |
obj:rotate_extrude(angle, segments) |
| Create a 3D surface from heightmap |
surface(file = "….extformats: DAT|PNG", center, convexity)
|
surface("file.png", center, convexity) |
Boolean operations
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Combine objects | union() { obj1; obj2; } |
obj1 + obj2 |
| Subtract objects | difference() { obj1; obj2; }
|
obj1 - obj2 |
| Keep overlapping parts | intersection() { obj1; obj2; } |
obj1 & obj2 |
Transformations
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Move object | translate([x, y, z]) |
obj:translate(x, y, z) |
| Rotate around each axis sequentially | rotate([x, y, z]) |
obj:rotate(x, y, z) |
| Rotate around vector | rotate(a, [x, y, z]) |
obj:rotate(a, {x, y, z}) |
| Scale object | scale([x, y, z]) |
obj:scale(x, y, z) |
| Resize object to absolute dimensions | resize([x, y, z], auto, convexity) |
obj:resize{{x, y, z}, auto, convexity} |
| Mirror object across plane | mirror([x, y, z]) |
obj:mirror(x, y, z) |
| Apply transformation matrix | multmatrix(m) |
obj:multmatrix(m) |
| Apply color by name | color("colorname", alpha) |
obj:color("colorname", alpha) |
| Apply color by hex value |
color("#rgb|#rrggbb")
|
obj:color("#rgb|#rrggbb")
obj:color("#rgba|#rrggbbaa")
|
| Apply color by RGBA values | color([r, g, b, a]) |
obj:color(r, g, b, a) |
| Offset 2D shape | offset(r|delta, chamfer) |
obj:offset(r, chamfer) |
| Create hull around objects | hull() |
obj:hull() |
| Minkowski sum of objects | minkowski() |
obj:minkowski() |
Modifier Characters
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Disable | * |
s(…) |
| Show only | ! |
o(…) |
| Highlight / debug | # |
d(…) |
| Transparent / background | % |
t(…) |
Math Operators
Arithmetic operators are the same in both languages:
+, -, *, /,
%, ^.
Comparison operators <, <=,
==, >=, >
are also identical.
The differences are:
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Not Equal | b != c |
b ~= c |
| Logical And | b && c |
b and c |
| Logical Or | b || c |
b or c |
| Negation | !b |
not b |
Constants
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Undefined value | undef |
nil |
| Mathematical constant π (~3.14159) | PI |
PI |
Special variables
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Minimum angle | $fa |
settings.fa |
| Minimum size | $fs |
settings.fs |
| Number of fragments | $fn |
settings.fn |
| Animation step | $t |
settings.t |
| Viewport rotation angles in degrees | $vpr |
settings.vpr |
| Viewport translation | $vpt |
settings.vpt |
| Viewport camera distance | $vpd |
settings.vpd |
| Viewport camera field of view | $vpf |
settings.vpf |
| Number of module children | $children |
settings.children |
| True in preview mode, false for render | $preview |
settings.preview |
Lists
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Create a list | list = […, …, …]; |
list = {…, …, …} |
| Index a list (Lua is 1-indexed) | x = list[2]; |
x = list[3] |
List Comprehensions
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Generate array with values | [ for (i = range|list) i ] |
local result = {}
|
| Generate with for loop | [ for (init;condition;next) i ] |
local result = {}
|
| Flatten array | [ each i ] |
table.unpack(table) |
| Filter array with condition | [ for (i = …) if (condition(i)) i ] |
local result = {}
|
| Conditional values in comprehension | [ for (i = …) if (condition(i)) x else y ] |
local result = {}
|
| Local assignments in comprehension | [ for (i = …) let (assignments) a ] |
local result = {}
|
Flow Control
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| For loop with range | for (i = [start:end]) { … } |
for i = start, stop do … end |
| For loop with step | for (i = [start:step:end]) { … } |
for i = start, stop, step do … end |
| For loop with list | for (i = […,…,…]) { … } |
for _, i in ipairs({…,…,…}) do … end |
| For loop with multiple variables | for (i = …, j = …, …) { … } |
for _, item in ipairs(list) do local i, j = item[1], item[2] … end |
| Intersect multiple iterations | intersection_for(i = [start:end]) { … } |
local models = {} for i = start, stop do table.insert(models, …) end cad.intersection(models)
|
| Intersect with step | intersection_for(i = [start:step:end]) { … }
|
local models = {} for i = start, stop, step do table.insert(models, …) end cad.intersection(models)
|
| Intersect list iterations | intersection_for(i = […,…,…]) { … } |
local models = {} for _, i in ipairs({…,…,…}) do table.insert(models, …) end cad.intersection(models)
|
| Conditional execution | if (…) { … } |
if … then … end |
| Local variable definition | let (…) { … } |
local … = … … |
Type test functions
is_bool(), is_num(), and is_list()
use the same name in both languages. The differences:
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Check if undefined | is_undef(x) |
x == nil |
| Check if string | is_string(x) |
is_str(x) |
| Check if function | is_function(x) |
is_func(x) |
Functions
Some functions use the same signature:
assert, lookup, version,
concat.
Note that concat uses {} tables
instead of [] arrays.
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Print message to console | echo(…) |
print(…) |
| Force rendering | render(convexity) |
obj:render_node(convexity) |
| Convert to string | str(123) |
tostring(123) |
| Get character from code | chr(65) |
string.char(65) |
| Get code from character | ord("a") |
string.byte("a") |
| Search for value | search() |
string.find() |
| Get parent module name | parent_module(idx) |
debug.getinfo(2, "n").name |
Mathematical
Most math functions use the same name and signature in both languages:
abs, sign,
sin, cos, tan,
asin, acos, atan, atan2,
floor, ceil, round,
sqrt, exp, ln, log,
min, max,
rands, norm, cross.
Trig functions use degrees in both languages.
| Description | OpenSCAD | LuaCAD |
|---|---|---|
| Length of array | len(list) |
#list |
| Local variable declaration | let(x = 123) |
local x = 123 |
| Power function | pow(x, y) |
pow(x, y) or x ^ y |