|
|
# IceSL scripting language specification
|
|
|
|
|
|
This is the official documentation of the IceSL scripting language. Examples featured here are for the most part self-contained unless they use an external asset (svg or stl files). Their associated illustrations are accurate depictions of their output.
|
|
|
|
|
|
We welcome IceSL users to redirect their questions about the scripting language to the [IceSL forum page](https://groups.google.com/forum/?fromgroups#!forum/icesl).
|
|
|
|
|
|
1. [Syntax](#syntax)
|
|
|
|
|
|
2. [Drawing and Scale](#drawing)
|
|
|
|
|
|
3. [Vectors, Matrices, Constants and Trigonometric Functions](#algebra)
|
|
|
1. [Vectors](#vectors)
|
|
|
2. [Matrices](#matrices)
|
|
|
3. [Constants, Trigonometric Functions and Angles](#constants)
|
|
|
4. [Shapes](#shapes)
|
|
|
1. [Primitive Shapes](#primitives)
|
|
|
2. [Centered Primitives](#centered)
|
|
|
3. [Non-primitive Shapes](#nonprimitives)
|
|
|
4. [Implicits](#implicits)
|
|
|
1. [Progressive rendering](#progressive)
|
|
|
2. [Uniform variables and file support](#uniforms)
|
|
|
3. [3D Textures](#3dtextures)
|
|
|
5. [Transformations](#transformations)
|
|
|
1. [Magnets](#magnets)
|
|
|
6. [Operations](#operations)
|
|
|
1. [CSG Operations](#csg)
|
|
|
2. [Other Operations](#otherops)
|
|
|
7. [Shape Representation](#shaperep)
|
|
|
1. [From assets](#assets)
|
|
|
2. [Distribute](#distribute)
|
|
|
8. [Other functionality](#otherfunc)
|
|
|
1. [Printing settings](#settings)
|
|
|
2. [Variable caching](#caching)
|
|
|
3. [Tweaks](#tweaks)
|
|
|
4. [Fields](#fields)
|
|
|
5. [Mesh Information](#meshinfo)
|
|
|
6. [Miscellaneous Functions](#miscfunc)
|
|
|
9. [Service Mode](#servicemode)
|
|
|
1. [Invoking Service Mode](#invokeservicemode)
|
|
|
2. [Service Mode functions](#servicemodefunctions)
|
|
|
3. [Examples](#servicemodeexamples)
|
|
|
|
|
|
## Syntax <a name="syntax"></a>
|
|
|
|
|
|
The scripting language of IceSL (hereafter referred to as IceSL) is a superset of [lua](http://www.lua.org/pil/contents.html). Moreover, IceSL has been designed to facilitate conversion from/to [OpenSCAD](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual).
|
|
|
|
|
|
IceSL also extends Lua's types in order to specify shapes and transforms. The main basic types are:
|
|
|
|
|
|
1. Vector (e.g. `v(1,0,0)`)
|
|
|
2. Matrix (e.g. `m(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1)`)
|
|
|
3. Shapes:
|
|
|
* Primitives (e.g. `sphere(1)`),
|
|
|
* Meshes (e.g. `load('fox.stl')`),
|
|
|
* Implicits,
|
|
|
* Voxels.
|
|
|
|
|
|
## Drawing and Scale <a name="drawing"></a>
|
|
|
|
|
|
Creating a shape in IceSL does not automatically render it in the final scene. In order to do this, you need to emit it.
|
|
|
|
|
|
```emit( shape, brush )```
|
|
|
|
|
|
* ```shape```: the shape to render
|
|
|
* ```brush```: the brush's index to render the shape with. 0 by default
|
|
|
|
|
|
Brushes are an internalized concept of IceSL, there are a total of 128 indexes starting from 0. Their use is meant to group shapes under a set of parameters (usually printing parameters like _infill percentage_). In case of overlapping, the group with the lower index takes priority. The next code exemplifies the use of <code>emit</code>:
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
b = box(10)
|
|
|
emit( b, 0 )
|
|
|
c = sphere(5)
|
|
|
emit( translate(0,0,5) * c, 1 )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/3ca402a5562e1b73efad21373bd1adcc/Example_emit.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Finally, a unit in the scripting language corresponds to 1mm in the printing world. IceSL always renders a scene with a virtual _printing bed_; a grid that represents the 3d printer bed (see image below). Each square of IceSL's printing bed corresponds to 1cm<sup>2</sup>.
|
|
|
|
|
|
Notice that, in order to have a visual aid on view orientation, axes are drown in the bottom-left corner. The red, green and blue lines correspond to the positive X, Y, and Z axes respectively.
|
|
|
|
|
|
<img src="uploads/b4e0712ea9a780482db48e616e486370/Printing_bed.png" width="200">
|
|
|
|
|
|
## Vectors, Matrices, Constants and Trigonometric Functions <a name="algebra"></a>
|
|
|
|
|
|
### Vectors <a name="vectors"></a>
|
|
|
|
|
|
Construction
|
|
|
* ```v(x,y,z)``` or ```v{x,y,z}```: creates the vector $`\begin{bmatrix} x \\ y \\ z
|
|
|
\end{bmatrix}`$.
|
|
|
* ```v(x,y)``` or ```v{x,y}```: creates the vector $`\begin{bmatrix} x \\ y \\ 0 \end{bmatrix}`$.
|
|
|
|
|
|
Members:
|
|
|
* ```v.x```: $`x`$ coordinate
|
|
|
* ```v.y```: $`y`$ coordinate
|
|
|
* ```v.z```: $`z`$ coordinate
|
|
|
|
|
|
Operations:
|
|
|
Let ```v``` and ```u``` be vectors and ```n``` a number.
|
|
|
* ```v + u```: vector addition.
|
|
|
* ```v - u```: vector subtraction.
|
|
|
* ```v * u```: vector component-wise multiplication.
|
|
|
* ```v / u```: vector component-wise division
|
|
|
* ```v * n``` or ```n * v```: vector scalar multiplication.
|
|
|
* ```v / n```: vector scalar division.
|
|
|
* ```v1 == v2```: vector comparison.
|
|
|
* ```-v```: syntactic sugar for ```-1 * v```.
|
|
|
* ```dot(v, u)```: dot product.
|
|
|
* ```cross(v, u)```: cross product.
|
|
|
* ```normalize(v)```: returns the unit vector $`\hat{v}`$.
|
|
|
* ```length(v)```: return the norm of ```v``` (i.e. $`||v||`$).
|
|
|
|
|
|
### Matrices <a name="matrices"></a>
|
|
|
|
|
|
Construction:
|
|
|
|
|
|
```m( m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 )```
|
|
|
|
|
|
or
|
|
|
|
|
|
```m{ m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 }```
|
|
|
|
|
|
Creates the matrix $`\begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34}\\ m_{41} & m_{42} & m_{43} & m_{44}\end{bmatrix}`$.
|
|
|
|
|
|
Members:
|
|
|
|
|
|
* ```m:at(c,r)```: element at column ```c``` and row ```r```
|
|
|
|
|
|
Operations: Let ```M``` and ```Q``` be matrices, let ```v``` be a vector and let ```s``` be a shape,
|
|
|
* ```M * Q```: matrix multiplication. Returns a matrix.
|
|
|
* ```M * v```: matrix-vector multiplication. Returns a vector.
|
|
|
* ```M * s```: shape transformation. Returns the shape transformed by ```M```.
|
|
|
* ```M1 == M2```: matrix comparison. Returns a boolean.
|
|
|
* ```inverse(M)```: matrix inversion. Returns the inverse of matrix ```M```.
|
|
|
|
|
|
### Constants, Trigonometric Functions and Angles <a name="constants"></a>
|
|
|
|
|
|
The following are constants in IceSL:
|
|
|
* ```Pi```: the $`\pi`$ constant.
|
|
|
* ```X```: the vector ```v(1,0,0)```.
|
|
|
* ```Y```: the vector ```v(0,1,0)```.
|
|
|
* ```Z```: the vector ```v(0,0,1)```.
|
|
|
* ```Id```: the identity matrix.
|
|
|
* ```Path```: the path of the current script.
|
|
|
|
|
|
IceSl can calculate the next trigonometric functions:
|
|
|
```sin```, ```asin```, ```cos```, ```acos```, ```tan```, ```atan```, ```atan2```.
|
|
|
|
|
|
Angles in IceSL are expected to be written in **degrees**.
|
|
|
|
|
|
## Shapes <a name="shapes"></a>
|
|
|
### Primitive Shapes <a name="primitives"></a>
|
|
|
|
|
|
```load(path)```
|
|
|
|
|
|
Loads the 3d mesh at ```path```. The mesh must be watertight.
|
|
|
* ```path```: Absolute path to a 3d mesh. It supports the following extensions:
|
|
|
* **stl**
|
|
|
* **obj**
|
|
|
* **3ds**
|
|
|
|
|
|
```sphere(r, c)```
|
|
|
|
|
|
Creates a sphere of radius ```r``` centered on ```c```. ```sphere(r)``` is syntactic sugar for ```sphere(r,v(0,0,0))``` -a centered sphere.
|
|
|
* ```r```: the sphere's radius
|
|
|
* ```c```: the sphere's center
|
|
|
|
|
|
```cube(dx, dy, dz)```
|
|
|
|
|
|
Creates a cube with with sides ```dx```, ```dy```, ```dz``` with its bottom face centered on the origin. ```cube(d)``` and ```cube(v)``` are syntactic sugars for ```cube(d,d,d)``` and ```cube(v.x,v.y,v.z)``` respectively.
|
|
|
* ```dx```: length of the face perpendicular to the X-axis
|
|
|
* ```dy```: length of the face perpendicular to the Y-axis
|
|
|
* ```dz```: length of the face perpendicular to the Z-axis
|
|
|
|
|
|
```cone(r0, r1, c0, c1)```
|
|
|
|
|
|
Creates a cone with base radius ```r0```, top radius ```r1```, base center ```c0``` and top center ```c1```. Moreover, ```cone(r0,r1,h)``` is syntactic sugar for ```cone(r0,r1,v(0,0,0),v(0,0,h))```.
|
|
|
* ```r0```: the cone's base radius
|
|
|
* ```r1```: the cone's top radius
|
|
|
* ```c0```: the cone's base center
|
|
|
* ```c1```: the cone's top center
|
|
|
|
|
|
```cylinder(r, c0, c1)```
|
|
|
|
|
|
Creates a cylinder with radius ```r```, base center ```c0``` and top center ```c1```. It is syntactic sugar for ```cone(r,r,c0,c1)```. Additionally, ```cylinder(r,h)``` is also syntactic sugar for ```cone(r,r,h)```.
|
|
|
|
|
|
```polyhedron(points,indices)```
|
|
|
|
|
|
Creates a polyhedron with ```points``` as its vertex and ```indices``` to specify its faces.
|
|
|
* ```points```: an array of vectors containing the polyhedron's vertex
|
|
|
* ```indices```: an array of vectors specifying the polyhedron's faces. Each vector specifies a face constructed from three vertex indices represented by the vector's components. Indices start from 0 and faces point outwards whenever the orientation of the vertices to which the indices refer to is counterclockwise.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
p = polyhedron(
|
|
|
{ v(0,0,0), v(1,0,0), v(0,1,0), v(1,1,0), v(0.5,0.5,1) },
|
|
|
{ v(0,3,1), v(0,2,3), v(0,1,4), v(1,3,4), v(3,2,4), v(2,0,4) } )
|
|
|
emit( p )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/384b83224915015bc3e3238dff4845b0/Example_polyhedron.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```Void```
|
|
|
|
|
|
Creates an empty primitive
|
|
|
|
|
|
### Centered Primitives <a name="centered"></a>
|
|
|
|
|
|
Many primitives can be automatically centered at creation to their center of symmetry with respect to their bounding boxes. The following table lists their centered versions.
|
|
|
|
|
|
| Primitive | Centered Version | Alternative Centered Version |
|
|
|
| --------- | ---------------- | ---------------------------- |
|
|
|
| ```load(path)``` | ```load_centered(path)``` | ```load_centered_on_plate(path)``` |
|
|
|
| ```cube(dx,dy,dz)``` | ```ccube(dx,dy,dz)``` | ```box(dx,dy,dz)``` |
|
|
|
| ```cone(r0,r1,h)``` | ```ccone(r0,r1,h)``` | |
|
|
|
| ```cylinder(r,h)``` | ```ccylinder(r,h)``` | |
|
|
|
|
|
|
Additionally, the cube and box primitives have the versions ```ocube(dx,dy,dz)``` and ```cornerbox(dx,dy,dz)``` that position their front lower-left corners at the origin.
|
|
|
|
|
|
### Non-primitive Shapes <a name="nonprimitives"></a>
|
|
|
|
|
|
```linear_extrude(dir, points)```
|
|
|
|
|
|
Creates a closed object from the extrusion of a polygon along a direction ```dir```. The polygon's orientations is specified as set of either clockwise or counter-clockwise 2D vertices in ```points```.
|
|
|
* ```dir```: extruding direction
|
|
|
* ```points```: polygon specification
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
triangle = { v(-10,0), v(0,10), v(10,0) }
|
|
|
-- 50 units along the Z-axis
|
|
|
dir = v(0,0,50)
|
|
|
emit( linear_extrude(dir, triangle) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/d49fa94fafa25664d5a02a674f2b21ae/Example_linear_extrude.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```linear_extrude_from_oriented(dir, points)```
|
|
|
|
|
|
Creates a closed object from the extrusion of a polygon along a direction ```dir```. Solid geometry is specified as set of *closed* (i.e. the last vertex matches the first one) counter-clockwise 2D vertices and hollow geometry is specified as a set of closed clockwise 2D vertices in ```points```.
|
|
|
* ```dir```: extruding direction
|
|
|
* ```points```: polygon specification
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
polygon1 = { v(10,10), v(-10,10), v(-10,-10), v(10,-10), v(10,10) } -- Solid
|
|
|
polygon2 = { v(0,6), v(6,-6), v(-6,-6), v(0,6) } -- Hollow
|
|
|
dir = v(0,0,10)
|
|
|
emit( union(
|
|
|
linear_extrude_from_oriented(dir, polygon1),
|
|
|
linear_extrude_from_oriented(dir, polygon2)
|
|
|
) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/2c40c2e7a34c7b15751a6425267aaf18/Example_linear_extrude_from_oriented.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```rotate_extrude(points, nsteps)```
|
|
|
|
|
|
Creates a closed object from the spinning of a polygon along the Z-axis (axis of revolution). The polygon is specified as set of counter-clockwise 2D vertices in ```points```. ```nsteps``` defines the number of steps in the revolution of the polygon, the more steps the smoother the resulting shape is.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
radius = v(10,0,0)
|
|
|
triangle = { radius + v(1,0,0), radius + v(0,1,0), radius + v(-1,0,0) }
|
|
|
emit( rotate_extrude( triangle, 100 ) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/ae89126ccae1653103493ffef57bc099/Example_rotate_extrude.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```sections_extrude(contours)```
|
|
|
|
|
|
Crates a closed object by connecting each polygon contained in ```contours```. Similar to the functions above, a polygon is defined as a table of at least three points. ```contours``` is a table of more than one polygon and all polygons must contain the same number of points.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
se = sections_extrude({
|
|
|
{rotate( 0,Z) * v( 0, 0, 0),
|
|
|
rotate( 0,Z) * v(10, 0, 0),
|
|
|
rotate( 0,Z) * v(10,10, 0),
|
|
|
rotate( 0,Z) * v( 0,10, 0)},
|
|
|
|
|
|
{rotate( 60,Z) * v( 0, 0,10),
|
|
|
rotate( 60,Z) * v(10, 0,10),
|
|
|
rotate( 60,Z) * v(10,10,10),
|
|
|
rotate( 60,Z) * v( 0,10,10)},
|
|
|
|
|
|
{rotate(120,Z) * v( 0, 0,20),
|
|
|
rotate(120,Z) * v(10, 0,20),
|
|
|
rotate(120,Z) * v(10,10,20),
|
|
|
rotate(120,Z) * v( 0,10,20)}
|
|
|
})
|
|
|
emit(se)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/84e315d1cc4e2a6fbad720171f180280/Example_sections_extrude.jpg" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Implicits <a name="implicits"></a>
|
|
|
|
|
|
IceSL supports implicits by way of the [GL Shading Language](https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language) (GLSL). A comprehensive list of the built-in functions of GLSL can be found [here](http://www.shaderific.com/glsl-functions/)
|
|
|
|
|
|
```implicit_distance_field(boxMin, boxMax, fragment)```
|
|
|
|
|
|
```implicit_solid(boxMin, boxMax, voxSize, fragment)```
|
|
|
|
|
|
Creates an object out of the [implicit geometry](https://en.wikipedia.org/wiki/Implicit_function) calculated in ```fragment```. The bounding box constructed by ```boxMin``` and ```boxMax``` defines the boundaries of the implicit shape.
|
|
|
* ```boxMin, boxMax```: domain of the implicit. The domain is specified by the box constructed with corners ```boxMin``` and ```boxMax```
|
|
|
* ```voxSize```: voxel output size. Lower values result in greater quality at the expense of higher calculation costs.
|
|
|
* ```fragment```: string containing the GLSL program. This program calculates the implicit function that defines the output geometry.
|
|
|
|
|
|
Implicits are calculated in IceSL with a sphere tracing method (detailed [here](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)). The program specified in ```fragment``` must contain a function called either ```float distance(vec3 p)```, in the case of ```implicit_distance_field```, or ```float solid(vec3 p)``` in the case of ```implicit_solid```. This function calculates the distance field or the solid/empty classification respectively for every point of the domain of the box. A resulting negative value is interpreted as _solid_ whereas a positive value means _hollow_. Consider the following example.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
cube = implicit_distance_field( v(-10,-10,-10), v(10,10,10),
|
|
|
[[
|
|
|
float distance(vec3 p) {
|
|
|
return -1;
|
|
|
}
|
|
|
]])
|
|
|
emit (cube)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/98f1f60e808308d35a4b4f2ea2e9280c/Example_implicit_1.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Above, every point in the domain of the implicit is marked as _solid_, therefore the geometry created has the shape of the boundary box.
|
|
|
|
|
|
Choosing ```implicit_distance_field``` over ```implicit_solid``` can be summarized as follows: The former requires to estimate a distance to the surface, which can prove difficult and prone to artifacts (when the estimate is too far off from reality). The latter is much easier, as the function simply has to return negative for solid and positive for empty.
|
|
|
|
|
|
#### Progressive rendering <a name="progressive"></a>
|
|
|
|
|
|
IceSL by default progressively renders implicits, consequently all the implicit's geometry may not render in one single frame. The order of rendering is defined by the distance to the camera (i.e. scene's point of view). To disable/enable this behavior use the following:
|
|
|
|
|
|
```enable_progressive_rendering(shape, bool)```
|
|
|
* ```shape```: output from either the ```implicit_*``` or ```to_voxel_*``` functions.
|
|
|
* ```bool```: either ```true``` or ```false```
|
|
|
|
|
|
This setting must be set right after the implicit/voxels creation. This is because IceSL clones a shape whenever it is transformed and/or reassigned to another variable. Each clone drags with it the _current_ value of this setting.
|
|
|
|
|
|
#### Uniform variables and file support <a name="uniforms"></a>
|
|
|
|
|
|
It is possible to set values for uniform variables specified inside the implicit's GLSL program via lua commands.
|
|
|
|
|
|
```set_uniform_{boolean|scalar|vector|matrix|texture3d}(implicit, var_name, var_value)```
|
|
|
|
|
|
sets ```var_name``` to ```var_value``` inside ```implicit```.
|
|
|
* ```implicit```: a created implicit
|
|
|
* ```var_name```: string specifying the name of the uniform variable in the implicit
|
|
|
* ```var_value```: new boolean/scalar/vector/matrix/texture3d/voxel_distance_field value
|
|
|
|
|
|
Furthermore, implicits can be loaded directly from files as the next function shows.
|
|
|
|
|
|
```implicit_distance_field_from_file(boxMin, boxMax, fileName)```
|
|
|
|
|
|
```implicit_solid_from_file(boxMin, boxMax, voxSize, fileName)```
|
|
|
|
|
|
Similar to ```implicit_distance_field``` and ```implicit_solid``` but the fragment program is in ```fileName```.
|
|
|
* ```boxMin, boxMax```: domain of the implicit. The domain is specified by the box constructed with corners ```boxMin``` and ```boxMax```
|
|
|
* ```fileName```: file containing the GLSL implicit program.
|
|
|
* ```voxSize```: voxel output size.
|
|
|
|
|
|
|
|
|
In the next example, we create an implicit whose points inside an origin-centered sphere are considered solid. The radius of the sphere is changed using ```set_uniform_scalar```.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
sphere = implicit_solid(v(-10,-10,-10), v(10,10,10), 0.25,
|
|
|
[[
|
|
|
uniform float r = 5;
|
|
|
float solid(vec3 p) {
|
|
|
return length(p) - r;
|
|
|
}
|
|
|
]])
|
|
|
set_uniform_scalar(sphere, 'r', 10.5)
|
|
|
emit(sphere)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/ae21547d9fbf2d1199d8ce753f9441e8/Example_implicit_2.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Notice how in the above example, the implicit boundary cuts off some parts of the sphere. Implicits are commonly used to construct geometry that is impossible to create with CSG or low-resolution meshes. See the following example.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
shape = implicit_distance_field(v(-2,-2,0), v(2,2,8),
|
|
|
[[
|
|
|
float distance(vec3 p) {
|
|
|
return 0.01 * ((pow(sqrt(p.x*p.x + p.y*p.y) - 3, 3) + p.z*p.z - 1) + noise(p));
|
|
|
}
|
|
|
]])
|
|
|
emit(scale(5) * shape)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/06292b311081b3b4ba6f77fe2aa7c356/Example_implicit_3.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
#### 3D Textures <a name="3dtextures"></a>
|
|
|
|
|
|
IceSL features the ability to construct 3D textures programmatically. There is support for single channel textures as well as RGB textures in 8bit and 32bit variants.
|
|
|
|
|
|
```tex3d_{rgb32f|r32f|rgb8f|r8f}(w,h,d)```
|
|
|
|
|
|
Creates a 3d texture class with the following possible specifications:
|
|
|
* ```rgb32f```: rgb 32bit float texture
|
|
|
* ```r32f```: luminance 32bit float texture
|
|
|
* ```rgb8f```: rgb 8bit float texture
|
|
|
* ```r8f```: luminance 8bit float texture
|
|
|
|
|
|
The 3D texture class possesses the following methods:
|
|
|
* ```w()```: return the texture's width
|
|
|
* ```h()```: return the texture's height
|
|
|
* ```d()```: return the texture's depth
|
|
|
* ```set(u,v,w,val)```: sets the value ```val``` at texture coordinate ```(u,v,w)```. ```val``` is a vector where each component must be in the range $`[0-1]`$. If the texture type is luminance (i.e., one channel texture), the second and third components of ```val``` are ignored.
|
|
|
|
|
|
The following example shows a 1-channel 3D texture created programmatically and used as input in an implicit. Two solid cubes (one on each corner) made of the value ```-1.0``` are drawn into the texture while the rest is left at value ```10.0```. The implicit maps each point of the implicit area to a point of the texture repeated twice.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
tex_dim = v(10,10,10)
|
|
|
tex = tex3d_r32f(tex_dim.x,tex_dim.y,tex_dim.z)
|
|
|
for ucoord = 0, tex_dim.x-1 do
|
|
|
for vcoord = 0, tex_dim.y-1 do
|
|
|
for wcoord = 0, tex_dim.z-1 do
|
|
|
if (ucoord < tex_dim.x/2 and vcoord < tex_dim.y/2 and wcoord < tex_dim.z/2) or
|
|
|
(ucoord >= tex_dim.x/2 and vcoord >= tex_dim.y/2 and wcoord >= tex_dim.z/2) then
|
|
|
tex:set(ucoord,vcoord,wcoord,v(-1.0,0.0,0.0))
|
|
|
else
|
|
|
tex:set(ucoord,vcoord,wcoord,v(10.0,0.0,0.0))
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
|
|
|
imp_dim = v(20,20,20)
|
|
|
imp = implicit_distance_field(v(0,0,0), imp_dim,
|
|
|
[[
|
|
|
uniform sampler3D tex_data;
|
|
|
uniform vec3 imp_ext;
|
|
|
float distance(vec3 p)
|
|
|
{
|
|
|
return 0.01 * texture(tex_data,(p/imp_ext)*2.0).x;
|
|
|
}
|
|
|
]])
|
|
|
set_uniform_vector(imp, 'imp_ext', imp_dim)
|
|
|
set_uniform_texture3d(imp, 'tex_data', tex)
|
|
|
|
|
|
emit(imp)
|
|
|
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/ad5c9dcb1ccff2a925dc5061f1e4cbd4/Example_3dtex.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
## Transformations <a name="transformations"></a>
|
|
|
|
|
|
This section deals with linear transformations. IceSL offers functions to calculate matrices of transformations. To apply a transformation, a transformation matrix is multiplied with a shape. In order to combine more than one transformation, the result of successive multiplications of transformation matrices may also be multiplied with a shape. All applications of transformations should be consistent with a [http://mathworld.wolfram.com/Right-HandedCoordinateSystem.html right-handed coordinate system]. This means the *rightmost transformation* in a combination *takes precedence*.
|
|
|
|
|
|
```translate(dx,dy,dz)```
|
|
|
|
|
|
Returns a transformation matrix that translates a shape by ```dx,dy,dz``` units in the X-axis, Y-axis and Z-axis respectively.
|
|
|
* ```dx```: number of units to translate in the X-axis
|
|
|
* ```dy```: number of units to translate in the Y-axis
|
|
|
* ```dz```: number of units to translate in the Z-axis
|
|
|
|
|
|
```translate(v)```
|
|
|
|
|
|
Syntactic sugar for ```translate(v.x,v.y,v.z)```.
|
|
|
|
|
|
```rotate(angle,axis)```
|
|
|
|
|
|
Returns a transformation matrix that rotates a shape by ```angle``` degrees around the vector ```axis```.
|
|
|
* ```angle```: angle of rotation. In degrees
|
|
|
* ```axis```: a vector specifying the axis of rotation
|
|
|
|
|
|
```rotate(rx,ry,rz)```
|
|
|
|
|
|
```rotate(v)```
|
|
|
|
|
|
Syntactic sugar for ```rotate(rz,Z) * rotate(ry,Y) * rotate(rx,X)``` and ```rotate(v.z,Z) * rotate(v.y,Y) * rotate(v.x,X)``` respectively.
|
|
|
|
|
|
```scale(sx, sy, sz)```
|
|
|
Returns a transformation matrix that scales a shape by ```sx,sy,sz``` factors in the X-axis, Y-axis and Z-axis respectively.
|
|
|
* ```sx```: scale factor in the X-axis
|
|
|
* ```sy```: scale factor in the Y-axis
|
|
|
* ```sz```: scale factor in the Z-axis
|
|
|
|
|
|
```scale(s)```
|
|
|
|
|
|
```scale(v)```
|
|
|
|
|
|
Syntactic sugar for ```scale(s,s,s)``` and ```scale(v.x,v.y,v.z)``` respectively.
|
|
|
|
|
|
The above transformations have alternative names (mainly for compatibility purposes). The next table summarizes them:
|
|
|
|
|
|
| Transformation | Alternative |
|
|
|
| -------------- | ----------- |
|
|
|
| translate | translation |
|
|
|
| rotate | rotation |
|
|
|
| scale | scaling |
|
|
|
|
|
|
```mirror(normal)```
|
|
|
|
|
|
Returns a transformation matrix that mirrors a shape along the vector ```normal```.
|
|
|
* ```normal```: vector specifying the direction to mirror
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = load_centered('fox.stl')
|
|
|
emit( mesh )
|
|
|
emit( translate(0,-100,0) * mirror(v(0,1,0)) * mesh )
|
|
|
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/011d458a111f9a042915c0437acc3de4/Example_mirror.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```frame(v)```
|
|
|
|
|
|
Returns a transformation matrix that orients (i.e. aligns) a shape's [up vector](http://autodeskmaya.wikia.com/wiki/Up_Vector) to the direction ```v```.
|
|
|
* ```v```: a vector specifying the direction to orientate in the transformation.
|
|
|
|
|
|
### Magnets <a name="magnets"></a>
|
|
|
|
|
|
Magnets are volumeless shapes that help building objects by way of assembling parts. Think of a magnet as a fastener that eventually couples with other magnets from different shapes.
|
|
|
|
|
|
```magnet('name')```
|
|
|
|
|
|
* ```name```: magnet name
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
case = union( cylinder(5,10), translate(0,0,10) * magnet('m1') )
|
|
|
head = union( cone(5,1,10), translate(0,0,0) * rotate(180,X) * magnet('m2') )
|
|
|
emit(case)
|
|
|
emit(translate(-20,0,0) * head)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/afaab141ada4970939e6adc2f10d215f/Example_magnet.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Magnets have orientation (the coupling orientation). To couple the magnets, the function ```snap``` returns a transformation matrix that assembles one shape's magnet (i.e. ```shape1```) to another (i.e. ```shape0```). The example below builds upon the previous one with the last two ```emit``` statements removed.
|
|
|
|
|
|
```snap(shape0, magnet0, shape1, magnet1)```
|
|
|
|
|
|
* ```shape0```: base shape
|
|
|
* ```magnet0```: the base shape's magnet name
|
|
|
* ```shape1```: shape to be coupled
|
|
|
* ```magnet1```: coupling shape's magnet name
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
smatrix = snap(case, 'm1', head, 'm2')
|
|
|
emit(union(smatrix * head, case))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/b55ddd1afdae5a1945bd3e26e7ca872e/Example_snap.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Snap matrices are not commutative with respect to their connecting magnets. Notice in the previous example that multiplying ```smatrix``` with ```case``` does not yield the same result.
|
|
|
|
|
|
## Operations <a name="operations"></a>
|
|
|
|
|
|
IceSL supports [Constructive Solid Geometry](https://en.wikipedia.org/wiki/Constructive_solid_geometry) (hereafter referred to as CSG). The following is a list of CSG operations:
|
|
|
|
|
|
### CSG Operations <a name="csg"></a>
|
|
|
|
|
|
```union(s0,s1)```
|
|
|
|
|
|
Returns a shape as the union of shape ```s0``` and shape ```s1```. This operation is commutative.
|
|
|
* ```s0```: A shape
|
|
|
* ```s1```: A shape
|
|
|
|
|
|
```intersection(s0,s1)```
|
|
|
|
|
|
Returns a shape as the intersection of shape ```s0``` and shape ```s1```. This operation is commutative.
|
|
|
* ```s0```: A shape
|
|
|
* ```s1```: A shape
|
|
|
|
|
|
```difference(s0,s1)```
|
|
|
|
|
|
Returns a shape as the difference of shape ```s0``` and shape ```s1```. This operation is **not** commutative.
|
|
|
* ```s0```: A shape
|
|
|
* ```s1```: A shape
|
|
|
|
|
|
IceSL supports abbreviated multi-input versions of these operations. Assume ```s``` is a shape and ```S``` is a table of shapes. The following table summarizes these operations.
|
|
|
|
|
|
| Operation | N-Argument Version | Short Version |
|
|
|
| --------- | ------------------ | ------------- |
|
|
|
| ```union(s0,s1)``` | ```union{s0,...,sn}, union(S)``` | ```U(s0,s1), U{s0,...,sn}, U(S)``` |
|
|
|
| ```intersection(s0,s1)``` | ```intersection{s0,...,sn}, intersection(S)``` | ```I(s0,s1), I{s0,...,sn}, I(S)``` |
|
|
|
| ```difference(s0,s1)``` | ```difference{s0,...,sn}, difference(S)``` | ```D(s0,s1), D{s0,...,sn}, D(S)``` |
|
|
|
|
|
|
N-ary versions from the above table are associative to the left. For example ```D{s0,s1,s2,s3}``` is equivalent to ```D(D(D(s0,s1),s2),s3)```. For this to be computationally sound [1](https://proofwiki.org/wiki/Union_of_Singleton) [2](https://proofwiki.org/wiki/Intersection_of_Singleton), the result of n-ary operations over a single shape is defined as the shape itself (i.e. ```U{s} = s```, ```I{s} = s``` and ```D{s} = s```).
|
|
|
|
|
|
### Other Operations <a name="otherops"></a>
|
|
|
|
|
|
```flip(m)```
|
|
|
|
|
|
Inverts the orientation of the faces from the mesh ```m```. This is specially useful when loading a mesh that has its faces defined clockwise.
|
|
|
* ```m```: input mesh
|
|
|
|
|
|
```convex_hull(shape)```
|
|
|
|
|
|
Creates the [convex hull](https://en.wikipedia.org/wiki/Convex_hull) of ```shape```. It only works with meshes or union of meshes.
|
|
|
* ```shape```: input primitive
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = load('crystal.stl')
|
|
|
emit( translate(100,0,0) * mesh )
|
|
|
emit( convex_hull(mesh) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/276b9ba6c7a260bde586b69e53463ae5/Example_convex_hull.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```dilate(mesh, factor)```
|
|
|
|
|
|
```erode(mesh, factor)```
|
|
|
|
|
|
[Dilates]( https://en.wikipedia.org/wiki/Dilation_(morphology) ) and [erodes]( https://en.wikipedia.org/wiki/Erosion_(morphology) ) a mesh respectively by ```factor```. The vertices in ```mesh``` need to be merged a priori (use ```merge_vertices```).
|
|
|
* ```mesh```: input mesh
|
|
|
* ```factor```: dilation/erosion factor
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = scale(0.1) * merge_vertices(load_centered('fox.stl'))
|
|
|
emit(translate(0,0,-6) * erode(mesh,0.3))
|
|
|
emit(translate(15,0,0) * dilate(mesh,0.5))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/bc4617409a7b056afd49689462c5706b/Example_dilate_erode.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```linear_offset(mesh,direction,offset)```
|
|
|
|
|
|
Creates a linear offset of ```mesh``` in the direction ```direction``` by factor ```offset```. Depending on the sign of ```offset```, the offset either goes inwards (i.e. negative sign) or outwards (i.e. positive sign). Only works with meshes with connectivity information, call ```merge_vertices``` when such information does not exist (e.g. _stl_ meshes).
|
|
|
* ```mesh```: input mesh
|
|
|
* ```direction```: offset direction
|
|
|
* ```offset```: offset factor
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = merge_vertices(load('fox.stl'))
|
|
|
emit( mesh )
|
|
|
emit( translate(100,0,0) * linear_offset(mesh,v(0,1,0),10) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/f6b8a5fb516b643473159df5acd0c3ce/Example_linear_offset.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```linear_offsets(mesh,directions,offsets)```
|
|
|
|
|
|
Same as ```linear_offset``` but multiple offsets can be applied at the same time. ```directions``` and ```offsets``` are arrays of vectors and numbers respectively and they have an ordered one-to-one correspondence.
|
|
|
|
|
|
## Shape Representation <a name="shaperep"></a>
|
|
|
|
|
|
IceSL offers several functions for calculating representations of shapes (i.e., meshes, voxels, etc).
|
|
|
|
|
|
```to_voxel_solid(shape, voxSize)```
|
|
|
|
|
|
```to_voxel_solid(tex3d, voxSize)```
|
|
|
|
|
|
Creates a solid voxel volume from ```shape``` or ```tex3d``` where each voxel measures ```voxSize``` units.
|
|
|
* ```shape```: input shape
|
|
|
* ```tex3d```: 3D texture
|
|
|
* ```voxSize```: voxel size (in mm)
|
|
|
|
|
|
```to_voxel_solid(tex3d, boxMin, boxMax)```
|
|
|
|
|
|
Creates a solid voxel volume from ```tex3d```. ```boxMin``` and ```boxMax``` specify the volume in space to create the solid. Values in ```tex3d``` below```0.5``` are considered solid, otherwise they are considered empty.
|
|
|
|
|
|
```to_voxel_distance_field(shape, voxSize)```
|
|
|
|
|
|
Creates a voxel distance field from ```shape``` using [this technique](http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). Each voxel measures ```voxSize``` units.
|
|
|
|
|
|
* ```shape```: input shape
|
|
|
* ```voxSize```: voxel size (in mm)
|
|
|
|
|
|
```set_distance_field_iso(voxels, threshold)```
|
|
|
|
|
|
In a distance field, sets the threshold to classify voxels as empty/solid whenever it is less/greater than ```threshold``` respectively.
|
|
|
|
|
|
* ```voxels```: voxel shape obtained by ```to_voxel_distance_field```
|
|
|
* ```threshold```: Number between ```0``` (empty) and ```1```(solid). Default is ```0.5```
|
|
|
|
|
|
```smooth_voxels(voxShape, windowSize)```
|
|
|
|
|
|
Smooths the voxel shape ```voxShape``` using a [trilinear interpolation](https://en.wikipedia.org/wiki/Trilinear_interpolation) with a windows size of ```windowSize```. This functions _does not_ return a shape, instead it modifies the shape specified on the first parameter.
|
|
|
|
|
|
* ```voxShape```: input shape. Only supports voxels
|
|
|
* ```windowSize```: interpolation 3D window size
|
|
|
|
|
|
```smooth_voxels_preserve_volume(voxShape, windowSize)```
|
|
|
|
|
|
Same as above but tries to preserve the shape's volume.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
s = sphere(5)
|
|
|
vs1 = to_voxel_solid(s, 0.1)
|
|
|
vs2 = to_voxel_solid(s, 0.1)
|
|
|
smooth_voxels(vs2,10)
|
|
|
emit(translate(0,0,0) * s)
|
|
|
emit(translate(15,0,0) * vs1)
|
|
|
emit(translate(30,0,0) * vs2)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/69b6b0930ded09a9c539f14033397535/Example_voxels.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```to_mesh(shape, voxSize)```
|
|
|
|
|
|
```to_mesh_dual(shape, voxSize)```
|
|
|
|
|
|
Creates a mesh from ```shape``` using the marching cubes or dual contouring algorithms respectively. Before calculating the resulting mesh, the 3D space containing the shape is discretized using voxels of size ```voxSize``` units.
|
|
|
|
|
|
* ```shape```: input shape
|
|
|
* ```voxSize```: voxel size of space discretization (in mm)
|
|
|
|
|
|
### From assets <a name="assets"></a>
|
|
|
|
|
|
```image_contouring(file,pixel_size)```
|
|
|
|
|
|
Extracts contours out of an image file. Pixels colored black are considered _hollow_, while any other color is considered _solid_. Returns a table of ```IMGContour``` objects.
|
|
|
* ```file```: input image file (PNG and TGA supported)
|
|
|
* ```pixel_size```: size in mm, of a pixel
|
|
|
|
|
|
The ```IMGContour``` object has the following members:
|
|
|
* ```outline```: The contour _(table)_
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
contours = image_contouring('shapes.png', 0.1)
|
|
|
for _,contour in pairs(contours) do
|
|
|
emit(linear_extrude_from_oriented(v(0,0,1), contour:outline()))
|
|
|
end
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/b5334a3f9d84f701e3727957ce6be7b7/Example_image_contouring.jpg" width="200">
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/82d378c0e4efb193bb5ea676e305b6b2/shapes.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```svg_contouring(file,dpi)```
|
|
|
|
|
|
Extracts contours out of a SVG file. Returns a table of ```SVGContour``` objects.
|
|
|
* ```file```: input svg file
|
|
|
* ```dpi```: dots per inch. Use 90 for Inkscape files
|
|
|
|
|
|
The ```SVGContour``` object has the following members:
|
|
|
* ```outline```: The contour _(table)_
|
|
|
* ```fill ```: fill color for the contour _(triplet)_
|
|
|
* ```stroke```: stroke color for the contour _(triplet)_
|
|
|
* ```strokeWidth```: stroke width for the contour _(num)_
|
|
|
* ```hasFill```: contour is color-filled _(bool)_
|
|
|
* ```hasStroke```: contour is color-bordered _(bool)_
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
svg_shapes = svg_contouring('restroom.svg',90)
|
|
|
for i,contour in pairs(svg_shapes) do
|
|
|
if contour:hasFill() then
|
|
|
set_brush_color(i, contour:fill()[1], contour:fill()[2], contour:fill()[3])
|
|
|
end
|
|
|
emit(linear_extrude_from_oriented(v(0,0,5),contour:outline()), i)
|
|
|
end
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/434f1733f99e33e71f3666761209ade6/Example_svg_ex.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```font()```
|
|
|
|
|
|
```font(ttf)```
|
|
|
|
|
|
Creates a font object based either using the default font provided by IceSL or the font described in the TrueType Font file ```ttf```.
|
|
|
* ```ttf```: TrueType Font file
|
|
|
|
|
|
The interface to the font object is the following:
|
|
|
* ```str(string, tracking)``` : Returns a 3D geometry of the string ```string```. If present, the font's [kerning](https://en.wikipedia.org/wiki/Kerning) information is added to ```tracking``` [tracking](https://en.wikipedia.org/wiki/Letter-spacing).
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
f = font(Path .. 'LiberationMono-Regular.ttf')
|
|
|
text = f:str('IceSL', 10)
|
|
|
emit(scale(0.5,0.5,10) * text)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/4b1fa3e9b2e4de82b33e286f1a2aaa4d/Example_font.jpg" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```load_raw_voxels(fileName, thicken)```
|
|
|
|
|
|
Creates a shape out of raw voxel data in ```fileName```. ```thicken``` stands for the thickening applied to the voxels.
|
|
|
* ```fileName```: input file
|
|
|
* ```thicken```: thickening of voxels
|
|
|
The format of the file is a continuous chunk of voxels with the following information in sequence:
|
|
|
1. Position (3 ints)
|
|
|
2. Normal (3 floats)
|
|
|
3. Color (3 unsigned chars)
|
|
|
4. State (1 bool)
|
|
|
|
|
|
### Distribute <a name="distribute"></a>
|
|
|
|
|
|
Additionally to changing the representations of a shape, IceSL also provides a function to calculate an evenly distributed set of points covering a surface. For each point this function also reports its surface normal and maximum distance to the set of nearest points.
|
|
|
|
|
|
```distribute(shape, density)```
|
|
|
|
|
|
Returns a Lua array describing the surface of ```shape``` using [Voronoid Iteration](https://en.wikipedia.org/wiki/Lloyd%27s_algorithm). The array is made out of triplets wherein the first element is a position of the surface, the second its surface normal and the third its distance to the furthest neighboring position in the array. How sparse the positions are is determined by the argument ```density```.
|
|
|
|
|
|
* ```shape```: input shape
|
|
|
* ```density```: position density. This argument is clamped to the unit interval where ```1``` signifies high density and ```0``` no density
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
shape = cube(10)
|
|
|
s = distribute(shape, 0.2)
|
|
|
centroids = {}
|
|
|
for i = 1,#s,1 do
|
|
|
centroids[i] = translate(s[i][1]) * frame(s[i][2]) *
|
|
|
union{ cone(s[i][3],0,1), mirror(Z) * cone(s[i][3],0,1) }
|
|
|
end
|
|
|
emit(union(centroids))
|
|
|
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/d1b3017bdeac39f7162c26f9ea279795/Example_distribute.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
## Other Functionality <a name="otherfunc"></a>
|
|
|
### Printing settings <a name="settings"></a>
|
|
|
|
|
|
Scripts also have the ability to change printing settings directly from within them. This allows the user (among other reasons) to specify printing settings tailored to the geometry being described in the script.
|
|
|
|
|
|
IceSL gives priority to an assignment of a printing setting according to the following list:
|
|
|
1. Default IceSL values -- _bottom priority_
|
|
|
2. Printer features (i.e., ```features.lua``` in printer profiles)
|
|
|
3. Print profile (e.g., fast print, high quality, etc.)
|
|
|
4. Material profile (e.g., abs, pla, etc.)
|
|
|
5. Lua script
|
|
|
6. User interface -- _top priority_
|
|
|
|
|
|
For example, if the value of a setting is specified in a printer profile as well as in the lua script, the latter takes priority. Moreover, if the user sets it manually using the UI then this overrides all other assignments.
|
|
|
|
|
|
```set_setting_value(setting, value)```
|
|
|
|
|
|
```set_setting_value(setting, value, bed_relative)```
|
|
|
|
|
|
Sets the printing parameter ```settings``` to ```value```
|
|
|
* ```setting```: Internal name of the printing setting to change
|
|
|
* ```value```: Value to assign. May be a boolean, a number, a string or a table. The latter is reserved to _per-layer_ assignments whereas the table is to be constructed as follows:
|
|
|
* ```{ [key_0]=value_0, ... , [key_n]=value_n }```
|
|
|
* where ```key_i``` specifies a height and ```value_i``` is a the parameter's value at such height.
|
|
|
* ```bed_relative```: If per-layer assignment, indicate whether the height is relative to the bed position (i.e., 0 means at bed level) or modeling position (i.e., 0 means at the center of geometry, see for example ```cube``` vs. ```ccube```). This parameter is _false_ by default.
|
|
|
* **NOTE**: Be aware that, at the point in the script where ```set_setting_value``` is being executed, the totality of the geometry is still unknown. The script hasn't finished executing and there might be more ```emit``` commands ahead. So when the parameter ```bed_relative``` is used, the bed position is still undecided, thus it is recommended to reload the script when this parameter is changing value to allow IceSL to recalculate the bed's final position.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
emit(cube(10))
|
|
|
set_setting_value('z_layer_height_mm', { [0.0]=0.2, [5]=0.3 })
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```set_setting_value(setting, tex3d, boxMin, boxMax)```
|
|
|
|
|
|
Sets the printing parameter ```setting``` as a _field_ that extends from ```boxMin``` to ```boxMax``` with values from ```tex3d```. Recall that individual values in textures are in the $`[0-1]`$ range, thus they are interpreted according to the setting's minimum and maximum values (e.g, 0.0 could mean no infill or zero degrees, and 1.0 could mean fully infilled or 360 degrees respectively).
|
|
|
* ```setting```: Internal name of the printing setting to change
|
|
|
* ```tex3d```: Value of the field as a 3d texture.
|
|
|
* ```boxMin,boxMax```: Field extent
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
height = 50
|
|
|
radius = 10
|
|
|
obj = cylinder(radius, height)
|
|
|
emit(obj)
|
|
|
|
|
|
size_tex3d = 64
|
|
|
size_tex3d_half = size_tex3d / 2
|
|
|
density = tex3d_r8f(size_tex3d, size_tex3d, size_tex3d)
|
|
|
|
|
|
for i = 0,size_tex3d - 1 do
|
|
|
for j = 0,size_tex3d - 1 do
|
|
|
for k = 0, size_tex3d - 1 do
|
|
|
r = math.sqrt((i - size_tex3d_half) ^ 2 + (j - size_tex3d_half) ^ 2)
|
|
|
d = r / size_tex3d_half -- from 0 to 100 inside out
|
|
|
density:set(i,j,k, v(d,0.0,0.0)) -- y and x values are ignored
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
|
|
|
box = bbox(obj)
|
|
|
set_setting_value('infill_percentage_0', density, box:min_corner(), box:max_corner())
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>
|
|
|
<img src="uploads/e6ff8f490ff96a7f1ac271f12835ae46/image.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Variable caching <a name="caching"></a>
|
|
|
|
|
|
It is possible to turn on/off variable caching in IceSL with the system variable ```enable_variable_cache```. Variable caching is useful when editing a script that constructs an object or preforms a calculation that is CPU intensive (i.e. consumes significant time).
|
|
|
|
|
|
In the following example it is possible to change the scaling of ```mesh``` without incurring in the penalty of re-calculating the result of ```to_mesh```:
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
enable_variable_cache = true
|
|
|
s = sphere(10)
|
|
|
if not mesh then
|
|
|
mesh = to_mesh(s,1)
|
|
|
end
|
|
|
emit(scale(1) * mesh)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Tweaks <a name="tweaks"></a>
|
|
|
|
|
|
```ui_scalar(name, default, min, max)```
|
|
|
|
|
|
Creates a sliding bar to interactively set a float value between ```min``` and ```max```.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
* ```min```: minimum value
|
|
|
* ```max```: maximum value
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
r = ui_scalar("Radius",10.0,1.0,20.0)
|
|
|
emit(sphere(r))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/e942eccb69903c2991560051674b463f/Example_tweaks.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```ui_scalarBox(name, default, step)```
|
|
|
|
|
|
Creates a quantity (+/-) box stepped by ```step``` to interactively set a float value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
* ```step```: increment/decrement delta
|
|
|
|
|
|
```ui_number(name, default, min, max)```
|
|
|
|
|
|
Creates a sliding bar to interactively set an integer value between ```min``` and ```max```.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
* ```min```: minimum value
|
|
|
* ```max```: maximum value
|
|
|
|
|
|
```ui_numberBox(name, default)```
|
|
|
|
|
|
Creates a quantity (+/-) box to interactively set an integer value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
|
|
|
```ui_bool(name, default)```
|
|
|
|
|
|
Creates a checkbox to interactively set a Boolean value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
|
|
|
```ui_text(name, default)```
|
|
|
|
|
|
Creates a text input box to interactively set a string value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
|
|
|
```ui_radio(name, list)```
|
|
|
|
|
|
Creates a radio box to interactively choose an integer value from a list.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```list```: an array of pairs of the form ```{integer, string}``` where ```integer``` is the id associated with ```string```
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
shape_list = {
|
|
|
{0, "sphere"},
|
|
|
{1, "cylinder"},
|
|
|
{2, "cube"}
|
|
|
}
|
|
|
shape = ui_radio("Shape:", shape_list)
|
|
|
|
|
|
if shape == 0 then emit(sphere(5))
|
|
|
elseif shape == 1 then emit(cylinder(5,10))
|
|
|
elseif shape == 2 then emit(cube(10)) end
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/0f6f18791297bc6e6c34cf7d2614f569/Example_tweakCombo.PNG" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```ui_combo(name, list)```
|
|
|
|
|
|
Creates a combo box to interactively choose a string value from a list.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```list```: an array of strings
|
|
|
|
|
|
```ui_selectFile(name)```
|
|
|
|
|
|
Creates a button to select an existing file. The return value is the file path
|
|
|
* ```name```: the tweak's name
|
|
|
|
|
|
|
|
|
### Fields <a name="fields"></a>
|
|
|
|
|
|
Fields are UI objects for interactively building 3D textures. They are useful for carving, sculpting and specifying surfaces among other things.
|
|
|
|
|
|
```ui_field(name, boxMin, boxMax)```
|
|
|
|
|
|
Creates a labeled button to build a 3D texture in the box space specified by ```boxMin``` and ```boxMax```.
|
|
|
* ```name```: field name
|
|
|
* ```boxMin```: left corner of the 3D texture
|
|
|
* ```boxMax```: right corner of the 3D texture
|
|
|
|
|
|
```ui_field_value_at(name, p)```
|
|
|
|
|
|
Retrieves the value of the field ```name``` (created by ```ui_field```) at position ```p```.
|
|
|
* ```name```: field name
|
|
|
* ```p```: position to inquire
|
|
|
|
|
|
```ui_file(fileName)```
|
|
|
|
|
|
Creates a UI to load/save all the script's tweaks and field values from/into ```fileName```.
|
|
|
|
|
|
* ```fileName```: file path to load/save tweaks and fields values
|
|
|
|
|
|
The following example sculpts a sphere using a field named ```Sculpting``` and saves the field values into the file ```sculpt.xml```
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
s = sphere(10)
|
|
|
bx = bbox(s)
|
|
|
bx:enlarge(1)
|
|
|
f = ui_field('Sculpting',bx:min_corner(),bx:max_corner())
|
|
|
ui_file(Path..'sculpt.xml')
|
|
|
result = intersection(s,to_voxel_solid(f,bx:min_corner(),bx:max_corner()))
|
|
|
emit(result)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/30f7f0ead3f449befc9d5fe67b5b0d96/Example_fields.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
In the next example, we use a field to avoid distributing (i.e. function ```distribute```) parts of the shape surface.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
enable_variable_cache = true
|
|
|
shape = sphere(10)
|
|
|
if not s then
|
|
|
s = distribute(shape, 0.5)
|
|
|
end
|
|
|
bx = bbox(shape)
|
|
|
bx:enlarge(1)
|
|
|
f = ui_field('surface', bx:min_corner(),bx:max_corner())
|
|
|
cubes = {}
|
|
|
for i = 1,#s do
|
|
|
if ui_field_value_at('surface', s[i][1]) > 0.5 then
|
|
|
cubes[#cubes+1] = translate(s[i][1]) * frame(s[i][2]) * ccube(s[i][3])
|
|
|
end
|
|
|
end
|
|
|
emit(union(shape,union(cubes)))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/3e2d7dde362967adb094ef5328aac543/Example_fields2.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Mesh Information <a name="meshinfo"></a>
|
|
|
|
|
|
```bbox(shape)```
|
|
|
|
|
|
Returns the bounding box of ```shape``` as an object ```AAB```.
|
|
|
* ```shape```: Input shape
|
|
|
The ```AAB``` object has the following members:
|
|
|
* ```min_corner```: Minimum corner of the bounding box _(vector)_
|
|
|
* ```max_corner```: Maximum corner of the bounding box _(vector)_
|
|
|
* ```center```: Center of the bounding box _(vector)_
|
|
|
* ```extent```: Dimensions of the bounding box _(vector)_
|
|
|
* ```empty```: Boolean value indicating whether the bounding box is _(bool)_
|
|
|
* ```enlarge(mm)```: Enlarges the box by ```mm``` millimeters _(method)_
|
|
|
|
|
|
```mesh_vertices(mesh)```
|
|
|
|
|
|
Returns a table containing the vertices of a mesh.
|
|
|
* ```mesh```: Input mesh
|
|
|
|
|
|
```mesh_normals(mesh)```
|
|
|
|
|
|
Returns a table containing the normals of a mesh.
|
|
|
* ```mesh```: Input mesh
|
|
|
|
|
|
```mesh_local_edge_size(mesh)```
|
|
|
|
|
|
Returns a table containing the average connecting edge length of every vertex of a mesh.
|
|
|
|
|
|
### Miscellaneous Functions <a name="miscfunc"></a>
|
|
|
|
|
|
```print(str)```
|
|
|
|
|
|
Prints the message ```str```
|
|
|
|
|
|
```dofile(path)```
|
|
|
|
|
|
Executes the script in ```path```
|
|
|
* ```path```: input string
|
|
|
|
|
|
```plugin_system_version()```
|
|
|
|
|
|
Returns the plugin system version string
|
|
|
|
|
|
```load_image(filename)```
|
|
|
|
|
|
Returns a 2D table where each $`(i,j)`$ index is a vector that corresponds to the rgb pixel from the image file ```filename```
|
|
|
|
|
|
```set_brush_color(brush, r, g, b)```
|
|
|
|
|
|
Sets the rendering color of ```brush``` to the normalized ```r```, ```g``` and ```b``` values.
|
|
|
* ```brush```: brush number
|
|
|
* ```r```: normalized (i.e., $`[0,1]`$) red component value
|
|
|
* ```g```: normalized (i.e., $`[0,1]`$) green component value
|
|
|
* ```b```: normalized (i.e., $`[0,1]`$) blue component value
|
|
|
|
|
|
```screenshot()```
|
|
|
|
|
|
Saves a screenshot in the ```pictures``` folder or current script folder for the windows build.
|
|
|
|
|
|
```sleep(ms)```
|
|
|
|
|
|
Suspends execution of IceSL by ```ms``` milliseconds.
|
|
|
* ```ms```: number of milliseconds
|
|
|
* ```path```: path to the script file
|
|
|
|
|
|
```dump(shape, filename)```
|
|
|
|
|
|
Saves the shape ```shape``` in file ```filename```
|
|
|
* ```shape```: shape to save
|
|
|
* ```filename```: destination file to save the shape. Supports _stl_ and _obj_ extensions
|
|
|
|
|
|
## Service Mode <a name="servicemode"></a>
|
|
|
|
|
|
IceSL offers the possibility of batch processing of its services (e.g., slicing, meshing, SVG output, etc.) without UI input. This is achievable through _Service Mode_.
|
|
|
|
|
|
In _Service Mode_, it is mandatory to provide IceSL with a lua script via the command line. There is no user interface nor any interaction from the user. Moreover, IceSL only outputs diagnostic information of the services used in the script.
|
|
|
|
|
|
### Invoking Service Mode <a name="invokeservicemode"></a>
|
|
|
|
|
|
_Service Mode_ can only be activated in _IceSL-slicer_, it **cannot** be invoked in _IceSL-forge_. To activate _Service Mode_, execute _IceSL-slicer_ with the `-s` flag and provide a script to execute:
|
|
|
|
|
|
* `IceSL-slicer.exe -s script_filename` (Windows)
|
|
|
* `./IceSL-slicer -s script_filename` (Linux)
|
|
|
|
|
|
A control string can be passed to the script while in service mode. This is done with the `-c` flag in the command line. It is subsequently set in the `control_string` global variable in the script:
|
|
|
|
|
|
* `IceSL-slicer.exe -c string -s script_filename` (Windows)
|
|
|
* `./IceSL-slicer -c string -s script_filename` (Linux)
|
|
|
|
|
|
|
|
|
### Service Mode functions <a name="servicemodefunctions"></a>
|
|
|
|
|
|
In addition to all other documented functions, the following also become available in _Service Mode_:
|
|
|
|
|
|
```set_service(service)```
|
|
|
|
|
|
Sets ```service``` as the current service to be used.
|
|
|
* ```service```: can be one of the following:
|
|
|
* ```'FilamentSlicer'```
|
|
|
* ```'DLPSlicer'```
|
|
|
* ```'LaserCutSlicer'```
|
|
|
* ```'MeshExportService'```
|
|
|
* ```'SVGSlicer'```
|
|
|
|
|
|
```run_service(filename)```
|
|
|
|
|
|
Executes the service on geometry emitted heretofore. Outputs the result to ```filename```.
|
|
|
|
|
|
```load_settings(filename)```
|
|
|
|
|
|
Loads settings (e.g., printing settings) saved in ```filename```.
|
|
|
* ```filename```: lua/xml file
|
|
|
|
|
|
```clear_brush(brush)```
|
|
|
|
|
|
Clears any emit done on ```brush``` up until this point.
|
|
|
|
|
|
### Service Mode examples <a name="servicemodeexamples"></a>
|
|
|
|
|
|
Slicing in _Service Mode_:
|
|
|
```lua
|
|
|
emit(scale(0.5) * load(Path..'fox.stl'))
|
|
|
set_service('FilamentSlicer')
|
|
|
load_settings(Path..'fox_printing_settings.lua')
|
|
|
run_service(Path..'fox.gcode')
|
|
|
```
|
|
|
|
|
|
Meshing in _Service Mode_:
|
|
|
```lua
|
|
|
emit(difference(ccube(40),sphere(25)))
|
|
|
set_service('MeshExportService')
|
|
|
set_setting_value('meshing_method', 'Dual contouring')
|
|
|
output_name = control_string..'.stl'
|
|
|
run_service('C:\\Users\\milchy\\Documents\\'..output_name)
|
|
|
# IceSL scripting language specification
|
|
|
|
|
|
This is the official documentation of the IceSL scripting language. Examples featured here are for the most part self-contained unless they use an external asset (svg or stl files). Their associated illustrations are accurate depictions of their output.
|
|
|
|
|
|
We welcome IceSL users to redirect their questions about the scripting language to the [IceSL forum page](https://groups.google.com/forum/?fromgroups#!forum/icesl).
|
|
|
|
|
|
1. [Syntax](#syntax)
|
|
|
|
|
|
2. [Drawing and Scale](#drawing)
|
|
|
|
|
|
3. [Vectors, Matrices, Constants and Trigonometric Functions](#algebra)
|
|
|
1. [Vectors](#vectors)
|
|
|
2. [Matrices](#matrices)
|
|
|
3. [Constants, Trigonometric Functions and Angles](#constants)
|
|
|
|
|
|
4. [Shapes](#shapes)
|
|
|
1. [Primitive Shapes](#primitives)
|
|
|
2. [Centered Primitives](#centered)
|
|
|
3. [Non-primitive Shapes](#nonprimitives)
|
|
|
4. [Implicits](#implicits)
|
|
|
1. [Progressive rendering](#progressive)
|
|
|
2. [Uniform variables and file support](#uniforms)
|
|
|
3. [3D Textures](#3dtextures)
|
|
|
|
|
|
5. [Transformations](#transformations)
|
|
|
1. [Magnets](#magnets)
|
|
|
|
|
|
6. [Operations](#operations)
|
|
|
1. [CSG Operations](#csg)
|
|
|
2. [Other Operations](#otherops)
|
|
|
|
|
|
7. [Shape Representation](#shaperep)
|
|
|
1. [From assets](#assets)
|
|
|
2. [Distribute](#distribute)
|
|
|
|
|
|
8. [Other functionality](#otherfunc)
|
|
|
1. [Printing settings](#settings)
|
|
|
2. [Distance field](#distfield)
|
|
|
3. [Variable caching](#caching)
|
|
|
4. [Tweaks](#tweaks)
|
|
|
5. [Fields](#fields)
|
|
|
6. [Mesh Information](#meshinfo)
|
|
|
7. [Miscellaneous Functions](#miscfunc)
|
|
|
|
|
|
9. [Service Mode](#servicemode)
|
|
|
1. [Invoking Service Mode](#invokeservicemode)
|
|
|
2. [Service Mode functions](#servicemodefunctions)
|
|
|
3. [Examples](#servicemodeexamples)
|
|
|
|
|
|
## Syntax <a name="syntax"></a>
|
|
|
|
|
|
The scripting language of IceSL (hereafter referred to as IceSL) is a superset of [lua](http://www.lua.org/pil/contents.html). Moreover, IceSL has been designed to facilitate conversion from/to [OpenSCAD](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual).
|
|
|
|
|
|
IceSL also extends Lua's types in order to specify shapes and transforms. The main basic types are:
|
|
|
|
|
|
1. Vector (e.g. `v(1,0,0)`)
|
|
|
2. Matrix (e.g. `m(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1)`)
|
|
|
3. Shapes:
|
|
|
* Primitives (e.g. `sphere(1)`),
|
|
|
* Meshes (e.g. `load('fox.stl')`),
|
|
|
* Implicits,
|
|
|
* Voxels.
|
|
|
|
|
|
## Drawing and Scale <a name="drawing"></a>
|
|
|
|
|
|
Creating a shape in IceSL does not automatically render it in the final scene. In order to do this, you need to emit it.
|
|
|
|
|
|
```emit( shape, brush )```
|
|
|
|
|
|
* ```shape```: the shape to render
|
|
|
* ```brush```: the brush's index to render the shape with. 0 by default
|
|
|
|
|
|
Brushes are an internalized concept of IceSL, there are a total of 128 indexes starting from 0. Their use is meant to group shapes under a set of parameters (usually printing parameters like _infill percentage_). In case of overlapping, the group with the lower index takes priority. The next code exemplifies the use of <code>emit</code>:
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
b = box(10)
|
|
|
emit( b, 0 )
|
|
|
c = sphere(5)
|
|
|
emit( translate(0,0,5) * c, 1 )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/3ca402a5562e1b73efad21373bd1adcc/Example_emit.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Finally, a unit in the scripting language corresponds to 1mm in the printing world. IceSL always renders a scene with a virtual _printing bed_; a grid that represents the 3d printer bed (see image below). Each square of IceSL's printing bed corresponds to 1cm<sup>2</sup>.
|
|
|
|
|
|
Notice that, in order to have a visual aid on view orientation, axes are drown in the bottom-left corner. The red, green and blue lines correspond to the positive X, Y, and Z axes respectively.
|
|
|
|
|
|
<img src="uploads/b4e0712ea9a780482db48e616e486370/Printing_bed.png" width="200">
|
|
|
|
|
|
## Vectors, Matrices, Constants and Trigonometric Functions <a name="algebra"></a>
|
|
|
|
|
|
### Vectors <a name="vectors"></a>
|
|
|
|
|
|
Construction
|
|
|
* ```v(x,y,z)``` or ```v{x,y,z}```: creates the vector $`\begin{bmatrix} x \\ y \\ z
|
|
|
\end{bmatrix}`$.
|
|
|
* ```v(x,y)``` or ```v{x,y}```: creates the vector $`\begin{bmatrix} x \\ y \\ 0 \end{bmatrix}`$.
|
|
|
|
|
|
Members:
|
|
|
* ```v.x```: $`x`$ coordinate
|
|
|
* ```v.y```: $`y`$ coordinate
|
|
|
* ```v.z```: $`z`$ coordinate
|
|
|
|
|
|
Operations:
|
|
|
Let ```v``` and ```u``` be vectors and ```n``` a number.
|
|
|
* ```v + u```: vector addition.
|
|
|
* ```v - u```: vector subtraction.
|
|
|
* ```v * u```: vector component-wise multiplication.
|
|
|
* ```v / u```: vector component-wise division
|
|
|
* ```v * n``` or ```n * v```: vector scalar multiplication.
|
|
|
* ```v / n```: vector scalar division.
|
|
|
* ```v1 == v2```: vector comparison.
|
|
|
* ```-v```: syntactic sugar for ```-1 * v```.
|
|
|
* ```dot(v, u)```: dot product.
|
|
|
* ```cross(v, u)```: cross product.
|
|
|
* ```normalize(v)```: returns the unit vector $`\hat{v}`$.
|
|
|
* ```length(v)```: return the norm of ```v``` (i.e. $`||v||`$).
|
|
|
|
|
|
### Matrices <a name="matrices"></a>
|
|
|
|
|
|
Construction:
|
|
|
|
|
|
```m( m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 )```
|
|
|
|
|
|
or
|
|
|
|
|
|
```m{ m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 }```
|
|
|
|
|
|
Creates the matrix $`\begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34}\\ m_{41} & m_{42} & m_{43} & m_{44}\end{bmatrix}`$.
|
|
|
|
|
|
Members:
|
|
|
|
|
|
* ```m:at(c,r)```: element at column ```c``` and row ```r```
|
|
|
|
|
|
Operations: Let ```M``` and ```Q``` be matrices, let ```v``` be a vector and let ```s``` be a shape,
|
|
|
* ```M * Q```: matrix multiplication. Returns a matrix.
|
|
|
* ```M * v```: matrix-vector multiplication. Returns a vector.
|
|
|
* ```M * s```: shape transformation. Returns the shape transformed by ```M```.
|
|
|
* ```M1 == M2```: matrix comparison. Returns a boolean.
|
|
|
* ```inverse(M)```: matrix inversion. Returns the inverse of matrix ```M```.
|
|
|
|
|
|
### Constants, Trigonometric Functions and Angles <a name="constants"></a>
|
|
|
|
|
|
The following are constants in IceSL:
|
|
|
* ```Pi```: the $`\pi`$ constant.
|
|
|
* ```X```: the vector ```v(1,0,0)```.
|
|
|
* ```Y```: the vector ```v(0,1,0)```.
|
|
|
* ```Z```: the vector ```v(0,0,1)```.
|
|
|
* ```Id```: the identity matrix.
|
|
|
* ```Path```: the path of the current script.
|
|
|
|
|
|
IceSl can calculate the next trigonometric functions:
|
|
|
```sin```, ```asin```, ```cos```, ```acos```, ```tan```, ```atan```, ```atan2```.
|
|
|
|
|
|
Angles in IceSL are expected to be written in **degrees**.
|
|
|
|
|
|
## Shapes <a name="shapes"></a>
|
|
|
### Primitive Shapes <a name="primitives"></a>
|
|
|
|
|
|
```load(path)```
|
|
|
|
|
|
Loads the 3d mesh at ```path```. The mesh must be watertight.
|
|
|
* ```path```: Absolute path to a 3d mesh. It supports the following extensions:
|
|
|
* **stl**
|
|
|
* **obj**
|
|
|
* **3ds**
|
|
|
|
|
|
```sphere(r, c)```
|
|
|
|
|
|
Creates a sphere of radius ```r``` centered on ```c```. ```sphere(r)``` is syntactic sugar for ```sphere(r,v(0,0,0))``` -a centered sphere.
|
|
|
* ```r```: the sphere's radius
|
|
|
* ```c```: the sphere's center
|
|
|
|
|
|
```cube(dx, dy, dz)```
|
|
|
|
|
|
Creates a cube with with sides ```dx```, ```dy```, ```dz``` with its bottom face centered on the origin. ```cube(d)``` and ```cube(v)``` are syntactic sugars for ```cube(d,d,d)``` and ```cube(v.x,v.y,v.z)``` respectively.
|
|
|
* ```dx```: length of the face perpendicular to the X-axis
|
|
|
* ```dy```: length of the face perpendicular to the Y-axis
|
|
|
* ```dz```: length of the face perpendicular to the Z-axis
|
|
|
|
|
|
```cone(r0, r1, c0, c1)```
|
|
|
|
|
|
Creates a cone with base radius ```r0```, top radius ```r1```, base center ```c0``` and top center ```c1```. Moreover, ```cone(r0,r1,h)``` is syntactic sugar for ```cone(r0,r1,v(0,0,0),v(0,0,h))```.
|
|
|
* ```r0```: the cone's base radius
|
|
|
* ```r1```: the cone's top radius
|
|
|
* ```c0```: the cone's base center
|
|
|
* ```c1```: the cone's top center
|
|
|
|
|
|
```cylinder(r, c0, c1)```
|
|
|
|
|
|
Creates a cylinder with radius ```r```, base center ```c0``` and top center ```c1```. It is syntactic sugar for ```cone(r,r,c0,c1)```. Additionally, ```cylinder(r,h)``` is also syntactic sugar for ```cone(r,r,h)```.
|
|
|
|
|
|
```polyhedron(points,indices)```
|
|
|
|
|
|
Creates a polyhedron with ```points``` as its vertex and ```indices``` to specify its faces.
|
|
|
* ```points```: an array of vectors containing the polyhedron's vertex
|
|
|
* ```indices```: an array of vectors specifying the polyhedron's faces. Each vector specifies a face constructed from three vertex indices represented by the vector's components. Indices start from 0 and faces point outwards whenever the orientation of the vertices to which the indices refer to is counterclockwise.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
p = polyhedron(
|
|
|
{ v(0,0,0), v(1,0,0), v(0,1,0), v(1,1,0), v(0.5,0.5,1) },
|
|
|
{ v(0,3,1), v(0,2,3), v(0,1,4), v(1,3,4), v(3,2,4), v(2,0,4) } )
|
|
|
emit( p )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/384b83224915015bc3e3238dff4845b0/Example_polyhedron.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```Void```
|
|
|
|
|
|
Creates an empty primitive
|
|
|
|
|
|
### Centered Primitives <a name="centered"></a>
|
|
|
|
|
|
Many primitives can be automatically centered at creation to their center of symmetry with respect to their bounding boxes. The following table lists their centered versions.
|
|
|
|
|
|
| Primitive | Centered Version | Alternative Centered Version |
|
|
|
| --------- | ---------------- | ---------------------------- |
|
|
|
| ```load(path)``` | ```load_centered(path)``` | ```load_centered_on_plate(path)``` |
|
|
|
| ```cube(dx,dy,dz)``` | ```ccube(dx,dy,dz)``` | ```box(dx,dy,dz)``` |
|
|
|
| ```cone(r0,r1,h)``` | ```ccone(r0,r1,h)``` | |
|
|
|
| ```cylinder(r,h)``` | ```ccylinder(r,h)``` | |
|
|
|
|
|
|
Additionally, the cube and box primitives have the versions ```ocube(dx,dy,dz)``` and ```cornerbox(dx,dy,dz)``` that position their front lower-left corners at the origin.
|
|
|
|
|
|
### Non-primitive Shapes <a name="nonprimitives"></a>
|
|
|
|
|
|
```linear_extrude(dir, points)```
|
|
|
|
|
|
Creates a closed object from the extrusion of a polygon along a direction ```dir```. The polygon's orientations is specified as set of either clockwise or counter-clockwise 2D vertices in ```points```.
|
|
|
* ```dir```: extruding direction
|
|
|
* ```points```: polygon specification
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
triangle = { v(-10,0), v(0,10), v(10,0) }
|
|
|
-- 50 units along the Z-axis
|
|
|
dir = v(0,0,50)
|
|
|
emit( linear_extrude(dir, triangle) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/d49fa94fafa25664d5a02a674f2b21ae/Example_linear_extrude.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```linear_extrude_from_oriented(dir, points)```
|
|
|
|
|
|
Creates a closed object from the extrusion of a polygon along a direction ```dir```. Solid geometry is specified as set of *closed* (i.e. the last vertex matches the first one) counter-clockwise 2D vertices and hollow geometry is specified as a set of closed clockwise 2D vertices in ```points```.
|
|
|
* ```dir```: extruding direction
|
|
|
* ```points```: polygon specification
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
polygon1 = { v(10,10), v(-10,10), v(-10,-10), v(10,-10), v(10,10) } -- Solid
|
|
|
polygon2 = { v(0,6), v(6,-6), v(-6,-6), v(0,6) } -- Hollow
|
|
|
dir = v(0,0,10)
|
|
|
emit( union(
|
|
|
linear_extrude_from_oriented(dir, polygon1),
|
|
|
linear_extrude_from_oriented(dir, polygon2)
|
|
|
) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/2c40c2e7a34c7b15751a6425267aaf18/Example_linear_extrude_from_oriented.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```rotate_extrude(points, nsteps)```
|
|
|
|
|
|
Creates a closed object from the spinning of a polygon along the Z-axis (axis of revolution). The polygon is specified as set of counter-clockwise 2D vertices in ```points```. ```nsteps``` defines the number of steps in the revolution of the polygon, the more steps the smoother the resulting shape is.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
radius = v(10,0,0)
|
|
|
triangle = { radius + v(1,0,0), radius + v(0,1,0), radius + v(-1,0,0) }
|
|
|
emit( rotate_extrude( triangle, 100 ) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/ae89126ccae1653103493ffef57bc099/Example_rotate_extrude.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```sections_extrude(contours)```
|
|
|
|
|
|
Crates a closed object by connecting each polygon contained in ```contours```. Similar to the functions above, a polygon is defined as a table of at least three points. ```contours``` is a table of more than one polygon and all polygons must contain the same number of points.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
se = sections_extrude({
|
|
|
{rotate( 0,Z) * v( 0, 0, 0),
|
|
|
rotate( 0,Z) * v(10, 0, 0),
|
|
|
rotate( 0,Z) * v(10,10, 0),
|
|
|
rotate( 0,Z) * v( 0,10, 0)},
|
|
|
|
|
|
{rotate( 60,Z) * v( 0, 0,10),
|
|
|
rotate( 60,Z) * v(10, 0,10),
|
|
|
rotate( 60,Z) * v(10,10,10),
|
|
|
rotate( 60,Z) * v( 0,10,10)},
|
|
|
|
|
|
{rotate(120,Z) * v( 0, 0,20),
|
|
|
rotate(120,Z) * v(10, 0,20),
|
|
|
rotate(120,Z) * v(10,10,20),
|
|
|
rotate(120,Z) * v( 0,10,20)}
|
|
|
})
|
|
|
emit(se)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/84e315d1cc4e2a6fbad720171f180280/Example_sections_extrude.jpg" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Implicits <a name="implicits"></a>
|
|
|
|
|
|
IceSL supports implicits by way of the [GL Shading Language](https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language) (GLSL). A comprehensive list of the built-in functions of GLSL can be found [here](http://www.shaderific.com/glsl-functions/)
|
|
|
|
|
|
```implicit_distance_field(boxMin, boxMax, fragment)```
|
|
|
|
|
|
```implicit_solid(boxMin, boxMax, voxSize, fragment)```
|
|
|
|
|
|
Creates an object out of the [implicit geometry](https://en.wikipedia.org/wiki/Implicit_function) calculated in ```fragment```. The bounding box constructed by ```boxMin``` and ```boxMax``` defines the boundaries of the implicit shape.
|
|
|
* ```boxMin, boxMax```: domain of the implicit. The domain is specified by the box constructed with corners ```boxMin``` and ```boxMax```
|
|
|
* ```voxSize```: voxel output size. Lower values result in greater quality at the expense of higher calculation costs.
|
|
|
* ```fragment```: string containing the GLSL program. This program calculates the implicit function that defines the output geometry.
|
|
|
|
|
|
Implicits are calculated in IceSL with a sphere tracing method (detailed [here](http://graphics.cs.illinois.edu/sites/default/files/zeno.pdf)). The program specified in ```fragment``` must contain a function called either ```float distance(vec3 p)```, in the case of ```implicit_distance_field```, or ```float solid(vec3 p)``` in the case of ```implicit_solid```. This function calculates the distance field or the solid/empty classification respectively for every point of the domain of the box. A resulting negative value is interpreted as _solid_ whereas a positive value means _hollow_. Consider the following example.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
cube = implicit_distance_field( v(-10,-10,-10), v(10,10,10),
|
|
|
[[
|
|
|
float distance(vec3 p) {
|
|
|
return -1;
|
|
|
}
|
|
|
]])
|
|
|
emit (cube)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/98f1f60e808308d35a4b4f2ea2e9280c/Example_implicit_1.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Above, every point in the domain of the implicit is marked as _solid_, therefore the geometry created has the shape of the boundary box.
|
|
|
|
|
|
Choosing ```implicit_distance_field``` over ```implicit_solid``` can be summarized as follows: The former requires to estimate a distance to the surface, which can prove difficult and prone to artifacts (when the estimate is too far off from reality). The latter is much easier, as the function simply has to return negative for solid and positive for empty.
|
|
|
|
|
|
#### Progressive rendering <a name="progressive"></a>
|
|
|
|
|
|
IceSL by default progressively renders implicits, consequently all the implicit's geometry may not render in one single frame. The order of rendering is defined by the distance to the camera (i.e. scene's point of view). To disable/enable this behavior use the following:
|
|
|
|
|
|
```enable_progressive_rendering(shape, bool)```
|
|
|
* ```shape```: output from either the ```implicit_*``` or ```to_voxel_*``` functions.
|
|
|
* ```bool```: either ```true``` or ```false```
|
|
|
|
|
|
This setting must be set right after the implicit/voxels creation. This is because IceSL clones a shape whenever it is transformed and/or reassigned to another variable. Each clone drags with it the _current_ value of this setting.
|
|
|
|
|
|
#### Uniform variables and file support <a name="uniforms"></a>
|
|
|
|
|
|
It is possible to set values for uniform variables specified inside the implicit's GLSL program via lua commands.
|
|
|
|
|
|
```set_uniform_{boolean|scalar|vector|matrix|texture3d}(implicit, var_name, var_value)```
|
|
|
|
|
|
sets ```var_name``` to ```var_value``` inside ```implicit```.
|
|
|
* ```implicit```: a created implicit
|
|
|
* ```var_name```: string specifying the name of the uniform variable in the implicit
|
|
|
* ```var_value```: new boolean/scalar/vector/matrix/texture3d/voxel_distance_field value
|
|
|
|
|
|
Furthermore, implicits can be loaded directly from files as the next function shows.
|
|
|
|
|
|
```implicit_distance_field_from_file(boxMin, boxMax, fileName)```
|
|
|
|
|
|
```implicit_solid_from_file(boxMin, boxMax, voxSize, fileName)```
|
|
|
|
|
|
Similar to ```implicit_distance_field``` and ```implicit_solid``` but the fragment program is in ```fileName```.
|
|
|
* ```boxMin, boxMax```: domain of the implicit. The domain is specified by the box constructed with corners ```boxMin``` and ```boxMax```
|
|
|
* ```fileName```: file containing the GLSL implicit program.
|
|
|
* ```voxSize```: voxel output size.
|
|
|
|
|
|
|
|
|
In the next example, we create an implicit whose points inside an origin-centered sphere are considered solid. The radius of the sphere is changed using ```set_uniform_scalar```.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
sphere = implicit_solid(v(-10,-10,-10), v(10,10,10), 0.25,
|
|
|
[[
|
|
|
uniform float r = 5;
|
|
|
float solid(vec3 p) {
|
|
|
return length(p) - r;
|
|
|
}
|
|
|
]])
|
|
|
set_uniform_scalar(sphere, 'r', 10.5)
|
|
|
emit(sphere)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/ae21547d9fbf2d1199d8ce753f9441e8/Example_implicit_2.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Notice how in the above example, the implicit boundary cuts off some parts of the sphere. Implicits are commonly used to construct geometry that is impossible to create with CSG or low-resolution meshes. See the following example.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
shape = implicit_distance_field(v(-2,-2,0), v(2,2,8),
|
|
|
[[
|
|
|
float distance(vec3 p) {
|
|
|
return 0.01 * ((pow(sqrt(p.x*p.x + p.y*p.y) - 3, 3) + p.z*p.z - 1) + noise(p));
|
|
|
}
|
|
|
]])
|
|
|
emit(scale(5) * shape)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/06292b311081b3b4ba6f77fe2aa7c356/Example_implicit_3.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
#### 3D Textures <a name="3dtextures"></a>
|
|
|
|
|
|
IceSL features the ability to construct 3D textures programmatically. There is support for single channel textures as well as RGB textures in 8bit and 32bit variants.
|
|
|
|
|
|
```tex3d_{rgb32f|r32f|rgb8f|r8f}(w,h,d)```
|
|
|
|
|
|
Creates a 3d texture class with the following possible specifications:
|
|
|
* ```rgb32f```: rgb 32bit float texture
|
|
|
* ```r32f```: luminance 32bit float texture
|
|
|
* ```rgb8f```: rgb 8bit float texture
|
|
|
* ```r8f```: luminance 8bit float texture
|
|
|
|
|
|
The 3D texture class possesses the following methods:
|
|
|
* ```w()```: return the texture's width
|
|
|
* ```h()```: return the texture's height
|
|
|
* ```d()```: return the texture's depth
|
|
|
* ```get(u,v,w)```: gets the value at texture coordinate ```(u,v,w)```. Values of each component are in the range $`[0-1]`$.
|
|
|
* ```set(u,v,w,val)```: sets the value ```val``` at texture coordinate ```(u,v,w)```. ```val``` is a vector where each component must be in the range $`[0-1]`$. If the texture type is luminance (i.e., one channel texture), the second and third components of ```val``` are ignored.
|
|
|
|
|
|
The following example shows a 1-channel 3D texture created programmatically and used as input in an implicit. Two solid cubes (one on each corner) made of the value ```-1.0``` are drawn into the texture while the rest is left at value ```10.0```. The implicit maps each point of the implicit area to a point of the texture repeated twice.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
tex_dim = v(10,10,10)
|
|
|
tex = tex3d_r32f(tex_dim.x,tex_dim.y,tex_dim.z)
|
|
|
for ucoord = 0, tex_dim.x-1 do
|
|
|
for vcoord = 0, tex_dim.y-1 do
|
|
|
for wcoord = 0, tex_dim.z-1 do
|
|
|
if (ucoord < tex_dim.x/2 and vcoord < tex_dim.y/2 and wcoord < tex_dim.z/2) or
|
|
|
(ucoord >= tex_dim.x/2 and vcoord >= tex_dim.y/2 and wcoord >= tex_dim.z/2) then
|
|
|
tex:set(ucoord,vcoord,wcoord,v(-1.0,0.0,0.0))
|
|
|
else
|
|
|
tex:set(ucoord,vcoord,wcoord,v(10.0,0.0,0.0))
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
|
|
|
imp_dim = v(20,20,20)
|
|
|
imp = implicit_distance_field(v(0,0,0), imp_dim,
|
|
|
[[
|
|
|
uniform sampler3D tex_data;
|
|
|
uniform vec3 imp_ext;
|
|
|
float distance(vec3 p)
|
|
|
{
|
|
|
return 0.01 * texture(tex_data,(p/imp_ext)*2.0).x;
|
|
|
}
|
|
|
]])
|
|
|
set_uniform_vector(imp, 'imp_ext', imp_dim)
|
|
|
set_uniform_texture3d(imp, 'tex_data', tex)
|
|
|
|
|
|
emit(imp)
|
|
|
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/ad5c9dcb1ccff2a925dc5061f1e4cbd4/Example_3dtex.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
## Transformations <a name="transformations"></a>
|
|
|
|
|
|
This section deals with linear transformations. IceSL offers functions to calculate matrices of transformations. To apply a transformation, a transformation matrix is multiplied with a shape. In order to combine more than one transformation, the result of successive multiplications of transformation matrices may also be multiplied with a shape. All applications of transformations should be consistent with a [http://mathworld.wolfram.com/Right-HandedCoordinateSystem.html right-handed coordinate system]. This means the *rightmost transformation* in a combination *takes precedence*.
|
|
|
|
|
|
```translate(dx,dy,dz)```
|
|
|
|
|
|
Returns a transformation matrix that translates a shape by ```dx,dy,dz``` units in the X-axis, Y-axis and Z-axis respectively.
|
|
|
* ```dx```: number of units to translate in the X-axis
|
|
|
* ```dy```: number of units to translate in the Y-axis
|
|
|
* ```dz```: number of units to translate in the Z-axis
|
|
|
|
|
|
```translate(v)```
|
|
|
|
|
|
Syntactic sugar for ```translate(v.x,v.y,v.z)```.
|
|
|
|
|
|
```rotate(angle,axis)```
|
|
|
|
|
|
Returns a transformation matrix that rotates a shape by ```angle``` degrees around the vector ```axis```.
|
|
|
* ```angle```: angle of rotation. In degrees
|
|
|
* ```axis```: a vector specifying the axis of rotation
|
|
|
|
|
|
```rotate(rx,ry,rz)```
|
|
|
|
|
|
```rotate(v)```
|
|
|
|
|
|
Syntactic sugar for ```rotate(rz,Z) * rotate(ry,Y) * rotate(rx,X)``` and ```rotate(v.z,Z) * rotate(v.y,Y) * rotate(v.x,X)``` respectively.
|
|
|
|
|
|
```scale(sx, sy, sz)```
|
|
|
Returns a transformation matrix that scales a shape by ```sx,sy,sz``` factors in the X-axis, Y-axis and Z-axis respectively.
|
|
|
* ```sx```: scale factor in the X-axis
|
|
|
* ```sy```: scale factor in the Y-axis
|
|
|
* ```sz```: scale factor in the Z-axis
|
|
|
|
|
|
```scale(s)```
|
|
|
|
|
|
```scale(v)```
|
|
|
|
|
|
Syntactic sugar for ```scale(s,s,s)``` and ```scale(v.x,v.y,v.z)``` respectively.
|
|
|
|
|
|
The above transformations have alternative names (mainly for compatibility purposes). The next table summarizes them:
|
|
|
|
|
|
| Transformation | Alternative |
|
|
|
| -------------- | ----------- |
|
|
|
| translate | translation |
|
|
|
| rotate | rotation |
|
|
|
| scale | scaling |
|
|
|
|
|
|
```mirror(normal)```
|
|
|
|
|
|
Returns a transformation matrix that mirrors a shape along the vector ```normal```.
|
|
|
* ```normal```: vector specifying the direction to mirror
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = load_centered('fox.stl')
|
|
|
emit( mesh )
|
|
|
emit( translate(0,-100,0) * mirror(v(0,1,0)) * mesh )
|
|
|
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/011d458a111f9a042915c0437acc3de4/Example_mirror.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```frame(v)```
|
|
|
|
|
|
Returns a transformation matrix that orients (i.e. aligns) a shape's [up vector](http://autodeskmaya.wikia.com/wiki/Up_Vector) to the direction ```v```.
|
|
|
* ```v```: a vector specifying the direction to orientate in the transformation.
|
|
|
|
|
|
### Magnets <a name="magnets"></a>
|
|
|
|
|
|
Magnets are volumeless shapes that help building objects by way of assembling parts. Think of a magnet as a fastener that eventually couples with other magnets from different shapes.
|
|
|
|
|
|
```magnet('name')```
|
|
|
|
|
|
* ```name```: magnet name
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
case = union( cylinder(5,10), translate(0,0,10) * magnet('m1') )
|
|
|
head = union( cone(5,1,10), translate(0,0,0) * rotate(180,X) * magnet('m2') )
|
|
|
emit(case)
|
|
|
emit(translate(-20,0,0) * head)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/afaab141ada4970939e6adc2f10d215f/Example_magnet.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Magnets have orientation (the coupling orientation). To couple the magnets, the function ```snap``` returns a transformation matrix that assembles one shape's magnet (i.e. ```shape1```) to another (i.e. ```shape0```). The example below builds upon the previous one with the last two ```emit``` statements removed.
|
|
|
|
|
|
```snap(shape0, magnet0, shape1, magnet1)```
|
|
|
|
|
|
* ```shape0```: base shape
|
|
|
* ```magnet0```: the base shape's magnet name
|
|
|
* ```shape1```: shape to be coupled
|
|
|
* ```magnet1```: coupling shape's magnet name
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
smatrix = snap(case, 'm1', head, 'm2')
|
|
|
emit(union(smatrix * head, case))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/b55ddd1afdae5a1945bd3e26e7ca872e/Example_snap.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
Snap matrices are not commutative with respect to their connecting magnets. Notice in the previous example that multiplying ```smatrix``` with ```case``` does not yield the same result.
|
|
|
|
|
|
## Operations <a name="operations"></a>
|
|
|
|
|
|
IceSL supports [Constructive Solid Geometry](https://en.wikipedia.org/wiki/Constructive_solid_geometry) (hereafter referred to as CSG). The following is a list of CSG operations:
|
|
|
|
|
|
### CSG Operations <a name="csg"></a>
|
|
|
|
|
|
```union(s0,s1)```
|
|
|
|
|
|
Returns a shape as the union of shape ```s0``` and shape ```s1```. This operation is commutative.
|
|
|
* ```s0```: A shape
|
|
|
* ```s1```: A shape
|
|
|
|
|
|
```intersection(s0,s1)```
|
|
|
|
|
|
Returns a shape as the intersection of shape ```s0``` and shape ```s1```. This operation is commutative.
|
|
|
* ```s0```: A shape
|
|
|
* ```s1```: A shape
|
|
|
|
|
|
```difference(s0,s1)```
|
|
|
|
|
|
Returns a shape as the difference of shape ```s0``` and shape ```s1```. This operation is **not** commutative.
|
|
|
* ```s0```: A shape
|
|
|
* ```s1```: A shape
|
|
|
|
|
|
IceSL supports abbreviated multi-input versions of these operations. Assume ```s``` is a shape and ```S``` is a table of shapes. The following table summarizes these operations.
|
|
|
|
|
|
| Operation | N-Argument Version | Short Version |
|
|
|
| --------- | ------------------ | ------------- |
|
|
|
| ```union(s0,s1)``` | ```union{s0,...,sn}, union(S)``` | ```U(s0,s1), U{s0,...,sn}, U(S)``` |
|
|
|
| ```intersection(s0,s1)``` | ```intersection{s0,...,sn}, intersection(S)``` | ```I(s0,s1), I{s0,...,sn}, I(S)``` |
|
|
|
| ```difference(s0,s1)``` | ```difference{s0,...,sn}, difference(S)``` | ```D(s0,s1), D{s0,...,sn}, D(S)``` |
|
|
|
|
|
|
N-ary versions from the above table are associative to the left. For example ```D{s0,s1,s2,s3}``` is equivalent to ```D(D(D(s0,s1),s2),s3)```. For this to be computationally sound [1](https://proofwiki.org/wiki/Union_of_Singleton) [2](https://proofwiki.org/wiki/Intersection_of_Singleton), the result of n-ary operations over a single shape is defined as the shape itself (i.e. ```U{s} = s```, ```I{s} = s``` and ```D{s} = s```).
|
|
|
|
|
|
### Other Operations <a name="otherops"></a>
|
|
|
|
|
|
```flip(m)```
|
|
|
|
|
|
Inverts the orientation of the faces from the mesh ```m```. This is specially useful when loading a mesh that has its faces defined clockwise.
|
|
|
* ```m```: input mesh
|
|
|
|
|
|
```convex_hull(shape)```
|
|
|
|
|
|
Creates the [convex hull](https://en.wikipedia.org/wiki/Convex_hull) of ```shape```. It only works with meshes or union of meshes.
|
|
|
* ```shape```: input primitive
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = load('crystal.stl')
|
|
|
emit( translate(100,0,0) * mesh )
|
|
|
emit( convex_hull(mesh) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/276b9ba6c7a260bde586b69e53463ae5/Example_convex_hull.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```dilate(mesh, factor)```
|
|
|
|
|
|
```erode(mesh, factor)```
|
|
|
|
|
|
[Dilates]( https://en.wikipedia.org/wiki/Dilation_(morphology) ) and [erodes]( https://en.wikipedia.org/wiki/Erosion_(morphology) ) a mesh respectively by ```factor```. The vertices in ```mesh``` need to be merged a priori (use ```merge_vertices```).
|
|
|
* ```mesh```: input mesh
|
|
|
* ```factor```: dilation/erosion factor
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = scale(0.1) * merge_vertices(load_centered('fox.stl'))
|
|
|
emit(translate(0,0,-6) * erode(mesh,0.3))
|
|
|
emit(translate(15,0,0) * dilate(mesh,0.5))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/bc4617409a7b056afd49689462c5706b/Example_dilate_erode.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```linear_offset(mesh,direction,offset)```
|
|
|
|
|
|
Creates a linear offset of ```mesh``` in the direction ```direction``` by factor ```offset```. Depending on the sign of ```offset```, the offset either goes inwards (i.e. negative sign) or outwards (i.e. positive sign). Only works with meshes with connectivity information, call ```merge_vertices``` when such information does not exist (e.g. _stl_ meshes).
|
|
|
* ```mesh```: input mesh
|
|
|
* ```direction```: offset direction
|
|
|
* ```offset```: offset factor
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
mesh = merge_vertices(load('fox.stl'))
|
|
|
emit( mesh )
|
|
|
emit( translate(100,0,0) * linear_offset(mesh,v(0,1,0),10) )
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/f6b8a5fb516b643473159df5acd0c3ce/Example_linear_offset.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```linear_offsets(mesh,directions,offsets)```
|
|
|
|
|
|
Same as ```linear_offset``` but multiple offsets can be applied at the same time. ```directions``` and ```offsets``` are arrays of vectors and numbers respectively and they have an ordered one-to-one correspondence.
|
|
|
|
|
|
## Shape Representation <a name="shaperep"></a>
|
|
|
|
|
|
IceSL offers several functions for calculating representations of shapes (i.e., meshes, voxels, etc).
|
|
|
|
|
|
```to_voxel_solid(shape, voxSize)```
|
|
|
|
|
|
```to_voxel_solid(tex3d, voxSize)```
|
|
|
|
|
|
Creates a solid voxel volume from ```shape``` or ```tex3d``` where each voxel measures ```voxSize``` units.
|
|
|
* ```shape```: input shape
|
|
|
* ```tex3d```: 3D texture
|
|
|
* ```voxSize```: voxel size (in mm)
|
|
|
|
|
|
```to_voxel_solid(tex3d, boxMin, boxMax)```
|
|
|
|
|
|
Creates a solid voxel volume from ```tex3d```. ```boxMin``` and ```boxMax``` specify the volume in space to create the solid. Values in ```tex3d``` below```0.5``` are considered solid, otherwise they are considered empty.
|
|
|
|
|
|
```to_voxel_distance_field(shape, voxSize)```
|
|
|
|
|
|
Creates a voxel distance field from ```shape``` using [this technique](http://www.comp.nus.edu.sg/~tants/jfa/i3d06.pdf). Each voxel measures ```voxSize``` units.
|
|
|
|
|
|
* ```shape```: input shape
|
|
|
* ```voxSize```: voxel size (in mm)
|
|
|
|
|
|
```set_distance_field_iso(voxels, threshold)```
|
|
|
|
|
|
In a distance field, sets the threshold to classify voxels as empty/solid whenever it is less/greater than ```threshold``` respectively.
|
|
|
|
|
|
* ```voxels```: voxel shape obtained by ```to_voxel_distance_field```
|
|
|
* ```threshold```: Number between ```0``` (empty) and ```1```(solid). Default is ```0.5```
|
|
|
|
|
|
```smooth_voxels(voxShape, windowSize)```
|
|
|
|
|
|
Smooths the voxel shape ```voxShape``` using a [trilinear interpolation](https://en.wikipedia.org/wiki/Trilinear_interpolation) with a windows size of ```windowSize```. This functions _does not_ return a shape, instead it modifies the shape specified on the first parameter.
|
|
|
|
|
|
* ```voxShape```: input shape. Only supports voxels
|
|
|
* ```windowSize```: interpolation 3D window size
|
|
|
|
|
|
```smooth_voxels_preserve_volume(voxShape, windowSize)```
|
|
|
|
|
|
Same as above but tries to preserve the shape's volume.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
s = sphere(5)
|
|
|
vs1 = to_voxel_solid(s, 0.1)
|
|
|
vs2 = to_voxel_solid(s, 0.1)
|
|
|
smooth_voxels(vs2,10)
|
|
|
emit(translate(0,0,0) * s)
|
|
|
emit(translate(15,0,0) * vs1)
|
|
|
emit(translate(30,0,0) * vs2)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/69b6b0930ded09a9c539f14033397535/Example_voxels.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```to_mesh(shape, voxSize)```
|
|
|
|
|
|
```to_mesh_dual(shape, voxSize)```
|
|
|
|
|
|
Creates a mesh from ```shape``` using the marching cubes or dual contouring algorithms respectively. Before calculating the resulting mesh, the 3D space containing the shape is discretized using voxels of size ```voxSize``` units.
|
|
|
|
|
|
* ```shape```: input shape
|
|
|
* ```voxSize```: voxel size of space discretization (in mm)
|
|
|
|
|
|
### From assets <a name="assets"></a>
|
|
|
|
|
|
```image_contouring(file,pixel_size)```
|
|
|
|
|
|
Extracts contours out of an image file. Pixels colored black are considered _hollow_, while any other color is considered _solid_. Returns a table of ```IMGContour``` objects.
|
|
|
* ```file```: input image file (PNG and TGA supported)
|
|
|
* ```pixel_size```: size in mm, of a pixel
|
|
|
|
|
|
The ```IMGContour``` object has the following members:
|
|
|
* ```outline```: The contour _(table)_
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
contours = image_contouring('shapes.png', 0.1)
|
|
|
for _,contour in pairs(contours) do
|
|
|
emit(linear_extrude_from_oriented(v(0,0,1), contour:outline()))
|
|
|
end
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/b5334a3f9d84f701e3727957ce6be7b7/Example_image_contouring.jpg" width="200">
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/82d378c0e4efb193bb5ea676e305b6b2/shapes.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```svg_contouring(file,dpi)```
|
|
|
|
|
|
Extracts contours out of a SVG file. Returns a table of ```SVGContour``` objects.
|
|
|
* ```file```: input svg file
|
|
|
* ```dpi```: dots per inch. Use 90 for Inkscape files
|
|
|
|
|
|
The ```SVGContour``` object has the following members:
|
|
|
* ```outline```: The contour _(table)_
|
|
|
* ```fill ```: fill color for the contour _(triplet)_
|
|
|
* ```stroke```: stroke color for the contour _(triplet)_
|
|
|
* ```strokeWidth```: stroke width for the contour _(num)_
|
|
|
* ```hasFill```: contour is color-filled _(bool)_
|
|
|
* ```hasStroke```: contour is color-bordered _(bool)_
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
svg_shapes = svg_contouring('restroom.svg',90)
|
|
|
for i,contour in pairs(svg_shapes) do
|
|
|
if contour:hasFill() then
|
|
|
set_brush_color(i, contour:fill()[1], contour:fill()[2], contour:fill()[3])
|
|
|
end
|
|
|
emit(linear_extrude_from_oriented(v(0,0,5),contour:outline()), i)
|
|
|
end
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/434f1733f99e33e71f3666761209ade6/Example_svg_ex.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```font()```
|
|
|
|
|
|
```font(ttf)```
|
|
|
|
|
|
Creates a font object based either using the default font provided by IceSL or the font described in the TrueType Font file ```ttf```.
|
|
|
* ```ttf```: TrueType Font file
|
|
|
|
|
|
The interface to the font object is the following:
|
|
|
* ```str(string, tracking)``` : Returns a 3D geometry of the string ```string```. If present, the font's [kerning](https://en.wikipedia.org/wiki/Kerning) information is added to ```tracking``` [tracking](https://en.wikipedia.org/wiki/Letter-spacing).
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
f = font(Path .. 'LiberationMono-Regular.ttf')
|
|
|
text = f:str('IceSL', 10)
|
|
|
emit(scale(0.5,0.5,10) * text)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/4b1fa3e9b2e4de82b33e286f1a2aaa4d/Example_font.jpg" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```load_raw_voxels(fileName, thicken)```
|
|
|
|
|
|
Creates a shape out of raw voxel data in ```fileName```. ```thicken``` stands for the thickening applied to the voxels.
|
|
|
* ```fileName```: input file
|
|
|
* ```thicken```: thickening of voxels
|
|
|
The format of the file is a continuous chunk of voxels with the following information in sequence:
|
|
|
1. Position (3 ints)
|
|
|
2. Normal (3 floats)
|
|
|
3. Color (3 unsigned chars)
|
|
|
4. State (1 bool)
|
|
|
|
|
|
### Distribute <a name="distribute"></a>
|
|
|
|
|
|
Additionally to changing the representations of a shape, IceSL also provides a function to calculate an evenly distributed set of points covering a surface. For each point this function also reports its surface normal and maximum distance to the set of nearest points.
|
|
|
|
|
|
```distribute(shape, density)```
|
|
|
|
|
|
Returns a Lua array describing the surface of ```shape``` using [Voronoid Iteration](https://en.wikipedia.org/wiki/Lloyd%27s_algorithm). The array is made out of triplets wherein the first element is a position of the surface, the second its surface normal and the third its distance to the furthest neighboring position in the array. How sparse the positions are is determined by the argument ```density```.
|
|
|
|
|
|
* ```shape```: input shape
|
|
|
* ```density```: position density. This argument is clamped to the unit interval where ```1``` signifies high density and ```0``` no density
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
shape = cube(10)
|
|
|
s = distribute(shape, 0.2)
|
|
|
centroids = {}
|
|
|
for i = 1,#s,1 do
|
|
|
centroids[i] = translate(s[i][1]) * frame(s[i][2]) *
|
|
|
union{ cone(s[i][3],0,1), mirror(Z) * cone(s[i][3],0,1) }
|
|
|
end
|
|
|
emit(union(centroids))
|
|
|
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/d1b3017bdeac39f7162c26f9ea279795/Example_distribute.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
## Other Functionality <a name="otherfunc"></a>
|
|
|
### Printing settings <a name="settings"></a>
|
|
|
|
|
|
Scripts also have the ability to change printing settings directly from within them. This allows the user (among other reasons) to specify printing settings tailored to the geometry being described in the script.
|
|
|
|
|
|
IceSL gives priority to an assignment of a printing setting according to the following list:
|
|
|
1. Default IceSL values -- _bottom priority_
|
|
|
2. Printer features (i.e., ```features.lua``` in printer profiles)
|
|
|
3. Print profile (e.g., fast print, high quality, etc.)
|
|
|
4. Material profile (e.g., abs, pla, etc.)
|
|
|
5. Lua script
|
|
|
6. User interface -- _top priority_
|
|
|
|
|
|
For example, if the value of a setting is specified in a printer profile as well as in the lua script, the latter takes priority. Moreover, if the user sets it manually using the UI then this overrides all other assignments.
|
|
|
|
|
|
```set_setting_value(setting, value)```
|
|
|
|
|
|
```set_setting_value(setting, value, bed_relative)```
|
|
|
|
|
|
Sets the printing parameter ```settings``` to ```value```
|
|
|
* ```setting```: Internal name of the printing setting to change
|
|
|
* ```value```: Value to assign. May be a boolean, a number, a string or a table. The latter is reserved to _per-layer_ assignments whereas the table is to be constructed as follows:
|
|
|
* ```{ [key_0]=value_0, ... , [key_n]=value_n }```
|
|
|
* where ```key_i``` specifies a height and ```value_i``` is a the parameter's value at such height.
|
|
|
* ```bed_relative```: If per-layer assignment, indicate whether the height is relative to the bed position (i.e., 0 means at bed level) or modeling position (i.e., 0 means at the center of geometry, see for example ```cube``` vs. ```ccube```). This parameter is _false_ by default.
|
|
|
* **NOTE**: Be aware that, at the point in the script where ```set_setting_value``` is being executed, the totality of the geometry is still unknown. The script hasn't finished executing and there might be more ```emit``` commands ahead. So when the parameter ```bed_relative``` is used, the bed position is still undecided, thus it is recommended to reload the script when this parameter is changing value to allow IceSL to recalculate the bed's final position.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
emit(cube(10))
|
|
|
set_setting_value('z_layer_height_mm', { [0.0]=0.2, [5]=0.3 })
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```set_setting_value(setting, tex3d, boxMin, boxMax)```
|
|
|
|
|
|
Sets the printing parameter ```setting``` as a _field_ that extends from ```boxMin``` to ```boxMax``` with values from ```tex3d```. Recall that individual values in textures are in the $`[0-1]`$ range, thus they are interpreted according to the setting's minimum and maximum values (e.g, 0.0 could mean no infill or zero degrees, and 1.0 could mean fully infilled or 360 degrees respectively).
|
|
|
* ```setting```: Internal name of the printing setting to change
|
|
|
* ```tex3d```: Value of the field as a 3d texture
|
|
|
* ```boxMin,boxMax```: Field extent
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
height = 50
|
|
|
radius = 10
|
|
|
obj = cylinder(radius, height)
|
|
|
emit(obj)
|
|
|
|
|
|
size_tex3d = 64
|
|
|
size_tex3d_half = size_tex3d / 2
|
|
|
density = tex3d_r8f(size_tex3d, size_tex3d, size_tex3d)
|
|
|
|
|
|
for i = 0,size_tex3d - 1 do
|
|
|
for j = 0,size_tex3d - 1 do
|
|
|
for k = 0, size_tex3d - 1 do
|
|
|
r = math.sqrt((i - size_tex3d_half) ^ 2 + (j - size_tex3d_half) ^ 2)
|
|
|
d = r / size_tex3d_half -- from 0 to 100 inside out
|
|
|
density:set(i,j,k, v(d,0.0,0.0)) -- y and x values are ignored
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
|
|
|
box = bbox(obj)
|
|
|
set_setting_value('infill_percentage_0', density, box:min_corner(), box:max_corner())
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td>
|
|
|
<img src="uploads/e6ff8f490ff96a7f1ac271f12835ae46/image.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Distance field <a name="distfield"></a>
|
|
|
|
|
|
```texture3d_distance_field(shape)```
|
|
|
|
|
|
Calculates a distance field based on the geometry of ```shape``` as a 3D texture where its coordinates correspond to positions in the bounding box volume of ```shape```. Each value of the computed distance field (i.e., the 3D texture) is in the range $`[0-1]`$ where `1` means the position is on the surface of ```shape``` or beyond (i.e., hollow). Positions inside ```shape``` (i.e., solid) decrease from `1` to `0` as the distance to the surface increases.
|
|
|
* ```shape```: Shape to calculate the distance field
|
|
|
|
|
|
### Variable caching <a name="caching"></a>
|
|
|
|
|
|
It is possible to turn on/off variable caching in IceSL with the system variable ```enable_variable_cache```. Variable caching is useful when editing a script that constructs an object or preforms a calculation that is CPU intensive (i.e. consumes significant time).
|
|
|
|
|
|
In the following example it is possible to change the scaling of ```mesh``` without incurring in the penalty of re-calculating the result of ```to_mesh```:
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
enable_variable_cache = true
|
|
|
s = sphere(10)
|
|
|
if not mesh then
|
|
|
mesh = to_mesh(s,1)
|
|
|
end
|
|
|
emit(scale(1) * mesh)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Tweaks <a name="tweaks"></a>
|
|
|
|
|
|
```ui_scalar(name, default, min, max)```
|
|
|
|
|
|
Creates a sliding bar to interactively set a float value between ```min``` and ```max```.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
* ```min```: minimum value
|
|
|
* ```max```: maximum value
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
r = ui_scalar("Radius",10.0,1.0,20.0)
|
|
|
emit(sphere(r))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/e942eccb69903c2991560051674b463f/Example_tweaks.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```ui_scalarBox(name, default, step)```
|
|
|
|
|
|
Creates a quantity (+/-) box stepped by ```step``` to interactively set a float value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
* ```step```: increment/decrement delta
|
|
|
|
|
|
```ui_number(name, default, min, max)```
|
|
|
|
|
|
Creates a sliding bar to interactively set an integer value between ```min``` and ```max```.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
* ```min```: minimum value
|
|
|
* ```max```: maximum value
|
|
|
|
|
|
```ui_numberBox(name, default)```
|
|
|
|
|
|
Creates a quantity (+/-) box to interactively set an integer value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
|
|
|
```ui_bool(name, default)```
|
|
|
|
|
|
Creates a checkbox to interactively set a Boolean value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
|
|
|
```ui_text(name, default)```
|
|
|
|
|
|
Creates a text input box to interactively set a string value.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```default```: default value
|
|
|
|
|
|
```ui_radio(name, list)```
|
|
|
|
|
|
Creates a radio box to interactively choose an integer value from a list.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```list```: an array of pairs of the form ```{integer, string}``` where ```integer``` is the id associated with ```string```
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
shape_list = {
|
|
|
{0, "sphere"},
|
|
|
{1, "cylinder"},
|
|
|
{2, "cube"}
|
|
|
}
|
|
|
shape = ui_radio("Shape:", shape_list)
|
|
|
|
|
|
if shape == 0 then emit(sphere(5))
|
|
|
elseif shape == 1 then emit(cylinder(5,10))
|
|
|
elseif shape == 2 then emit(cube(10)) end
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/0f6f18791297bc6e6c34cf7d2614f569/Example_tweakCombo.PNG" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
```ui_combo(name, list)```
|
|
|
|
|
|
Creates a combo box to interactively choose a string value from a list.
|
|
|
* ```name```: the tweak's name
|
|
|
* ```list```: an array of strings
|
|
|
|
|
|
```ui_selectFile(name)```
|
|
|
|
|
|
Creates a button to select an existing file. The return value is the file path
|
|
|
* ```name```: the tweak's name
|
|
|
|
|
|
|
|
|
### Fields <a name="fields"></a>
|
|
|
|
|
|
Fields are UI objects for interactively building 3D textures. They are useful for carving, sculpting and specifying surfaces among other things.
|
|
|
|
|
|
```ui_field(name, boxMin, boxMax)```
|
|
|
|
|
|
Creates a labeled button to build a 3D texture in the box space specified by ```boxMin``` and ```boxMax```.
|
|
|
* ```name```: field name
|
|
|
* ```boxMin```: left corner of the 3D texture
|
|
|
* ```boxMax```: right corner of the 3D texture
|
|
|
|
|
|
```ui_field_value_at(name, p)```
|
|
|
|
|
|
Retrieves the value of the field ```name``` (created by ```ui_field```) at position ```p```.
|
|
|
* ```name```: field name
|
|
|
* ```p```: position to inquire
|
|
|
|
|
|
```ui_file(fileName)```
|
|
|
|
|
|
Creates a UI to load/save all the script's tweaks and field values from/into ```fileName```.
|
|
|
|
|
|
* ```fileName```: file path to load/save tweaks and fields values
|
|
|
|
|
|
The following example sculpts a sphere using a field named ```Sculpting``` and saves the field values into the file ```sculpt.xml```
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
s = sphere(10)
|
|
|
bx = bbox(s)
|
|
|
bx:enlarge(1)
|
|
|
f = ui_field('Sculpting',bx:min_corner(),bx:max_corner())
|
|
|
ui_file(Path..'sculpt.xml')
|
|
|
result = intersection(s,to_voxel_solid(f,bx:min_corner(),bx:max_corner()))
|
|
|
emit(result)
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/30f7f0ead3f449befc9d5fe67b5b0d96/Example_fields.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
In the next example, we use a field to avoid distributing (i.e. function ```distribute```) parts of the shape surface.
|
|
|
|
|
|
<table>
|
|
|
<tr>
|
|
|
<td>
|
|
|
|
|
|
```lua
|
|
|
enable_variable_cache = true
|
|
|
shape = sphere(10)
|
|
|
if not s then
|
|
|
s = distribute(shape, 0.5)
|
|
|
end
|
|
|
bx = bbox(shape)
|
|
|
bx:enlarge(1)
|
|
|
f = ui_field('surface', bx:min_corner(),bx:max_corner())
|
|
|
cubes = {}
|
|
|
for i = 1,#s do
|
|
|
if ui_field_value_at('surface', s[i][1]) > 0.5 then
|
|
|
cubes[#cubes+1] = translate(s[i][1]) * frame(s[i][2]) * ccube(s[i][3])
|
|
|
end
|
|
|
end
|
|
|
emit(union(shape,union(cubes)))
|
|
|
```
|
|
|
|
|
|
</td>
|
|
|
<td>
|
|
|
<img src="uploads/3e2d7dde362967adb094ef5328aac543/Example_fields2.png" width="200">
|
|
|
</td>
|
|
|
</tr>
|
|
|
</table>
|
|
|
|
|
|
### Mesh Information <a name="meshinfo"></a>
|
|
|
|
|
|
```bbox(shape)```
|
|
|
|
|
|
Returns the bounding box of ```shape``` as an object ```AAB```.
|
|
|
* ```shape```: Input shape
|
|
|
The ```AAB``` object has the following members:
|
|
|
* ```min_corner```: Minimum corner of the bounding box _(vector)_
|
|
|
* ```max_corner```: Maximum corner of the bounding box _(vector)_
|
|
|
* ```center```: Center of the bounding box _(vector)_
|
|
|
* ```extent```: Dimensions of the bounding box _(vector)_
|
|
|
* ```empty```: Boolean value indicating whether the bounding box is _(bool)_
|
|
|
* ```enlarge(mm)```: Enlarges the box by ```mm``` millimeters _(method)_
|
|
|
|
|
|
```mesh_vertices(mesh)```
|
|
|
|
|
|
Returns a table containing the vertices of a mesh.
|
|
|
* ```mesh```: Input mesh
|
|
|
|
|
|
```mesh_normals(mesh)```
|
|
|
|
|
|
Returns a table containing the normals of a mesh.
|
|
|
* ```mesh```: Input mesh
|
|
|
|
|
|
```mesh_local_edge_size(mesh)```
|
|
|
|
|
|
Returns a table containing the average connecting edge length of every vertex of a mesh.
|
|
|
|
|
|
### Miscellaneous Functions <a name="miscfunc"></a>
|
|
|
|
|
|
```print(str)```
|
|
|
|
|
|
Prints the message ```str```
|
|
|
|
|
|
```dofile(path)```
|
|
|
|
|
|
Executes the script in ```path```
|
|
|
* ```path```: input string
|
|
|
|
|
|
```plugin_system_version()```
|
|
|
|
|
|
Returns the plugin system version string
|
|
|
|
|
|
```load_image(filename)```
|
|
|
|
|
|
Returns a 2D table where each $`(i,j)`$ index is a vector that corresponds to the rgb pixel from the image file ```filename```
|
|
|
|
|
|
```set_brush_color(brush, r, g, b)```
|
|
|
|
|
|
Sets the rendering color of ```brush``` to the normalized ```r```, ```g``` and ```b``` values.
|
|
|
* ```brush```: brush number
|
|
|
* ```r```: normalized (i.e., $`[0,1]`$) red component value
|
|
|
* ```g```: normalized (i.e., $`[0,1]`$) green component value
|
|
|
* ```b```: normalized (i.e., $`[0,1]`$) blue component value
|
|
|
|
|
|
```screenshot()```
|
|
|
|
|
|
Saves a screenshot in the ```pictures``` folder or current script folder for the windows build.
|
|
|
|
|
|
```sleep(ms)```
|
|
|
|
|
|
Suspends execution of IceSL by ```ms``` milliseconds.
|
|
|
* ```ms```: number of milliseconds
|
|
|
* ```path```: path to the script file
|
|
|
|
|
|
```dump(shape, filename)```
|
|
|
|
|
|
Saves the shape ```shape``` in file ```filename```
|
|
|
* ```shape```: shape to save
|
|
|
* ```filename```: destination file to save the shape. Supports _stl_ and _obj_ extensions
|
|
|
|
|
|
## Service Mode <a name="servicemode"></a>
|
|
|
|
|
|
IceSL offers the possibility of batch processing of its services (e.g., slicing, meshing, SVG output, etc.) without UI input. This is achievable through _Service Mode_.
|
|
|
|
|
|
In _Service Mode_, it is mandatory to provide IceSL with a lua script via the command line. There is no user interface nor any interaction from the user. Moreover, IceSL only outputs diagnostic information of the services used in the script.
|
|
|
|
|
|
### Invoking Service Mode <a name="invokeservicemode"></a>
|
|
|
|
|
|
_Service Mode_ can only be activated in _IceSL-slicer_, it **cannot** be invoked in _IceSL-forge_. To activate _Service Mode_, execute _IceSL-slicer_ with the `-s` flag and provide a script to execute:
|
|
|
|
|
|
* `IceSL-slicer.exe -s script_filename` (Windows)
|
|
|
* `./IceSL-slicer -s script_filename` (Linux)
|
|
|
|
|
|
A control string can be passed to the script while in service mode. This is done with the `-c` flag in the command line. It is subsequently set in the `control_string` global variable in the script:
|
|
|
|
|
|
* `IceSL-slicer.exe -c string -s script_filename` (Windows)
|
|
|
* `./IceSL-slicer -c string -s script_filename` (Linux)
|
|
|
|
|
|
|
|
|
### Service Mode functions <a name="servicemodefunctions"></a>
|
|
|
|
|
|
In addition to all other documented functions, the following also become available in _Service Mode_:
|
|
|
|
|
|
```set_service(service)```
|
|
|
|
|
|
Sets ```service``` as the current service to be used.
|
|
|
* ```service```: can be one of the following:
|
|
|
* ```'FilamentSlicer'```
|
|
|
* ```'DLPSlicer'```
|
|
|
* ```'LaserCutSlicer'```
|
|
|
* ```'MeshExportService'```
|
|
|
* ```'SVGSlicer'```
|
|
|
|
|
|
```run_service(filename)```
|
|
|
|
|
|
Executes the service on geometry emitted heretofore. Outputs the result to ```filename```.
|
|
|
|
|
|
```load_settings(filename)```
|
|
|
|
|
|
Loads settings (e.g., printing settings) saved in ```filename```.
|
|
|
* ```filename```: lua/xml file
|
|
|
|
|
|
```clear_brush(brush)```
|
|
|
|
|
|
Clears any emit done on ```brush``` up until this point.
|
|
|
|
|
|
### Service Mode examples <a name="servicemodeexamples"></a>
|
|
|
|
|
|
Slicing in _Service Mode_:
|
|
|
```lua
|
|
|
emit(scale(0.5) * load(Path..'fox.stl'))
|
|
|
set_service('FilamentSlicer')
|
|
|
load_settings(Path..'fox_printing_settings.lua')
|
|
|
run_service(Path..'fox.gcode')
|
|
|
```
|
|
|
|
|
|
Meshing in _Service Mode_:
|
|
|
```lua
|
|
|
emit(difference(ccube(40),sphere(25)))
|
|
|
set_service('MeshExportService')
|
|
|
set_setting_value('meshing_method', 'Dual contouring')
|
|
|
output_name = control_string..'.stl'
|
|
|
run_service('C:\\Users\\milchy\\Documents\\'..output_name)
|
|
|
``` |
|
|
\ No newline at end of file |