Overview
ShapeJS is a language designed to make creating and sharing 3D printable objects easy. Based on Javascript, it provides a rich set of solid modeling primitives over top a powerful voxel engine. The combination enables control of 3d printed objects down to printer resolution levels. The voxel approach has many advantages over typical triangle systems and aligns well with how 3d printers actually manufacture items. Scripts include a parameter definition to allow interactive exploration of interesting variants via an automatically generated user interface. The script, current parameters and any external resources can be saved into a simple transmittal format that others can easily load.
These docs describe the new ShapeJS 2.0 system. ShapeJS 2.0 is a major overhaul of the original ShapeJS system. Core to this release is a focus on creating real time responses. We've been prototyping several creators on the Shapeways site to prove out this point. Check out the Pendant Creator, Ornament Creator and Audio creators for examples of what's possible.
We developed ShapeJS to serve two primary communities: makers and creator creators. In the maker community OpenSCAD has shown the way in a simple but powerful scripting language for creating physical objects. They married a scripting engine to a powerful CAD kernel. For many makers this emphasis on a programming approach to 3D modeling resonated well. ShapeJS is similar in concept with a few significant differences. It is based on a voxel kernel instead of a triangle one and it’s built on a common programming language(Javascript), which is complete and used all over the world by millions of people.
To avoid a holy war I won't detail the differences too much here. Most 3D printers work by adding together small bits of material into a complete object. Using triangles to describe these voxels makes the code more difficult and harder to allow for print resolution accuracy. ShapeJS and the accompanying editor is designed to make creating 3D printable objects fast and easy. Using voxels avoids the most common reasons that 3d prints fail. Currently if you download a triangle model from most 3d repositories they typically must be repaired before printing. This is because it's very hard to write triangle code that retains the mathematical rigor necessary for 3d printing. ShapeJS will always generate manifold and oriented models that can be 3d printed. For these reasons we felt that writing a new language was warranted and would in the end prove valuable in the maker's toolbox.
The second community we wanted to target is are people who want to write object creators for others to use. We call them "Creator Creators" and we see them as a necessary enabler for 3d printing to be usable by humanity at large. A natural progression when developing an object is to parameterize its function. Similar to software an object gains features during it's development. These parameters allow the object to be used in a wider context and meet more peoples needs. A natural tendency is to want to share your creations with others. Now that many people have 3D printers at home and access to many more through printing services its become feasible to share the design for an object and expect others to be able to make it. ShapeJS provides a development environment to create those parameterizable objects and a way to share those designs with others.
The voxel based representation gives ShapeJS greater flexibility in shape generation over traditional representation via triangle meshes. It is similar to advantages 2D raster graphics has over 2D vector graphics. Vector graphics is great for drawing diagrams and raster graphics is on practice the tool of choice for anything else.
The way to fill the voxel grid is to create an object with a DataSource interface, which can calculate signed distance function for each point in space. The distance function calculations may be very complex task for complex object. But this calculation can be simplified by composing complex objects from many simpler ones using several simple operations.
There are several predefined simple object like Sphere,Box, Cylinder and Cone. More complex methods include functionality to convert 2D image to a 3D embossed object using Image3D object and importing user provided 3D object using load() function.
There is a flexible set of transformations which can be applied to any DataSource object. Transformations include standard 3D linear transformations like rotation, translation, scale, reflection. Flexibility of using volume based data allows to use arbitrary non linear transformation among those are RingWrap, SphereInversion, FriezeSymmetry, WalPaperSymmetry, ReflectionSymmetry. Several simple transformations can be composed into more complex transformation using CompositeTransform. A transformation can be applied to any DataSource object via its setTransform() method.
Script Structure
ShapeJS Scripts are Javascript programs over top the AbFab3D Voxel library. All standard Javascript functionality is supported.
Below is a simple ShapeJS program.
function main(args) { var r = 10*MM; var sphere = new Sphere(r); var bounds = new Bounds(-r,r,-r,r,-r,r); var scene = new Scene(sphere,bounds); return scene; }
Click Simple Sphere to run this example.
All ShapeJS scripts should have a function main(args). This function is executed by the ShapeJS scripting engine. The main function must return a Scene object. A scene specifies how to create the object,its physical bounds and other global properties. It is possible to pass arbitrary arguments (including uploaded files) to the main(args), but we will explain this later.
The unit of length in ShapeJS is meters. To avoid awkward numbers there are a few useful conversion constants in the global scope, MM=0.001 for millimeters, IN=0.0254 for inches.
The scene bounds are the area in which ShapeJS will endeavor to display. The Bounds are a box, defined as Bounds(X minimum, X maximum, Y minimum, Y maximum, Z minimum, Z maximum). These distances are relative to the center of everything, which you will generally use as the center of your bounds as well, (0,0,0), which is also called the origin. It is the center of the scene, as well as the default center for data sources. If whatever data source you are displaying is red and cut off at its edges, this is a warning that part of it is extending out of the Bounds of your scene. To remedy this, simply enlarge the scene size. There are some performance implications for having bounds too large so try to keep them relatively minimal. An optional parameter voxelSize is the size of a grid voxel. It defines the resolution of volume rendering. A Voxel size of 0.1 millimeter corresponds to the printing resolution of most 3D printers in 2015. This parameter greatly affects speed of all calculations and the best approach is to keep it larger (0.2mm or 0.3mm) during script development and set to printer resolution only at the final stage.
Controlling parameters of output mesh
When writing triangle models from ShapeJS there are some variables that control different aspects of the operation. These parameters are set on the Scene object returned from the main function.
setMeshSmoothingWidth Width of gaussian smoothing of the grid before conversion to triangle mesh. The width is given relative the grid voxel size. Default value is 0.5.
setMeshErrorFactor is maximal error allowed during mesh decimation (reducing mesh complexity). It is given relative to voxel size. Default value is 0.1. Smaller values greatly increase the resulting mesh complexity.
setMinPartVolume allows to filter out sand size particles from the resulting mesh. All parts of volume less than meshMinPartVolume are discarded. This volume is specified in meters3. Default value is 0.
setMaxPartsCount specifies the maximum number of parts to save. The n largest parts are kept. By default all parts are retained.Parameters
ShapeJS scripts can contain a parameter definition that defines the interface of the script. These parameters should be user facing parameters that allow changes to the object. They will typically be used in automatic user interface creation and they will be available in the IDE for you to modify.When main is called on your script you are passed a map of the parameter values. This map contains the parameter name as the key and then the current parameter value as a native Javascipt object. These can be referenced as "args.radius" inside your script.
All parameters have the following properties:Name | Description |
---|---|
name | The name of the parameter. Must be unique in the script. |
label | The label to use in user interfaces. Defaults to name if not provided |
desc | A textual description of the parameter, usually used in tool tips. |
dataType | The type of data. See DataTypes section for valid values |
defaultVal | The default value for the parameter. JSON encoded value. |
group | Grouping ID. Used to group similar properties together. |
onChange | Function to call when the value changes. Defaults to main |
Data Types
The following data types are supported:Double
A floating point number. Doubles have a default unit of measure which is M for meters. If a non default value is specified then the script will convert the value to meters when sending in the main(args) method.{ name: "textHeight", desc: "Text Height(mm)", type: "double", rangeMin:1, rangeMax:1000, step: 0.5, defaultVal: 5, group: "Text" }
Name | Description |
---|---|
rangeMin | The minimum acceptable value. Defaults to -Infinity |
rangeMax | The maximum acceptable value. Defaults to +Infinity |
step | The step value to use in user interfaces such as sliders |
unit | The unit of measure. Valid values are: M,CM,MM,UM,IN,FT. Defaults to M |
Enum
Enumerated values. This defines a list of valid values. Example:{ name: "purpose", desc: "Purpose", type: "enum", values: ["MESH","RENDER","PICK"], defaultVal: "RENDER", }
Name | Description |
---|---|
values | JSON encoded list of valid string values |
Location
Represents a 3D location and orientation in space. Location parameters usually implemented by allowing the user to click onto the object to place something. The default value for this type is a JSON map with two properties: point and normal. The point is a 3D position in space. The normal is the outward surface direction at that point.Example:
{ name: "textpos0", desc: "Text Pos1", type: "location", defaultVal : {"point":[-0.024,0,0],"normal":[0,0,1]} }
Name | Description |
---|---|
pointMin | The minimum point value allowed. |
pointMax | The maximum acceptable value. Defaults to +Infinity |
String
String valuesName | Description |
---|
URI
A URI references a resource such as an image or 3d model. A URI type will typically allow the user to use a local file from their system. It can also use fully qualified URL's to access network resources. Example:{ name: "image", desc: "Image", type: "uri", defaultVal: "http://www.website.com/sample_image.png" }URI's support the use of stock images and models. These are resources that are available to all scripts and are typically useful for default content.
{ name: "image", desc: "Image", type: "uri", defaultVal: "urn:shapeways:stockImage:allblack" }
Stock Media
URI | Description |
---|---|
urn:shapeways:stockImage:allblack | An image of all black(0,0,0) pixel values |
urn:shapeways:stockImage:allwhite | An image of all white(255,255,255) pixel values |
urn:shapeways:stockImage:gradient | An image gradient that goes from black to white in a left to right direction |
urn:shapeways:stockImage:smallbox | An 3d model of a 10mm box |
urn:shapeways:stockImage:box | An 3d model of a 20mm box |
urn:shapeways:stockImage:smallsphere | An 3d model of a 10mm diameter sphere |
urn:shapeways:stockImage:sphere | An 3d model of a 20mm diameter sphere |
Mental Model
When your authoring a ShapeJS script it's helpful to understand what's going on under the covers. Your script is building up a datasource graph that describes the object. This graph is composed of datasources as the nodes. Each datasource contains a transform that locates it in and its children in space.ShapeJS's transform graph allows for any arbitrary transformation. Unlike traditional real time graphics you are not restricted to affine transformations such as translation, scale, rotation. These are available of course but you can also do more interesting effects such as twists and infinite symmetry calculations.
Change Listeners
A parameter can contain a field called onChange. By default this just recalls the main() method with the changed parameters. If you specify a different method name then that method will be called each time the parameter is changed. These change listeners are expected to modify the current scene. This maybe faster then rerunning main each time. Currently we are looking at some caching techniques that would hopefully make authoring change listeners unnecessary.Javascript
We use the Rhino Scripting engine in Java which implements Javascript 5. If you want specific details you can find the project documentation here: Rhino DocumentationFunctions
ShapeJS has global helper functions accessible from your script.double sx | x size of grid |
double sy | y size of grid |
double sz | z size of grid |
double voxelSize | The size of each voxel. |
String filename | The name of the file to load |
double voxelSize | The size of voxels to use, defaults to 0.1mm |
double margin | The margin around the object, default to voxelSize. |
String filename | The name of the file to load |
double pixelSize | The size of pixels to use, defaults to 0.1mm |
String filename | The name of file to load |
String filename | The name of the file to load |
double voxelSize | The size of voxels to use |
String filename | The name of the file to load |
Grid grid | The grid to load the result into. Will overwrite filled areas with model data, unfilled areas will not be changed. The grid must be large enough to contain the object. |
String filename | The name of the file to load |
double voxelSize | The size of voxels to use, defaults to 0.1mm |
double maxDist | The maximum distance to calculate from the surface, defaults to 1mm. |
int algo | The algorithm to use. Defaults to 0. Algoritm 1 is a slightly more accurate version of 0 but much slower. Algorithm 2 is the ShapeJS 1.0 original algorithm for backwards compatibility. |
Variables
ShapeJS has global variables accessible from your script.MM | Conversion factor from mm's to meters. |
MM3 | Conversion factor from mm^3 to m^3 |
CM | Conversion factor from cm's to meters. |
IN | Conversion factor from in's to meters. |
FT | Conversion factor from feet to meters. |
Objects
Specific objects are exposed to the scripts. This section lists the objects exposed and provides links to their documentation.Math
The standard Javascript Math object is available. W3Schools provides a nice overview here