Create a gist now

Instantly share code, notes, and snippets.

@paniq /csgtree.rst
Last active Aug 8, 2016

What would you like to do?
CSG Tree Pruning

CSG Tree Flattening & Pruning

Based on whether the evaluation of two input primitives returns that the region we're operating on is fully inside the primitive (-), fully outside (+), or intersecting with the primitive surface (o), we can predict whether the output of a union (OR), or intersection (AND) operation will be fully inside, outside or potentially intersecting as well.

A CSG subtraction A - B is equal to X AND NOT Y, where the sign of the right operand is inverted.

A B OR AND
- - - -
o - - o
+ - - +
- o - o
o o o o
+ o o +
- + - +
o + o +
+ + + +

- = cell fully inside o = cell contains surface + = cell fully outside

We can flatten any CSG tree into a list of operations. For example, this sequential union of four primitives:

A    B
 \  /
  OR   C
   \  /
    OR   D
     \  /
      OR

...can be written as a sequence of operations:

%1 = A
%2 = OR %1 B
%3 = OR %2 C
%4 = OR %3 D

After line-by-line evaluation, %4 holds the result of the computation. The list can be further turned into pseudo-assembly with a single register E0 and two ops, SET and OR:

0: SET E0 +
1: OR E0 [A]
2: OR E0 [B]
3: OR E0 [C]
4: OR E0 [D]
5: END

From the truth table above it becomes apparent that if line 1 evaluates to -, none of the dependent operations need to run, as they will also all evaluate to -. We generalize to all other cases, and extend each binary operator with two branch arguments that serve as a jump table for the two definite result cases - and +, specifying how many operations may be skipped:

0: SET E0 +
1: OR E0 [A] 3 0
2: OR E0 [B] 2 0
3: OR E0 [C] 1 0
4: OR E0 [D] 0 0

Let's observe the translation of a more complex tree with composite operators:

A    B C    D
 \  /   \  /
 AND    SUB
   \   /
    OR   E
     \  /
      OR

We observe that AND can be skipped if A is outside, that SUB can be skipped if C is outside and that all OR's can be skipped if AND or SUB are inside.

The corresponding flat list requires two registers and looks like this:

0: SET E0 +
1: OR  E0 [A] 0 1
2: AND E0 [B] 5 0
3: SET E1 +
4: OR  E1 [C] 0 2
5: SUB E1 [D] 2 0
6: OR  E0 E1  1 0
7: OR  E0 [E] 0 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment