AngelScript CSG

Download AngelScript CSG version V2.0-02, with IDE included
Windows 64bit here.
Linux (K)ubuntu 15.10 64bit here.

Constructive Solid geometry (CSG) is a form of 3d modelling where you assemble simple 3d primitives into a hierarchy to make interesting 3d objects.  This technique is much used e.g. in 3d printing.


The key to CSG modelling is using 3d primitives like cylinder, sphere, cube … and for each of them apply 3d transformations like translate, rotate and scale. Finally, the transformed pieces are assembled into a CSG tree using 3d operations like union, difference and intersection. The result is a (hopefully) interesting 3d object. Wikipedia has a nice example:

A CSG assembly (from Wikipedia)


A popular open source program for CSG modelling with focus on 3d Printing is OpenSCAD. It is different from other CAD software in that it does not provide a complicated graphical user interface for modelling, but instead provides its own language for describing models. Below is a very simple example of OpenSCAD code for defining a simple “lollipop”, i.e. an object consisting of a stick to hold it and the head with the sweet:

OpenSCAD code below

// CSG modelling with OpenSCAD.  

// Carsten Arnholm, 26. December 2015


module lollipop(height, radius, head_radius )


   // use cylinder and sphere primitives and

   // assemble as a union.

   union() {





   // The union is implicitly returned


// model parameters

height       = 200;

radius       = 5;

head_radius  = 20;


// assemble and rotate


lollipop(height, radius, head_radius );


// export needs to be done from the OpenSCAD GUI
File → Export ...


The resulting model becomes:

This is all very nice. There are a couple of things to observe, however. One is that The OpenSCAD language is static, i.e. you cannot change the values of the “variables” in the program, they are just declarations of named values. Another is that the models created cannot be assigned to variables and reused via them. The only means of abstraction available are functions (called “modules”) that implicitly return the model created within them. Also, the language is unique to OpenSCAD, and there seems to be significant resources put into developing this language in the OpenSCAD project.

Possible changes

This author is of the opinion that the excellent idea of OpenSCAD as a language oriented CSG modeller would benefit from a couple of (admittedly major) changes:

  • Use an existing scripting language instead of a self made language. This would enable focusing on the modelling features rather than the language syntax. For example, the somewhat  incomprehensible “list comprehensions”  is an example of obscure language syntax.

  • Use a more complete geometry/topology kernel such as for example OpenCascade instead of the facet-based and very resource-demanding CGAL. This could also simplify the language syntax by doing away with the “convexity” parameters that are currently seen in OpenSCAD, they are really irrelevant from a modelling point of view.

These are clearly radical suggestions that will probably never be implemented in OpenSCAD. This does not, however, stop one from experiementing with such ideas. The focus of this post is the language (#2 in the list is left for some other time). Could we use an existing scripting language to implement similar functionality as is currently in OpenSCAD?


I have been playing with the idea of using AngelScript as a language interpreter for CSG modelling. AngelScript has some very nice features for end users and is designed for integration into a C++ application. The language provides pretty much everything in the current OpenSCAD language, plus much more

  • It is not just a declarative language, variables can be modified

  • The script writer can, if needed write functions and even classes.

  • The language is strongly typed

  • and much more.

As an experiment a CSG interpreter prototype using AngelScript has been implemented. As with any real prototype, the idea is not to make a final application, just explore the possibilities. This is throw-away work, with the sole intention of learning. Also, since this prototype does not address #2 in the list, the prototype simply exports to the OpenSCAD .csg file format for visualisation (The OpenSCAD .csg file format is not the same as the OpenSCAD language, but it is still dependent on it).

So let us try the “lollipop” example in the prototype AngelScript CSG interpreter:

AngelScript CSG code below

// CSG modelling with AngelScript
Carsten Arnholm, 25. December 2015

// a global constant + a function to convert from degrees to radians

const double pi = 4.0*atan(1.0);        

double rad(double deg) { return pi*deg/180.0; }


csg_solid@ lollipop(double height, double radius, double head_radius )


   // use cylinder and sphere primitives and

   // assemble as a union. We choose to keep variables here.

   csg_cylinder@ stick = csg_cylinder(height,radius);

   csg_solid@ head     = csg_sphere(head_radius);

   return csg_union( array<csg_solid@> =

                    { stick, translate(0,0,stick.height())*head }




void main()


    // model parameters

    double height       = 200;

    double radius       = 5;

    double head_radius  = 20;       


    // assemble and rotate

    csg_solid@ model = rotate_y(rad(30)) *



    // export to OpenSCAD-style .csg for display




The generated CSG file “lollipop.csg” :

Generated OpenSCAD-style CSG file (generated from AngelScript CSG)

group() {

   multmatrix([[0.866025396499,0,0.500000012618,0],[0,1,0,0],[-0.500000012618,0,0.866025396499,0],[0,0,0,1]]) {

      union() {

         multmatrix([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]) {

            cylinder( r1=5, r2=5, h=200 );


         multmatrix([[1,0,0,0],[0,1,0,0],[0,0,1,200],[0,0,0,1]]) {

            sphere( r=20 );






The generated CSG file  displayed in OpenSCAD:

As can be seen, the result is the same in both cases, and it makes it possible to evaluate the syntax similarities and differences. For an example as small as this, the AngelScript code does not appear to offer much benefit, but the code illustrates some important differences.

Basic construction and type safety of 3d primitives

First, observe that parts can be referred to in variables, like this

csg_cylinder@ stick = csg_cylinder(height,radius);

 double h = stick.height();   // Ok

The “stick” is a variable of type csg_cylinder, which allows you to do things like extracting data from it in code later, such as reading the cylinder height. The following code is also allowed:

csg_solid@ stick_solid = csg_cylinder(height,radius);

Because every csg_cylinder is also a csg_solid, it can be received as such. You are however, no longer allowed to call the height() function in this case:

       double h = stick_solid.height();    // error, slick_solid is not a csg_cylinder

… unless you typecast the stick_solid variable back to a csg_cylinder type:

csg_cylinder@ stick = cast<csg_cylinder@>(stick_solid);
double h = stick.height();   // Ok

The use of the character @ behind the types means that the variable is a handle. All of the CSG objects in the prototype are handle types and is used with the @ character.

3d transformations
Transformations are handled with a syntax familiar to OpenSCAD-users, except an explicit  multiplication operator is used  to indicate the coordinate system transformation from the object being transformed to the coordinate system of the result:

      csg_solid@ head = translate(0,0,stick.height()) * csg_sphere(head_radius);


Transformations can also be stored in variables:

tmatrix@ transform = rotate_y(pi/2) * translate(1,0,0);


Angelscript CSG vs OpenSCAD

Thefollowing is a summary of the CSG related commands

Angelscript CSG


3d primitives

csg_solid   (abstract type)


csg_cone(double h, double r);


csg_cube(double size);


csg_cuboid(double dx, double dy, double dz);


csg_cylinder(double h, double r);


csg_sphere(double r);


3d transformations

tmatrix   (abstract type)

multimatrix([ …. ]);

rotate_x(double rx);


rotate_y(double ry);


rotate_z(double rz);


scale(double sx, double sy, double sz);


translate(double dx, double dy, double dz);


Boolean operations

csg_difference(csg_solid@ incl, csg_solid@  excl);
(array<csg_solid@>@ also accepted)

difference() { ... }

csg_intersection(csg_solid@ incl, csg_solid@  excl);
(array<csg_solid@>@ also accepted)

intersection() { ... }

csg_union(array<csg_solid@>@+ arr);

union() { ... }


Math functions




Other language features





For non-trivial models, it looks like using a language like AngelScript is indeed interesting. The Angelscript CSG prototype shows it is possible to express CSG models that have similar characteristics as OpenSCAD, but using an existing object oriented scripting language. It also shows that using objects will allow more flexible and powerful expressions, since the object properties may be retrieved from the objects directly (like in the example with the cylinder height).


To implement such features in AngelScript is reasonably straight forward. All you have to do is write C++ classes for the different concepts and expose constructors and member functions to those classes in AngelScript by means of the AngelScript API. The current prototype implementation is not 100% stable, for some cases there are issues with using the built-in array type (see for example its use in csg_union). However, such issues can always be overcome with a bit of effort.


All in all, the prototype appears successful in that it demontrated how a language like AngelScript can be used for CSG modelling.


Leave a Reply

Your email address will not be published. Required fields are marked *