Language Overview
m3dscad uses an OpenSCAD-like syntax with expression evaluation, user-defined symbols, and block-based geometry composition.
Calls And Modifiers
Function/module calls use parentheses. Modifiers like translate() can wrap a single call directly or a block of children.
sphere(r=1);
translate([2, 0, 0]) sphere(r=1);
translate([0, 0, 3]) {
sphere(r=1);
}
Variables
Variables are assigned with = and then referenced in later expressions.
radius = 1.5; height = 4; cylinder(r=radius, h=height, center=true);
Functions
User-defined functions return a single expression and can be used in parameters and other expressions.
function ring_r(base, wall) = base - wall;
difference() {
cylinder(h=2, r=2);
cylinder(h=2, r=ring_r(2, 0.4));
}
Anonymous Functions
Anonymous functions are expression values created with function(...). They can be assigned, passed to functions, returned, and called later.
add3 = function(x) x + 3;
echo(add3(2));
selector = function(which)
which == "add"
? function(x) x + x + 1
: function(x) x * x + 1;
echo(selector("add")(5));
Modules
User-defined modules package reusable geometry statements.
module post(z, r=0.6) {
translate([0, 0, z]) sphere(r=r);
}
post(0);
post(3);
If / Else
Conditionals choose which branch of geometry to evaluate. Note that they introduce their own scope, so assignments cannot escape.
use_big = true; if (use_big) sphere(r=2); else sphere(r=1);
For Loops
for loops iterate ranges/lists and emit geometry each iteration.
for (i = [0:3]) translate([i * 3, 0, 0]) sphere(r=1);
List Comprehension
List comprehensions build arrays from iteration expressions, which can then be indexed or reused.
values = [for (a = [1:4]) a * a]; radius = values[2]; sphere(r=radius);
3D Primitives
sphere
Creates a sphere solid centered at the origin.
sphere(r=1)
r: Sphere radius.
sphere_metaball
Creates a spherical metaball field contribution.
sphere_metaball(r=1)
r: Sphere radius.
sphere_sdf
Creates a sphere represented as an SDF.
sphere_sdf(r=1)
r: Sphere radius.
cube
Creates an axis-aligned box solid.
cube(size=1, center=false)
size: Edge length or per-axis size vector.center: If true, centers the cube at the origin.
cube_metaball
Creates an axis-aligned box as a metaball primitive.
cube_metaball(size=1, center=false)
size: Edge length or per-axis size vector.center: If true, centers the box at the origin.
cube_sdf
Creates an axis-aligned box represented as an SDF.
cube_sdf(size=1, center=false)
size: Edge length or per-axis size vector.center: If true, centers the box at the origin.
cylinder
Creates a cylinder, cone, or frustum solid along the Z axis.
cylinder(h=1, r | d | r1/r2 | d1/d2, center=false)
h: Height along Z.r: Uniform radius for both ends.d: Uniform diameter for both ends.r1: Radius at the first end (low Z if not centered).r2: Radius at the second end (high Z if not centered).d1: Diameter at the first end.d2: Diameter at the second end.center: If true, centers height around Z=0.
cylinder_metaball
Creates a cylinder-family primitive as a metaball.
cylinder_metaball(h=1, r | d | r1/r2 | d1/d2, center=false)
h: Height along Z.r: Uniform radius for both ends.d: Uniform diameter for both ends.r1: Radius at the first end.r2: Radius at the second end.d1: Diameter at the first end.d2: Diameter at the second end.center: If true, centers height around Z=0.
cylinder_sdf
Creates a cylinder-family primitive as an SDF.
cylinder_sdf(h=1, r | d | r1/r2 | d1/d2, center=false)
h: Height along Z.r: Uniform radius for both ends.d: Uniform diameter for both ends.r1: Radius at the first end.r2: Radius at the second end.d1: Diameter at the first end.d2: Diameter at the second end.center: If true, centers height around Z=0.
capsule
Creates a capsule solid with hemispherical end caps.
capsule(h=1, r=1, center=false)
h: Distance between cap centers along Z.r: Capsule radius.center: If true, centers the capsule around Z=0.
capsule_metaball
Creates a capsule as a metaball primitive.
capsule_metaball(h=1, r=1, center=false)
h: Distance between cap centers along Z.r: Capsule radius.center: If true, centers the capsule around Z=0.
capsule_sdf
Creates a capsule represented as an SDF.
capsule_sdf(h=1, r=1, center=false)
h: Distance between cap centers along Z.r: Capsule radius.center: If true, centers the capsule around Z=0.
line_join
Creates a rounded 3D tube-like solid around a polyline path.
line_join(points, r=1, norm="l2")
points: List of 3D points[[x, y, z], ...](at least two points).r: Join radius (non-negative).norm: Distance norm, either"l2"(euclidean) or"l1"(manhattan).
line_join(points=[[0,0,0], [2,0,0], [2,2,0]], r=0.25, norm="l2");
fn_solid
Creates a 3D solid by evaluating a function over bounded 3D coordinates.
fn_solid(min, max, fn)
min: 3D minimum corner vector[x, y, z].max: 3D maximum corner vector[x, y, z].fn: Function taking one coordinate vector[x, y, z]and returning bool.
fn_solid([-1,-1,-1], [1,1,1], function(c) norm(c) <= 1);
2D Primitives
circle
Creates a circle solid centered at the origin.
circle(r=1)
r: Circle radius.
circle_metaball
Creates a circle as a 2D metaball primitive.
circle_metaball(r=1)
r: Circle radius.
circle_sdf
Creates a circle represented as a 2D SDF.
circle_sdf(r=1)
r: Circle radius.
circle_hull
Creates a 2D convex-hull input primitive from a circle. Combine multiple hull primitives with union(), then convert the result with hull_solid() or hull_sdf().
circle_hull(r=1)
r: Circle radius. User=0to contribute a point to the convex hull instead of a rounded circle.behavior: Positive radii create a rounded arc hull; if all contributing radii are zero, the hull becomes the ordinary convex hull of the circle centers.
teardrop
Creates a centered 2D teardrop solid.
teardrop(radius=1)
radius(orr): Teardrop radius.
The tip direction is fixed to positive Y. Use rotate() to orient it differently.
square
Creates an axis-aligned rectangle solid in 2D.
square(size=1, center=false)
size: Edge length or per-axis size vector.center: If true, centers the rectangle at the origin.
square_metaball
Creates an axis-aligned rectangle as a 2D metaball primitive.
square_metaball(size=1, center=false)
size: Edge length or per-axis size vector.center: If true, centers the rectangle at the origin.
square_sdf
Creates an axis-aligned rectangle represented as a 2D SDF.
square_sdf(size=1, center=false)
size: Edge length or per-axis size vector.center: If true, centers the rectangle at the origin.
fn_solid (2D)
Creates a 2D solid from a boolean function over 2D coordinates.
fn_solid(min, max, fn)
min: 2D minimum corner vector[x, y].max: 2D maximum corner vector[x, y].fn: Function taking one coordinate vector[x, y]and returning bool.
fn_solid([-1,-1], [1,1], function(c) c.x*c.x + c.y*c.y <= 1);
polygon
Creates a 2D polygon solid from points and optional path indices.
polygon(points, paths, convexity=1)
points: Vertex list used by the polygon.paths: Optional index list(s) describing outer ring and holes.convexity: Compatibility parameter (currently unused for evaluation behavior).
polygon_mesh
Creates a 2D polygon boundary mesh from points and optional path indices.
polygon_mesh(points, paths, convexity=1)
points: Vertex list used by the polygon.paths: Optional index list(s) describing contours.convexity: Compatibility parameter (currently unused for evaluation behavior).
polygon_sdf
Creates a polygon as a 2D SDF by converting polygon mesh to SDF.
polygon_sdf(points, paths, convexity=1)
points: Vertex list used by the polygon.paths: Optional index list(s) describing contours.convexity: Compatibility parameter (currently unused for evaluation behavior).
polygon_hull
Creates a 2D convex-hull input from polygon vertices. This is equivalent to using circle_hull(r=0) at each exterior vertex, then converting the combined hull with hull_solid() or hull_sdf().
polygon_hull(points, paths, convexity=1)
points: Vertex list used by the polygon hull.paths: Optional index list(s). Only the first path is used; interior holes are ignored for hull construction.convexity: Compatibility parameter (currently unused for evaluation behavior).
image
Loads a bitmap image and creates a 2D boundary mesh from its foreground pixels.
image(file)
file(orfilename): Path to a PNG, JPEG, or GIF image. Relative paths are resolved from the file containing theimage()call, including calls inside files loaded withuse.
The top-left pixel is treated as background. Foreground pixels are inferred by comparing their colors with the image's mean color and its top-left color.
Each source pixel occupies one model unit in X and Y. Wrap the result in scale() to change its size.
smooth_sq(10)
image("../assets/logo.png");
hull_solid
Converts a 2D hull input into a solid. Hull inputs are typically built from circle_hull(), polygon_hull(), or mesh_to_hull().
hull_solid() { hull2d }
children: 2D hull child geometry.behavior: Rounded hull circles produce an arc hull; all-zero radii produce the ordinary convex hull of the contributing points.
hull_sdf
Converts a 2D hull input into an SDF.
hull_sdf() { hull2d }
children: 2D hull child geometry.behavior: Uses the same hull construction rules ashull_solid(), but preserves SDF output for downstream operations.
path
Parses an SVG path and creates a solid from its sampled curve mesh.
path(path, segments=1000)
path: SVG path string.segments: Number of line segments used for curve sampling.
path_mesh
Parses an SVG path and returns the sampled 2D mesh.
path_mesh(path, segments=1000)
path: SVG path string.segments: Number of line segments used for curve sampling.
path_sdf
Parses an SVG path and returns a 2D SDF.
path_sdf(path, segments=1000)
path: SVG path string.segments: Number of line segments used for curve sampling.
text
Creates filled 2D glyph outlines using the embedded Liberation Sans font or a font file.
text(text, size=10, font="Liberation Sans", halign="left", valign="baseline", spacing=1, segments=8)
text: Input text content to render.size: Font size scale.font:"Liberation Sans"(the embedded default),"Liberation Sans:style=Regular", or a path to a TTF/OTF font with TrueType outlines. Relative paths are resolved from the file containing the call, including calls inside files loaded withuse.halign: Horizontal alignment (left,center,right).valign: Vertical alignment (baseline,top,center,bottom).spacing: Additional spacing multiplier between glyphs.segments: Curve tessellation segments per glyph curve.
text("Custom font", font="../assets/custom.ttf");
text_mesh
Creates text outlines as a 2D mesh using the embedded Liberation Sans font or a font file.
text_mesh(text, size=10, font="Liberation Sans", halign="left", valign="baseline", spacing=1, segments=8)
text: Input text content to render.size: Font size scale.font: Embedded Liberation Sans or a font path, as described fortext().halign: Horizontal alignment (left,center,right).valign: Vertical alignment (baseline,top,center,bottom).spacing: Additional spacing multiplier between glyphs.segments: Curve tessellation segments per glyph curve.
text_sdf
Creates text outlines as a 2D SDF using the embedded Liberation Sans font or a font file.
text_sdf(text, size=10, font="Liberation Sans", halign="left", valign="baseline", spacing=1, segments=8)
text: Input text content to render.size: Font size scale.font: Embedded Liberation Sans or a font path, as described fortext().halign: Horizontal alignment (left,center,right).valign: Vertical alignment (baseline,top,center,bottom).spacing: Additional spacing multiplier between glyphs.segments: Curve tessellation segments per glyph curve.
CSG
For 2D and 3D meshes, all three CSG operations use unixpickle/meshbool to operate directly on mesh facets. This preserves vertices and flat surfaces instead of voxelizing the inputs. Mesh inputs should be closed, consistently oriented, and manifold. 3D mesh inputs, retained surface fragments, and outputs are limited to 10,000,000 triangles or fragments; invalid topology or excessive intersection complexity produces an evaluation error.
union
Combines child shapes of the same kind into one shape. Mesh children produce a geometric union with internal and overlapping facets removed, rather than simply concatenating their facets.
union() { ... }
children: One or more child shapes; all children must share the same shape kind.
difference
Subtracts every later child from the first child. This works directly on both 2D and 3D meshes as well as solids and SDFs.
difference() { a; b; ... }
children: At least one child shape of the same kind; the first is the minuend and the rest are subtrahends.
intersection
Keeps only the volume or area shared by all children, including 2D and 3D mesh children.
intersection() { ... }
children: One or more child shapes of the same kind.
Transforms And Extrusion
translate
Moves child geometry by a translation vector.
translate(v=[0,0,0]) { child }
v: Translation vector; for 2D children, Z must be 0.children: Exactly one child branch (or multiple children that union first).
scale
Scales child geometry per axis.
scale(v=[0,0,0]) { child }
v: Scale vector; for 2D children, Z must be 0.children: Exactly one child branch (or multiple children that union first).
rotate
Rotates child geometry using Euler angles or axis-angle form.
rotate(a, v) { child }
a: Either a scalar angle (degrees) or a 3-angle vector.v: Optional axis vector for axis-angle mode.children: Exactly one child branch (or multiple children that union first).
mirror
Reflects child geometry across the hyperplane orthogonal to a given axis.
mirror(v) { child }
v: Mirror axis vector. It need not be normalized, but it must be non-zero; for 2D children, Z must be 0.children: Exactly one child branch (or multiple children that union first).
transform
Applies a user-defined coordinate map to solid, SDF, or mesh children.
transform(min, max, fn) { solid_or_sdf }
transform(fn) { mesh }
min,max: Required bounds for solid/SDF output; vectors must match child dimensionality (2D or 3D).fn: Mapping function. For solids/SDFs, maps outer coordinates to inner coordinates; for meshes, maps old mesh coordinates to new coordinates.children: Solid, SDF, or mesh child geometry to transform.
slice
Takes the XY cross-section of a 3D solid at a given Z coordinate.
slice(z=0) { solid3d }
z: Z coordinate of the cross-section plane.children: 3D solid geometry to slice. Meshes and SDFs are not supported.
linear_extrude
Extrudes 2D geometry along Z, with optional twist and scale.
linear_extrude(height=1, center=false, twist=0, scale=1) { child2d }
height: Extrusion distance; aliash.center: If true, centers extrusion around Z=0.twist: Total twist in degrees across extrusion height.scale: End scale factor (scalar or 2D vector).children: 2D child geometry to extrude.
inset_extrude
Extrudes a 2D SDF along Z while applying inset or outset shaping at the top and bottom.
inset_extrude(height=1, center=false, bottom=0, top=0, bottom_fn="chamfer", top_fn="chamfer") { sdf2d }
height: Extrusion distance; aliash.center: If true, centers extrusion around Z=0.bottom: Bottom inset radius. Negative values produce an outset instead.top: Top inset radius. Negative values produce an outset instead.bottom_fn: Bottom profile function, either"chamfer"or"fillet". Defaults to"chamfer".top_fn: Top profile function, either"chamfer"or"fillet". Defaults to"chamfer".children: 2D SDF child geometry to extrude.
rotate_extrude
Revolves 2D solid geometry around the Z axis. For SDF children, a full 360-degree revolve preserves SDF output.
rotate_extrude(angle=360, start=0) { child2d }
angle: Sweep angle in degrees.start: Start angle in degrees.children: 2D solid or 2D SDF child geometry to revolve.SDF behavior: SDF children require a full 360-degree sweep; partial sweeps are unsupported.
Meshing And SDF
marching_squares
Converts a 2D solid into a mesh using marching squares search.
marching_squares(delta=0.02, subdiv=8) { child2d }
delta: Grid spacing for contour extraction.subdiv: Search subdivisions per cell.children: 2D solid child geometry to mesh.
marching_cubes
Converts a 3D solid into a mesh using marching cubes search.
marching_cubes(delta=0.02, subdiv=8) { child3d }
delta: Grid spacing for surface extraction.subdiv: Search subdivisions per cell.children: 3D solid child geometry to mesh.
dual_contour
Converts a 3D solid into a mesh using dual contouring.
dual_contour(delta=0.02, repair=true, clip=false) { child3d }
delta: Cell size for contouring.repair: Enables additional mesh repair pass.clip: Enables clipping behavior in contouring.children: 3D solid child geometry to mesh.
mesh_to_sdf
Converts a 2D or 3D mesh to an SDF of matching dimensionality.
mesh_to_sdf() { mesh }
children: Mesh child geometry to convert.
mesh_to_hull
Converts a 2D mesh into a convex-hull input by using each mesh vertex as a zero-radius hull point.
mesh_to_hull() { mesh2d }
children: 2D mesh child geometry.behavior: The resulting hull can be turned into geometry withhull_solid()orhull_sdf().
smooth_sq
Smooths a 2D mesh by moving its existing vertices to minimize squared segment lengths, producing more even boundary segments.
smooth_sq(iters) { mesh2d }
iters: Non-negative integer number of smoothing iterations.children: 2D mesh geometry, such as the result ofimage(),polygon_mesh(), ormarching_squares().behavior: Smoothing moves vertices but does not add segments. Larger iteration counts produce a smoother result and may change or shrink the outline.
decimate
Simplifies a manifold 3D triangle mesh using quadric error functions while preserving its topology.
decimate(triangles_fraction, min_det=1e-8, min_normal_dot_product=0, tikhonov_regularization=1e-5) { mesh3d }
decimate(triangle_count=N, min_det=1e-8, min_normal_dot_product=0, tikhonov_regularization=1e-5) { mesh3d }
triangles_fraction: Fraction of the input mesh's current triangle count to retain, from0to1. It can be passed positionally or by name.triangle_count: Named-only, non-negative integer target triangle count. Specify exactly one oftriangles_fractionandtriangle_count.min_det: Minimum QEF matrix determinant before treating the matrix as singular. Defaults tomodel3d.QEFDecimatorDefaultMinDet, currently1e-8.min_normal_dot_product: Minimum allowed dot product between old and replacement triangle normals, from-1to1. Defaults to0, preventing flips greater than 90 degrees.tikhonov_regularization: Non-negative regularization weight toward the original vertices. Defaults to1e-5.children: A manifold 3D mesh.
inset_sdf
Shrinks an SDF shape by an inward field offset.
inset_sdf(delta) { sdf }
delta: Inset amount.children: SDF child geometry.
outset_sdf
Expands an SDF shape by an outward field offset.
outset_sdf(delta) { sdf }
delta: Outset amount.children: SDF child geometry.
solid
Converts child mesh/SDF geometry back to solid representation.
solid() { child }
children: Child geometry to convert to solid.
Metaball
metaball
Converts an SDF into metaball form.
metaball() { sdf }
children: SDF child geometry to convert.
weight_metaball
Scales metaball weights during metaball composition.
weight_metaball(weight) { metaball }
weight: Multiplier for all child metaball weights (for negation, use-1).children: Exactly one metaball child to scale.
metaball_solid
Combines weighted metaballs into a solid using a thresholded falloff field.
metaball_solid(threshold, falloff="quartic") { metaballs... }
threshold: Isosurface threshold for solid extraction.falloff: Falloff kernel name (linear, quadratic, cubic, quartic, quintic, exponential, gaussian).children: One or more metaball child primitives.