sabresaurus / SabreCSG

Level design tools for Unity
MIT License
1.36k stars 137 forks source link

Better collision geometry #194

Open hickVieira opened 5 years ago

hickVieira commented 5 years ago

I think I noted that the collision geometry is just a mesh-collider of the output CSG, which is a bad approach in my opinion. Instead, we could use the shape of each brush to generate collision geometry. Use box-colliders for 6-faced brushes and convex-mesh-colliders for non-6-faced brushes, or maybe even make it a option.

Subtraction brushes would be a problem, but we could just use non-convex-mesh-colliders (aka the method that is being used now) for these particular brushes (could make it an user option).

Henry00IS commented 5 years ago

SabreCSG used to have colliders per-brush. You can still find remnants of it in the source code (that currently removes colliders on brushes as part of an upgrade process for old levels made with previous versions of SabreCSG). Perhaps @sabresaurus can shed some light on why this was done.

PhysX (the physics engine Unity uses) can pre-process and optimize a static "polygon soup" (the collision mesh) to then do collision checks very quickly at play. There are several early-outs, assumptions and shortcuts you can take. One example is a quick dot product on an imaginary plane that cuts through the center of the level to determine whether the object is completely on the left or right side of the polygon soup; already you can skip 50% of the polygons. It can also create an octree in advance that will quickly tell what level polygons exist in the bounding box of the collider to then only check a handful of polygons. But regardless of the algorithms implemented;- It all comes with the condition that this mesh must NOT be moved. It's the reason why you can only have convex rigidbody colliders (older PhysX versions used to internally create convex colliders out of the polygon soup but this has since been discontinued as it may have (supposedly) resorted to creating a convex collider for every polygon).

The convex collider provides several assumptions and early-outs that make it optimal for very fast boundary checks. Every polygon has a unique normal and a quick dot product on every polygon can tell you whether something is inside of it. It's essentially a more advanced version of the bounding box.

Having too many convex colliders will increase the component count in Unity and consume additional resources which may eventually slow down all collision checks. Some real-world levels in SabreCSG can easily have over 3000 brushes or more. We'd have to generate over 3000 convex colliders. This will also inevitably slow down scene loading times and the overal performance of SabreCSG. Once #103 is fixed we will have very optimized geometry that can be passed on to PhysX dealing with any potential concerns.

Please correct me if I am wrong.

sabresaurus commented 5 years ago

In earlier versions of SabreCSG editor selection of brushes was implemented by raycasting against mesh colliders with meshes matching the preview mesh on the brush mesh renderer. Later on I implemented ray-brush intersection for another feature (I don't recall which, perhaps it was the Clip tool), so it seemed a good idea to replace the collision components which internal intersection tests. SabreCSG automatically cleans up collision geometry on brushes from old levels as a result.

A common approach is to have two CSG models - one for rendering, one for collision, that way you can simplify your collision geometry. You can also toggle rendering/collision per brush in SabreCSG which is useful if you are doing visual detailing but don't want to contribute towards collision complexity.

I'm not sure I'd agree that mesh colliders from the output polygon soup are inherently bad, for many use cases they work and are efficient. However I take your point that it's a shame when building additively that SabreCSG can't generate box/convex mesh colliders. In fact I've already written an optional extension to do this - SabreCSG Extensions (Brush to Collider), this could be rolled into SabreCSG as an option with support added for convex mesh colliders when brushes aren't cuboid. SabreCSG has been used in production environments in the past with this approach to allow efficient primitive collision geometry to be generated (and I observed it to be more efficient than mesh colliders).