manifold icon indicating copy to clipboard operation
manifold copied to clipboard

Improve Godot Engine's boolean operator engine (CSG) with `elalish/manifold`

Open fire opened this issue 2 years ago • 107 comments

  • [x] Restore normals and tangents
  • [x] Postpone running a profiler and see if there's easy bottlenecks
  • [x] Write a Godot Engine proposal
  • [x] Generating CSG nodes is slow on a full character mesh added to a box
  • [x] Can start providing test cases that crash the godot engine patched with manifold
  • [x] Remove exceptions from elalish/manifold ?
  • [x] Propose idea
  • [x] Ask for comments
  • [x] Investigate code details
  • [x] Tech lead of Godot Engine is ok with requiring manifold geometry inputs for CSG
  • [x] Remove requiring Cuda Developer Kit to build.
  • [x] Check performance latency of mesh generation (per frame? per second? per minute?)
  • [x] Blocked on removal of boost dependency
  • [x] The results of boolean operations look great. No gaps.
  • [x] Restore UV coordinates
  • [x] Restore materials

fire avatar Apr 05 '22 13:04 fire

That would be awesome! Technically it should be possible to build Thrust with the C++ backend without using nvcc (from the CUDA toolkit) since Thrust is just a C++ header library. However, I haven't tried it yet. I'd like to migrate from Thrust to C++17 parallel algorithms partially to simplify the code and make it run in parallel on more than just CUDA GPUs, but also to make standard compiler chains work better.

Are you interested in helping to try some of these options?

elalish avatar Apr 05 '22 15:04 elalish

Can you briefly describe a guide?

  1. where inputting manifold meshes
  2. apply union, intersect and merge
  3. output another mesh?

fire avatar Apr 05 '22 16:04 fire

I think this test and the following one demonstrate all of that: https://github.com/elalish/manifold/blob/master/test/mesh_test.cpp#L698

And of course the docs: https://elalish.github.io/manifold/classmanifold_1_1_manifold.html

elalish avatar Apr 05 '22 16:04 elalish

Is it difficult to disable assimp?

fire avatar Apr 05 '22 16:04 fire

Assimp is only linked for building meshIO. It's separated for exactly this reason; I figured most users would use their own input/output code.

elalish avatar Apr 05 '22 16:04 elalish

To give some context on Godot's CSG usage, Godot features CSG nodes (with both primitive and user-supplied custom meshes) that can be used to block out levels. CSG nodes can also have one or more material slots configured (and assigned on a per-face basis), which are preserved by the CSG algorithm and can be assigned by the user. The documentation can be found here.

Custom code had to be written for this back in 2018, since CSG libraries available at that time were generally GPL-licensed. (Godot is MIT-licensed and therefore needs to avoid (L)GPL-licensed components.)

This custom code is relatively small, but it also suffers from many bugs, especially with coplanar faces:

  • https://github.com/godotengine/godot/issues/41140
  • https://github.com/godotengine/godot/issues/43755
  • https://github.com/godotengine/godot/issues/58637

Mesh generation performance is good enough for static level design, but performing real-time changes should be avoided to prevent stuttering during gameplay. (That said, I doubt any CSG library can be fast enough to guarantee that mesh generation happens in < 16 milliseconds with typical low-poly game meshes. Moving mesh generation to a separate thread is probably a good idea.)

[x] Tech lead of Godot Engine is ok with requiring manifold geometry inputs for CSG

For reference, the current custom CSG implementation already has this as a requirement:

Any mesh can be used for CSG, this makes it easier to implement some types of custom shapes. Even multiple materials will be properly supported.[^1] There are some restrictions for geometry, though:

  • It must be closed
  • It must not self-intersect
  • Is must not contain internal faces
  • Every edge must connect to only two other faces

Godot gets CSG support

In parallel, we'd like to rework the CSG editor for better usability, but this can be done separately from the underlying mesh generation algorithm.

[^1]: Multiple materials per CSG node are already supported since Godot 3.1.

Calinou avatar Apr 07 '22 23:04 Calinou

@elalish Can you remove boost graph dependency?

https://github.com/haasdo95/graphlite was the closest I can find.

fire avatar Apr 08 '22 08:04 fire

I was able to extract https://github.com/V-Sekai/godot/tree/csg-manifold [does not compile] and did a build system trick to enable .cu, but the boost dependency was too much after the 8th Boost folder...

fire avatar Apr 08 '22 12:04 fire

Interesting, I'm still relatively new to the world of C++ libraries and didn't imagine Boost would be a big problem dependency-wise. I'm only using it for a connected components algorithm - figured better not to reinvent the wheel. Still, that's a generic algorithm and I'm sure it's available elsewhere, or we could just write our own. Thoughts?

elalish avatar Apr 08 '22 15:04 elalish

Can you evaluate https://github.com/haasdo95/graphlite? I wasn't able to find many substitutes.

What operations are you using?

fire avatar Apr 08 '22 20:04 fire

All I use is connected_components (in two places): https://github.com/elalish/manifold/blob/3e92f47c89b48aa384c41f27e2c7b1a63194c1c5/manifold/src/impl.cu#L427

graphlite doesn't technically include it, but it basically has it sketched out here: https://github.com/haasdo95/graphlite/blob/dde08e41c75b5fe42f7e3e0c6b02c4883b23155f/src/graph_lite/serialize.h#L156

Shouldn't be too hard to switch over. I like the idea of keeping my dependencies light.

elalish avatar Apr 10 '22 05:04 elalish

Can you do an estimate how difficult the work is, and if you need help?

fire avatar Apr 11 '22 12:04 fire

Shouldn't be more than a few hours, ideally. However, I'm leaving on vacation tomorrow for the rest of the week. If you want to take a stab at it, you're welcome to. Otherwise I'll take a look next week.

As far as taking a dependency on graphlite, should I just copy in graph_lite.h and note the git hash it's from? I can't think of a better way at the moment...

elalish avatar Apr 11 '22 16:04 elalish

I'm swamped with pending work. I can't promise anything.

It'll mostly like be next week.

Regarding dependencies, Godot Engine has a readme and a licenses document.

fire avatar Apr 13 '22 13:04 fire

Here's my thoughts on the two Material Case.

  1. mesh 1 mat 1 and mesh 2 mat 2 need to be converted to mesh 1 mat 3 and mesh 2 mat 3
  2. mat 3 uses xatlas to combine or a simple algorithm that uses double the uv space. (like 4x)
  3. Use manifold on the mesh 1 and mesh 2.

fire avatar Apr 17 '22 15:04 fire

Yeah, pretty much. You can do steps 1 and 2 after 3 (which means you can do it after many boolean operations and just deal with the UV coords that are left if you want). This is what the MeshRelation is for.

elalish avatar Apr 18 '22 06:04 elalish

I've got a WIP #92 to change the graph dependency.

elalish avatar Apr 18 '22 06:04 elalish

Debugging winding order and conventions.

Do you have an example cube with the positions and the triangle vertex indices?

fire avatar Apr 18 '22 14:04 fire

CCW. Manifold cube = Manifold::Cube(); should give you what you need, yeah?

elalish avatar Apr 18 '22 15:04 elalish

image

image

If I used the meshes from the manifold library I was able to do csg operations, but still working on the mesh import. It crashes on non-manifoldness.

fire avatar Apr 18 '22 21:04 fire

Works perfectly now :) unknown

ksuprynowicz avatar Apr 18 '22 23:04 ksuprynowicz

Some fun shapes. image

fire avatar Apr 18 '22 23:04 fire

Nice work! So @fire, if this is working, does that mean the Boost dependency is okay, or you still need that removed?

elalish avatar Apr 19 '22 04:04 elalish

So @fire, if this is working, does that mean the Boost dependency is okay, or you still need that removed?

The Boost dependency still needs to be removed if this is to be integrated in Godot core. We can't integrate such a massive dependency in Godot's repository (as we include the source of all dependencies within https://github.com/godotengine/godot). Small binary size and fast build times are important to us, so we had to make this decision.

Calinou avatar Apr 19 '22 10:04 Calinou

I posted the changes I used here https://github.com/elalish/manifold/pull/93.

Here's a Godot Engine master patched branch https://github.com/V-Sekai/godot/tree/csg-manifold-03.

fire avatar Apr 19 '22 12:04 fire

Notes:

  1. Generating CSG nodes is slow on a full character mesh added to a box, but did not run a profiler
  2. Can start providing test cases that crash the godot engine patched with manifold
  3. Can we remove exceptions from elalish/manifold ?
  4. The results of boolean operations look great. No gaps.

fire avatar Apr 19 '22 13:04 fire

Can we remove exceptions from elalish/manifold ?

To clarify, we want Godot to remain buildable without exceptions, so they need to be disableable at build-time. It's fine to keep exception code for those who want it, but it needs to be optional.

Calinou avatar Apr 19 '22 13:04 Calinou

logs_28140.zip

7_Compilation (armv7).txt

Here are the logs that fail on exceptions.

fire avatar Apr 19 '22 14:04 fire

Posting my test godot project so I can clean up my desktop.

CSG Game Project.zip

fire avatar Apr 19 '22 15:04 fire

When you say remove exceptions, what exactly do you mean? Are you hoping for old-school error return codes or something?

elalish avatar Apr 19 '22 15:04 elalish