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.

_images/example_BasicCSG.jpg

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