Basic CSG
The classic constructive solid geometry solid (see Constructive solid geometry): a cube with
its corners rounded off by a ball, drilled through along all three axes. It is described with the
expression builder, compiled into a Tape (see The tape), and evaluated on the host and on a
GPU. The source is at Examples/BasicCSG/main.cpp.
Fig. 18 The solid as the viewer first shows it.
Describing the solid
Every analytic shape converts to an Expr, and the
builder functions in EBGeometry_Expr.hpp combine
expressions without evaluating anything. Intersection keeps what is inside both operands and
Difference removes the second from the first; like Union, both take a pair or a std::vector:
const Expr solid = Difference(Intersection(cube, ball), Union(drills));
Compiling and using it on the host
A Tape compiles the expression into a Pool, which must outlive the tape and every copy of it (see Memory model):
Pool pool(hostMemoryResource());
const Tape<T> tape(pool, solid);
const T value = tape.signedDistance(point); // negative inside, positive outside
An intersection or a difference of exact distances is only a lower bound on the distance, which
getDistanceQuality() reports. closestPrimitive(point) names the leaf the value comes from (see
Which part: the deciding primitive), numbered in expression order: the cube 0, the ball 1, the drills 2 to 4.
The same query on a GPU
The query is a trivially copyable functor holding the tape by value. The program freezes the pool,
mirrors it into GPU::memoryResource() (device memory in a CUDA or HIP build), and runs the query
on a view of the tape onto the copy:
pool.freeze();
const Pool devicePool = Pool::mirror(pool, GPU::memoryResource());
GPU::transform(Distance{tape.rebasedView(devicePool)}, points, values);
In a plain C++ build the same lines run on the host.
Looking at it
The example ends with Render::view(tape, pool, argc, argv), a window on the solid.
The window needs SDL2 and is built with make VIEWER=SDL2 or cmake -DEBGEOMETRY_VIEWER=SDL2 (see
The viewer window (EBGEOMETRY_VIEWER)); otherwise, and with --no-view or without a display, view() prints why
and returns. Drag to orbit and scroll to zoom; the window lists its other keys (see
The viewer’s keys).
Building and running
See Building for how to compile it with CMake, GNU Make, or a direct compiler invocation, and Running on a GPU for a GPU build.
cd Examples/BasicCSG
./BasicCSG.ex