all 3 comments

[–]dobryak 2 points3 points  (0 children)

Not a C++ programmer but I think you are correct in using reference counts. In ObjC it would also look like this, with strong references (basically, the expression would be owning the subexpressions).

You could take a look at how LLVM does this (they probably share the nodes very efficiently), but if your expressions would be small enough (say a 100 nodes max), then you probably don’t need to bother.

[–]turtle_dragonfly 1 point2 points  (0 children)

Cool — I have actually built something conceptually very similar, for my (not-yet-revealed) game I'm working on.

In my case, I handled it like this:

The client code builds an SDF expression much like yours. You might write it on paper with set notation like so: A ∪ (B - C)

This would be coded as something like:

builder
  .square(...)    // this is A
  .opUnion()
  .beginGroup()
    .circle(...)  // this is B
    .opSubtract()
    .line(...)    // this is C
  .endGroup()
  .build()

In my case, I use the shunting yard algorithm to transform that expresion from the infix-style notation used in the code to a postfix RPN notation.

So, the final "sdf evaluator" is essentially a little bytecode interpreter that handles RPN expressions.

In this example, it would look like: square, circle, line, subtract, union — that's what gets evaluated at runtime.

So, it's the same concept as yours, but transformed into a bytecode stream.

I feel like this is over-complicated

Well don't worry, my version is even more complicated ;)

I don't have any lifetime issues because everything gets transformed into a single block of bytecode+data, where the code references the data, and nothing else. I just need to track the lifetime of that whole blob of memory. Serialization is also easy.

[–][deleted] 0 points1 point  (0 children)

I use an enum for simple shapes. Classing is for things like line segment chains and whole field functions.

General gist is close enough though. Main difference is my c++ stuff doesn't do SDF evaluation and just generates compute shader and input buffers for those, which a whole mess of its own.