OpenSCAD
Program OpenSCAD slouží k modelování 3D modelů nejen pro 3D tiskárny. Je to program umožňující CSG modelování deklarativním zápisem – kódem.

Vyčerpávající manuál v angličtině použijte jako referenci.
CSG modelování
CSG modelování (Constructive Solid Geometry) je vektorové modelování grafických prvků, v našem případě 3D modelů. Základní primitiva (koule, kužel/válec, kvádr…) se skládají do CSG stromu pomocí hran transformací (posun, škálování, rotace…) a uzlů booleovských operací (rozdíl, průnik, sloučení).
Na obrázku vidíte ilustraci CSG stromu. Zde jsou pro zjednodušení primitivy již otočené.

OpenSCAD umožňuje takové stromy zapsat pomocí kódu a vyrenderovat z nich výsledný 3D model ve formě triangulární meshe (o té se budeme učit později).
Uživatelské rozhraní
Okno programu se skládá ze tří částí:
- Editor
- (vlevo) V něm píšete zdrojový kód modelu.
- Náhled
- (vpravo) 3D plátno, kde uvidíte náhled modelu.
- Konzole
- (vpravo dole) V konzoli je vidět chybový a ladící výstup.
Po napsání kódu do editoru je třeba model „zkompilovat“. Existuje rychlý (ne vždy přesný) náhled pomocí OpenGL (Design → Zobrazit, F5) a plnohodnotný render do 3D modelu pro export (počítá se bohužel na procesoru, Design → Vyrenderovat, F6). V nabídce Design lze zapnout i Automaticky načítat a zobrazovat, po uložení se pak provede náhled automaticky.
V nabídce Zobrazit najdete spousto možností pro zobrazení náhledu, doporučujeme zapnout osy a pravítko.
Pro pohyb modelem později použijete myš (vyzkoušejte různá tlačítka).
Abyste něco viděli, potřebujete ale zdrojový kód. Můžete si vybrat z pestré nabídky Soubor → Příklady.
Syntax
Syntaxe je hned na první pohled velmi podobná C/C++/Javě – obsahuje středníky, chlupaté závorky, komentáře se píší stejně.
Kromě jiného můžete psát čísla
(buď celá, nebo s plovoucí desetinnou čárkou (zápis pomocí tečky nebo vědecky)) – 1
, 0
, -5
, 5.3
, 9.99998
, 185e-5
;
vektory/souřadnice v hranatých závorkách – [1, 2, 3]
; řetězce ve "dvojitých uvozovkách"
, boolean true
/false
.
Můžete používat proměnné (které se nedeklarují, ale chovají se nestandardně,
k tomu se dostaneme dále), matematické
výrazy
a
funkce,
konstantu PI
…
Varování:
Nenechte se syntaxí zmást, nejedná se o programovací, ale deskriptivní jazyk! To znamená, že jednotlivé příkazy a výrazy se nedějí postupně odshora dolů, ale spolu najednou popisují výsledek – CSG strom.
Primitiva
cube(size, center);
- kvádr (
size=[1, 2, 3]
) nebo krychle (size=5
) sphere(r);
- koule (lze použít
r
– poloměr nebod
– průměr) cylinder(…);
- (komolý) kužel (
h, r1, r2, center
) nebo válec (h, r, center
) polyhedron(…);
- mnohostěn, nízkoúrovňová primitiva popisující přímo triangulární mesh
cube(150, center=true); 1
sphere(100); 2
- vycentrovaná krychle o hraně délky 150 (všimněte si, že argumenty se dají předávat pozičně i pomocí jména)
- koule o poloměru 100

Transformace
Když už umíte vytvářet primitivní geometrická tělesa, je dobré naučit se s nimi provádět jednotlivé transformace.
scale()
- škáluje objekt o zadanou konstantu nebo vektor tří hodnot
resize()
- škáluje objekt na zadanou velikost
rotate()
- objekt otáčí o úhel zadaný ve stupních, použije se jako
rotate([deg,deg,deg])
neborotate(deg,[1,1,0])
translate([x, y, z])
- relativní posun objektu
mirror([x, y, z])
- překlopí (zrcadlí) objekt podle počátkem procházející roviny se zadaným normálovým vektorem,
např.
[1, 0, 0]
zrcadlí podle roviny YZ; zrcadlený objekt se neduplikuje multmatrix([[…]])
- transformační matice velikosti 4×4, nízkoúrovňové
color(…)
- obarví objekt zadanou barvou, funguje jen v náhledu
Transformace se aplikují zápisem před objekt, který chcete transformovat:
transformace() objekt();
. Dají se také řetězit, jsou aplikované postupně od
„nejbližší“ po nejvzdálenější. Dají se aplikovat i na více objektů současně,
zabalením objektů do chlupatých závorek a předsazením před ně.
transformace() {
objekt1();
objekt2();
}
Důležité:
Veškeré operace (snad kromě barvy) se dějí kolem počátku souřadnic. Např. pokud objekt leží někde mimo počátek a vy jej otočíte, jeho poloha se změní.
color("green") rotate([0,0,60]) translate([30,0,0]) cube(5); 1
color("red") translate([30,0,0]) rotate([0,0,60]) cube(5); 2
- Kostka se nejprve posune, poté otočí kolem počátku a nakonec obarví
- Kostka se nejprve otočí kolem počátku, poté posune a nakonec obarví

Booleovské operace
Základem CSG modelování jsou tři boolovské operace:
union()
– sloučení- z více objektů udělá jeden (pokud by měl mít výsledný CSG strom více kořenů, provede se na nich implicitně)
difference()
– rozdíl- od prvního objektu odečte všechny další
intersection()
– průnik- zůstane pouze společná část všech objektů
union() {
cube(150, center=true);
sphere(100);
}

difference() {
cube(150, center=true);
sphere(100);
}

intersection() {
cube(150, center=true);
sphere(100);
}

Všechny tyto operace nemají žádné argumenty, ale zpracují libovolný počet objektů. Takovým objektům se říká children dané operace. Česky to znamená děti, ale my tento pojem raději překládat nebudeme.
Použití proměnných
Není nutné všude používat hodnoty přímo, v OpenSCADu se dají používat i proměnné.
awesome = 42;
cylinder(h=awesome, r=awesome/2);
Mějte ale na paměti fakt, že všechno se děje zároveň. Proměnou proto nelze předefinovat, respektive lze, ale chová se to jinak, než jste zvyklí.
awesome = 42;
echo(awesome); 1
awesome = 4242; 2
echo(awesome);
- funkce echo vypisuje ladící informace do konzole
- přenastavení, co se stane?
Výsledkem je dvakrát vypsané ECHO: 4242
🤯
Důvodem je to, že nezáleží, kdy proměnnou nastavíte, její hodnota platí v celém
scopu. Pokud proměnnou nastavíte v jednom scopu dvakrát, platí později uvedená
hodnota, to berte ale jen jako implementační detail a nikdy to nedělejte.
Varování:
Ze stejného důvodu nemůžete použít a = a + 1;
a syntaxe pro
a += 1;
ani neexistuje (jedná se o syntaktickou chybu).
Pomůže o proměnných uvažovat jako o konstantách pro daný scope. Zatím známe jen jeden (globální) scope, ale to se brzy změní.
Cykly
Two or more, use a for.
Syntaxe foru je kapku odlišná od C a vypadá asi takto:
for (var = [...]) { 1
... 2
}
- hlavička cyklu, do proměnné přiřadíme vektor
- v těle cyklu proměnná
var
nabývá hodnot z použitého vektoru
Zastavme se na chvíli u zápisu vektorů, které jde zapsat několika způsoby:
- výčtem
var = [-1, 1]
– hodnoty -1 a 1- intervalem
var = [0 : 5]
– celá čísla od 0 do 5, obě meze jsou použity- intervalem se skokem
var = [0 : 0.2 : 5]
– hodnoty od 0 do 5 (včetně), použije se krok 0,2
Toho často využijeme v zápisu cyklu for.
for (i = [0:10:100]) echo(i); // => ECHO 10, 20, 30...
intersection_for(n = [1 : 6]) {
rotate([0,0,n*60]) translate([5,0,0]) sphere(12);
}

Cykly lze samozřejmě do sebe vnořovat, existuje k tomu i zkratka.
for (xpos=[0:3]) {
for (ypos=[2,4,6]) { 1
...
}
}
for (xpos=[0:3], ypos=[2,4,6]) { 2
...
}
- Vnořený cyklus
- Zkratka (syntactic sugar) pro vnořený cyklus
Vzhledem k tomu, jak cyklus for v OpenSCADu funguje, zde vypichujeme několik informací, na které pozorný čtenář jistě již přišel sám:
- Každá „iterace“ cyklu má vlastní scope, jakékoliv nastavení proměnných v další iteraci (a také po skončení cyklu) pozbývá platnosti.
- Z předchozího bodu plyne, že v cyklu se nedá nic iterativně počítat, je možné pouze použít matematické výrazy s řídící proměnnou.
- Cyklus while nedává v OpenSCADu smysl a tedy neexistuje.
Podmínky
OpenSCAD obsahuje dva druhy podmínek: if a ternární operátor.
if, else if, else
Syntaxe podmínky if není překvapující (chlupaté závorky jsou volitelné):
if (...) { 1
... 2
} else if (...) { 3
... 4
} else { 5
... 6
}
- pravdivostní výraz (např.
a > b
,0
,true
,len(vec) != 42
) - vlastní scope!
- volitelná větev s jinou podmínkou
- vlastní scope!
- volitelná větev, když žádná podmínka neplatí
- vlastní scope!
Jednotlivé větve podmínky mají vlastní scope. To znamená, že není následující kód může mít pro někoho překvapující výsledek:
num = 42;
if (num > 0) {
sign = 1;
} else if (num < 0) {
sign = -1;
} else {
sign = 0;
}
echo(sign); // WARNING: Ignoring unknown variable 'sign'.
Tuto vlastnost OpenSCADu lze obejít jedině ternárním operátorem.
Ternární operátor
Ternární operátor, je jediný způsob, jak podmíněně nastavit nějakou hodnotu s dlouhodobou platností.
num = 42;
// var = test ? TrueValue : FalseValue;
sign = num > 0 ? 1 : (num < 0 ? -1 : 0); 1
echo(sign); // ECHO: 1
- Zde noříme operátory do sebe
Funkce
Podobně jako ternární operátor se zapisují funkce. Funkce nevytváří části CSG stromu, pouze počítají nějakou hodnotu ze svého vstupu. Jsou to jednovýrazové zkratky.
function name ( parameters ) = expression;
Funkcemi se v tomto kurzu moc nezabýváme, ale zvídaví studenti je mohou samozřejmě používat. Více o funkcích v manuálu.
Moduly
Ekvivalentem k funkci pro CSG strom je modul. Modul se více podobá funkcím, jak je známe z programovacích jazyků, s tím rozdílem, že nevrací žádnou hodnotu, ale uzel (či hranu) CSG stromu.
Laicky řečeno: modul něco „nakreslí“ tam, kde se použije.
Stejně jako funkce, přijímá modul parametry,
které mohou nabývat výchozích hodnot.
Navíc může přijímat (zpracovávat) children()
.
Moduly (a funkce) mohou existovat v samostatných souborech (knihovnách),
ve vlastním souboru s modelem můžete použít use
nebo
include
:
use <lib.scad>;
- dá k dispozici moduly a funkce ze souboru
lib.scad
include <lib.scad>;
- na místo vloží celý soubor
lib.scad
(případné objekty se rovnou vykreslí)
module rounded_cylinder(h=20, r=5, center=false) {
baseh = h-2*r;
translate([0, 0, center ? -baseh/2 : r]) {
cylinder(h=baseh, r=r);
sphere(r);
translate([0, 0, baseh]) sphere(r);
}
}
// pro zobrazení musíte modul zavolat
rounded_cylinder(center=true);

children()
Kromě modulů, které vytvářejí tvary jen na základě vstupních parametrů
(argumentů), jdou vytvářet i moduly, které přijímají children()
.
Používá se to na modifikování nebo zakomponování libovolného objektu.
children()
- reprezentuje všechny předané objekty
children(n)
- reprezentuje n-tý předaný objekt
children([n1, …, nx])
- reprezentuje n-první až n-x-tý předaný objekt
$children
- magická (s dolarem) konstanta s počtem předaných objektů
children([1 : 2 : $children])
- každý druhý předaný objekt
children()
nějakou operacimodule elongate() {
scale([10 , 1, 1])
children();
}
elongate() {
sphere(30);
cube(45, center=true);
cylinder(r=10, h=50);
}

elongate()
Debugging
Pro debugging modelů je dobbré naučit si několik modifikátorů:
%
- F5 vykreslí uzel poloprůhledně, F6 vůbec
#
- F5 vykreslí uzel poloprůhledně a červeně, F6 normálně
!
- F5 i F6 zobrazí pouze tento uzel
*
- F5 i F6 tento uzel bude ignorovat
#
difference() {
sphere(45);
#cube(65, center=true);
}

#
Pomocníčci
Varování:
Zde zhruba končí obsah druhého cvičení a pokračuje obsah třetího.
Speciálními operacemi v OpenSCADu jsou minkowski()
a hull()
.
Pomocí nich můžete vyvářet složité tvary,
které by se jinak vytvářely velice obtížně.
Minkowského suma
Minkowského suma je množinová operace, kdy všechny body z jedné množiny sečtete se všemi body z druhé množiny. Nejlépe to vystihuje následující obrázek:
Můžete si to představit tak, že jeden z objektů uchopíte za počátek souřadný a objíždíte s ním po povrchu druhého objektu, zanechávajíc za sebou stopu. Jedná se o operaci komutativní a asociativní, je tedy jedno, kterým objektem jezdíte po kterém. V praxi se tato operace používá většinou s koulí pro zaoblení, ale pozor, zaoblený objekt se zvětší.
minkowski()
minkowski() {
cube(300);
sphere(30);
}

minkowski()
Varování:
Vypočtení minkowského sumy může trvat velmi dlouho.
Konvexní obal
Konvexní obal (convex hull) objektů je takový nejmenší konvexní objekt, který pojme všechny objekty v něm. Opět se jedná o komutativní a asociativní množinovou operaci.
hull()
hull() {
cube(100);
sphere(30);
}

hull()
Varování:
Vypočtení konvexního obalu může trvat celkem dlouho.
Dvourozměrný subsystém
Zatím jsme vytvářeli jen trojrozměrné objekty. V OpenSCADu se dá ale využít dvourozměrný subsystém, ve kterém se pracuje jen na jedné rovině.
V 2D subsystému je možné vyvářet 2D primitiva:
circle()
, square()
a polygon()
.
Pomocí linear_extrude()
nebo rotate_extrude()
jde z 2D objektu vytvořit 3D objekt.
Naopak projection()
slouží k projekci 3D objektů do 2D.
Když pracujete ve 2D subsystému, lze použít vše, co již znáte,
jen API některých operací se náležitě změní
(např. translate()
bere vektor 2 hodnot, rotate()
bere jen jeden úhel…).
hull() {
rotate(45) square([25, 15]);
translate([12, 7]) circle(7);
}

Operace hull()
a minkowski()
jsou ve 2D subsystému relativně rychlé.
Pokud to jde, je tedy lepší provádět je v něm.
2D primitiva
square()
- alternativa ke
cube()
circle()
- alternativa ke
sphere()
polygon()
- alternativa k
polyhedron()
offset()
K zaoblení dvourozměrných tvarů lze použít offset()
.
Ten má několik způsobů použití:
linear_extrude()
Operace linear_extrude()
vytáhne 2D tvar do prostoru a vytvoří tedy 3D tvar.
Lze nastavit několik parametrů:
height
- výška vytažení
center
false
vytahuje jen nahoru,true
na oba směry (každý o polovinu výšky)twist
- o kolik stupňů se 2D tvar při vytažení otočí
slices
- počet kroků u
twist
scale
- kolikrát se 2D tvar při vytažení zvětší
convexity
- hodnota ovlivňující náhled; kuchař radí: „nevíš-li, dej tam 10“
linear_extrude()
linear_extrude(height=20, twist=180, slices=100, center=true) {
square(5);
square(5, center=true);
}

linear_extrude()
rotate_extrude()
Další možností, jak převést 2D tvar na 3D tvar, je rotovat ho.
K tomu slouží rotate_extrude()
, které rotuje 2D tvar do prostoru.
Rotace probíhá kolem osy Y, ale objekt se „vzpřímí“ kolem osy Z (dodnes nevíme proč).
rotate_extrude()
rotate_extrude()
polygon(points=[[0,0],[20,10],[10,20],[10,30],[30,40],[0,50]]);

rotate_extrude()
projection()
Projekce (projection()
) promítne 3D objekt na rovinu XY.
Parametr cut
umožní použít jen průnik s rovinou XY.
Výsledkem projekce je vždy 2D tvar;
ten pak můžete využít opět k vytvoření 3D tvaru.
projection()
projection(cut=true)
translate([0, 0, -15])
rotate([45, 0, 0])
cylinder(r1=0, r2=500, h=500);

projection()
import()
Pro použití již existujících 2D nebo 3D tvarů můžete použít import()
,
pomocí něhož lze do CSG stromu vložit STL a DXF soubory.
Argumentem je cesta k souboru (relativní či absolutní).
Při importování 2D tvarů (DXF) si dejte především pozor na výslednou velikost,
je vhodné použít resize()
.
rotate_extrude()
resize([20, 0], auto=[false, true])
import("bottle.dxf");

Importované soubory lze využít k jakýmkoliv dalším operacím. Cizí STL soubory se ne vždy povedou vyrenderovat, je třeba je nejprve opravit, k tomu se dostaneme ve cvičení o opravě meshe.
difference() {
import("kangaroo.stl"); // http://www.thingiverse.com/thing:33273 CC BY-NC-SA
translate([0, -10, 80])
cube(30, center=true);
}

surface()
Alternativním způsobem využité externích souborů je surface()
,
který slouží k převodu obrázků do výškové mapy.

surface(file="smiley.png", center=true);
© Torsten Paul (CC BY-SA)Rozlišení
Jistě jste si všimli, že kulaté věci jsou v OpenSCADu hranaté. Čím menší jsou, tím je to více poznat.

Pomocí speciálních proměnných $fn
, $fa
a $fs
lze rozlišení měnit,
viz manuál.
V praxi se nejčastěji nastavuje proměnná $fn
,
která nastaví absolutní počet hran na kruh (minimálně 3).
Tvary jsou vytvořené tak, že zadaná velikost je velikost opsané kružnice.
Proměnou $fn
lze využít například k vytvoření n-úhelníku.
Tyto speciální proměnné se mohou nastavit globálně, ve scopu nebo argumentem libovolné operaci, primitivu či modulu. Při vytváření modulů není třeba tyto proměnné uvádět v předpisu.

for (fn=[1:10]) translate([fn*2.1,0,0]) circle($fn=fn);
Simple – 2-Manifold
Pro správný export STL souboru je potřeba,
aby byl model Simple – 2-Manifold.
To mj. znamená, že stěny modelu se nemohou všelijak protínat.
Skoro všechny možné problémy řeší výsledný implicitní union()
.
Nějaké problémy ale přece jen můžou vzniknout,
například při nesprávném použití polyhedronu.
Jedním z problémů, který může nastat jednoduše, je společná hrana dvou objektů. Pokud si představíte dvě kostky (např. z obrázku níže), v reálném světě nemohou mít společnou hranu. Buďto jde „projít“ z jedné kostky do druhé, nebo „jde projít“ mezi nimi; jinými slovy buďto to jsou dvě kostky nebo jedna dvoukostka.

cube(20);
translate([20, 20, 0]) cube(20);
e=0.0001;
cube(20);
translate([20-e, 20-e, 0]) cube(20);
e=0.0001;
cube(20);
translate([20+e, 20+e, 0]) cube(20);
Knihovna MCAD
Pomocí modulů lze pro OpenSCAD vytvářet různé knihovny. Některé již existují, jednou z nich je knihovna MCAD, která bývá často distribuovaná společně s OpenSCADem.
Knihovna MCAD obsahuje spoustu elementárních i pokročilých věcí:
- nové tvary,
- vhodné věci pro RepRap:
- motorky,
- řemeničky…
Pro použití knihovny MCAD je potřeba použít include
, ne use
.
include <MCAD/stepper.scad>
motor(Nema17);
