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:
require("luacad")
andrequire "luacad"
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 with exported symbols | include <….scad> |
require "…" |
Use file but keep namespace separate | use <….scad> |
local module = require "…" |
2D
Description | OpenSCAD | LuaCAD |
---|---|---|
Create a circle |
circle(radius) |
circle(radius) |
Create a square with equal sides | square(size, center) |
square(size, center) |
Create a rectangle | square([width, height], center) |
square{width, height, center) |
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 cube with equal sides | cube(size, center) |
cube(size, center) |
Create a rectangular prism | cube([width, depth, height], center) |
cube{{width, depth, height}, center} |
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, faces, convexity) |
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:rotateExtrude(angle, convexity) |
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
Description | OpenSCAD | LuaCAD |
---|---|---|
Addition | n + m |
n + m |
Subtraction | n - m |
n - m |
Multiplication | n * m |
n * m |
Division | n / m |
n / m |
Modulo | n % m |
n % m |
Exponentiation | n ^ m |
n ^ m |
Less Than | n < m |
n < m |
Less or Equal | n <= m |
n <= m |
Equal | b == c |
b == c |
Not Equal | b != c |
b ~= c |
Greater or Equal | n >= m |
n >= m |
Greater Than | n > m |
n > m |
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 |
math.pi |
Smallest Integer |
|
math.mininteger |
Largest Integer |
|
math.maxinteger |
Biggest Number |
|
math.huge |
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] |
Dot notation indexing (x/y/z) | x = list.z; |
x = list.z |
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
Description | OpenSCAD | LuaCAD |
---|---|---|
Check if undefined | is_undef() |
x == nil |
Check if boolean | is_bool() |
is_bool() |
Check if number | is_num() |
is_num() |
Check if string | is_string |
is_str() |
Check if list | is_list() |
is_list() |
Check if function | is_function() |
is_func() |
Functions
Description | OpenSCAD | LuaCAD |
---|---|---|
Print message to console | echo(…) |
print(…) |
Force rendering | render(convexity) |
obj:render(convexity) |
Access child objects | children([idx]) |
children[idx] |
Assert condition is true | assert(condition, message) |
assert(condition, message) |
Concatenate vectors / lists | concat([1,2], [3,4]) |
concat({1,2}, {3,4}) |
Look up value in a table | lookup() |
lookup() |
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") (does not work for multi-byte characters) |
Search for value | search() |
string.find() |
Get version string | version() |
version() |
Get parent module name | parent_module(idx) |
debug.getinfo(2, "n").name |
Mathematical
Description | OpenSCAD | LuaCAD |
---|---|---|
Absolute value | abs() |
math.abs() |
Sign of value (-1, 0, 1) | sign() |
sign() |
Sine function | sin() |
math.sin() |
Cosine function | cos() |
math.cos() |
Tangent function | tan() |
math.tan() |
Arc cosine function | acos() |
math.acos() |
Arc sine function | asin() |
math.asin() |
Arc tangent function | atan() |
math.atan() |
2-argument arc tangent | atan2() |
math.atan2() |
Round down | floor() |
math.floor() |
Round to nearest | round() |
round() |
Round up | ceil() |
math.ceil() |
Natural logarithm | ln() |
math.log() |
Length of array | len() |
#array() |
Local variable declaration | let(x = 123) |
local x = 123 |
Base-10 logarithm | log(x) |
math.log(x, 10) |
Power function | pow(x, y) |
x ^ y |
Square root | sqrt() |
math.sqrt() |
Exponential function | exp() |
math.exp() |
Random numbers | rands(min, max, count, seed) |
math.randomseed(seed) |
Minimum value | min() |
math.min() |
Maximum value | max() |
math.max() |
Vector length/magnitude | norm() |
vector.length() |
Cross product of vectors | cross() |
vector.cross() |