CSG library for C#

Hello 3dDevs,
i’ve ported the java j3dbool library to C#. Constructive Solid Geometry (CSG) is a modeling technique that uses Boolean operations like union and intersection to combine 3D solids. This library implements CSG operations on meshes. All edge cases involving overlapping coplanar polygons in both solids are correctly handled.

It’s a standalone library, it does not require Unity3D. A small example is included (using OpenTK OpenGL wrapper).
It seems, the library does not generate normals. My 3D skills are not the best, so i cannot add this functionality.

I’ve compared some CSG implementations, i think j3dbool/Net3dbool have nicer polygon cuts.

It’s free and open source!

(No, i will not create an asset :slight_smile: )

Greetings,
Sebastian

1 Like

Hi Arakis - you can generate normals automatically with mesh.
Have you tried using something like:
mesh.RecalculateBounds();
mesh.RecalculateNormals();
mesh.Optimize();
Will have a look at your library… to see if I can help at all - I’m looking for something similar to this.

Managed to get it working fine in Unity.
I’ll put up a package soon.
Going to try out some different csg operations.

Here’s a replacement Demo.cs that works in Unity. The library should work with it.
Attach to a GameObject and set the material (I used a defaut).
using System;
using UnityEngine;
using Net3dBool;

public class Demo : MonoBehaviour
{
public Material ObjMaterial;
public Net3dBool.Solid mesh;

public Net3dBool.Color3f[ ] getColorArray(int length, Color c)
{
var ar = new Net3dBool.Color3f[length];
for (var i = 0; i < length; i++)
ar = new Net3dBool.Color3f(c.r, c.g, c.b);
return ar;
}
public void Start()
{
var box = new Net3dBool.Solid(Net3dBool.DefaultCoordinates.DEFAULT_BOX_VERTICES,
Net3dBool.DefaultCoordinates.DEFAULT_BOX_COORDINATES,
getColorArray(Net3dBool.DefaultCoordinates.DEFAULT_BOX_VERTICES.Length, Color.red));

var sphere = new Net3dBool.Solid(Net3dBool.DefaultCoordinates.DEFAULT_SPHERE_VERTICES,
Net3dBool.DefaultCoordinates.DEFAULT_SPHERE_COORDINATES,
getColorArray(Net3dBool.DefaultCoordinates.DEFAULT_SPHERE_VERTICES.Length, Color.red));
sphere.scale(0.68, 0.68, 0.68);
var cylinder1 = new Net3dBool.Solid(Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_VERTICES,
Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_COORDINATES,
getColorArray(Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_VERTICES.Length, Color.green));
cylinder1.scale(0.38, 1, 0.38);
var cylinder2 = new Net3dBool.Solid(Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_VERTICES,
Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_COORDINATES,
getColorArray(Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_VERTICES.Length, Color.green));
cylinder2.scale(0.38, 1, 0.38);
cylinder2.rotate(Math.PI / 2, 0);
var cylinder3 = new Net3dBool.Solid(Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_VERTICES,
Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_COORDINATES,
getColorArray(Net3dBool.DefaultCoordinates.DEFAULT_CYLINDER_VERTICES.Length, Color.green));
cylinder3.scale(0.38, 1, 0.38);
cylinder3.rotate(Math.PI / 2, 0);
cylinder3.rotate(0, Math.PI / 2);
//–
//mesh = s;
//–
// var modeller = new Net3dBool.BooleanModeller(b, c1);
// mesh = modeller.getDifference();
//–
var modeller = new Net3dBool.BooleanModeller(box, sphere);
var tmp = modeller.getIntersection();
modeller = new Net3dBool.BooleanModeller(tmp, cylinder1);
tmp = modeller.getDifference();
modeller = new Net3dBool.BooleanModeller(tmp, cylinder2);
tmp = modeller.getDifference();
modeller = new Net3dBool.BooleanModeller(tmp, cylinder3);
tmp = modeller.getDifference();
mesh = tmp;
MeshFilter mf = gameObject.AddComponent ();
Mesh tmesh = new Mesh();
int mlen = mesh.getVertices().Length;
Vector3 [ ] vertices = new Vector3[mlen];
for(int i=0; i<mlen; i++)
{
Net3dBool.Point3d p = mesh.getVertices();
vertices = new Vector3((float)p.x, (float)p.y, (float)p.z);
}
tmesh.vertices = vertices;
tmesh.triangles = mesh.getIndices ();
int clen = mesh.getColors ().Length;
Color [ ] clrs = new Color[clen];
for (int j=0; j<clen; j++) {
Net3dBool.Color3f c = mesh.getColors()[j];
clrs[j] = new Color((float)c.r, (float)c.g, (float)c.b);
}
tmesh.colors = clrs;
tmesh.RecalculateNormals();
mf.mesh = tmesh;
MeshRenderer mr = gameObject.AddComponent ();
mr.materials = new Material[1];
mr.materials[0] = ObjMaterial;
mr.material = ObjMaterial;
}
}

1 Like

First of all i want to say congratulations for transcoding and porting that code to U3D, i have tried some CSG code libraries for unity3d online recently and had major errors, and am keen to run this demo file…

I am seeing something confusing already in the Demo.cs file… i.e., only at line 14:

{
var ar = new Net3dBool.Color3f[length];
for (var i = 0; i < length; i++)
ar = new Net3dBool.Color3f(c.r, c.g, c.b);

cannot implicitly convert [ ] to float… i am not sure how you managed to run that demo file?!?

Hi i had a session with it last night, have it running, it does take 20-30 seconds to render the cube-sphere-3cylinders with about 450 vertices to run through… here is a unitypackage with demo.cs:

So lets get on our 3dkini’s and play net3dbool.

2260545–151190–CSG-WORKING-UNITY3D-NET3BOOL.unitypackage (65.6 KB)
2260545--151192--csg.jpg

Awesome. Sorry I must have put up an old copy of Demo.cs.
It wasn’t something I was concentrating on anyway :slight_smile:
However… you may be a little more interested in what I made last night. I have built a CSG Toolkit using the awesome Node Editor kit made elsewhere in the forums (I’ll add the links in… dont have them at the moment).
So… the result was this:

And because the majority of the code and systems is open. I’ll be putting this all up for free. Its great_fun to play around with. I need to fix some bugs and general use case issues (probably a day or so to sort out). I’ll post it here hopefully tomorrow sometime.

Thanks greatly to Sebastian and the Unity community (for Node Editor)… it stuns me how fast this sort of complex system can be built.
Cheers,
Dave Lannan

Im also going to look into beefing up the performance a bit. There are a number of loops and such that could be optimized. Im even thinking of pushing some of it into CUDA.

2 Likes

Hi Dave, Seems like a very cool project, Did you manage to get Unity3d primitives working with the net3dbool code? If ever you have any kind of working version in unity, I’d love a unitypackage version and i’d probably fork it into a different project using coded formations of primitives like structuresynth program.

I am currently transferring a U3d project to another program which is more adapted for CSG of mesh, it’s trouble tough i have to rewrite primitives by points and triangles and translations and rotations as matrices. I would love a copy.

I timed the performance with union of cubes at 50s for 100 cubes on a Q8200 processor, and i found that it crashed if i try to get the difference of cubes in a line because there is an array error when the modelling function doesn’t find shared vertices.

would love to see the node editor, there are many and i haven’t seen that one, i actually learnt to code using maths nodes. the shader is very cool, what shader is it?

Antony Stewart

Hi Antony,
Heres my current build. Now few warnings:

  • Its in development so go knows what it can and cannot do :slight_smile: … be careful. Ive had a couple of odd operations completely crash Unity (still trying to find these sorts of bugs - sounds a little like the problem you had).
  • Its going to change alot… The more I work with this lib, the more I want to rewrite/reorganize some things to improve performance. Generally the node editor interface will remain the same, but I will be adding a number of operators and effects to do all sorts of things.
  • The code is not all mine, in fact only a small portion is, so I cannot vouch for most of it, and I do not know what much of it actually does :slight_smile: … The Node Editor is great… but Im very new to it.

Links to Node Editor:

http://forum.unity3d.com/threads/simple-node-editor.189230/page-3

Below is the package - it should be installed into Assets/Plugins… folder.
All operations work in editor mode - no need to run.
Beware that some operations can run for minutes!!! I need to put a display in the operator node for that!

2262283–151371–CSGEditor.unitypackage (616 KB)

Hi David,

Did you manage to get it working with Unity3d primitives?

Whooa that’s very kind of you. Thanks very much. I installed it to a new project and Assets/Plugins folder, I couldn’t find node editor in the windows menu, and the demo file couldnt import to an empty gameobject as there is a compilation error somewhere regarding BeginClip and EndClip and Unityenging.GUI…

Still the Node-Editor is awesome i think i can bring over some of my untidy projects to that, I have seen your coding is amazing tidy… as soon as i start a project it rapidly becomes 20 fast tests of different things all in the same file with no files structure…

:smile:

Ok see you, will have a go afterwards. I just spend all day working on rotation matrix things. :smile: fun!

have to say my priorities are to have it working with unity3d mesh formats and also in realtime… in playmode will help to find the array errors and can be interesting for optimising it. will see.

PS
I was investigating the possibility of having a modifiable polygonal terrain in Unity, and was looking for implementations of CSG in C#.

Currently I’m playing around with GitHub - LogicalError/Realtime-CSG-demo: Code from article "Real Time Constructive Solid Geometry" in the book "Game Development Tools" trying to figure out what the hell is going on there and how to use it in Unity.

That’s a good idea. Currently with this CSG implementation, you can expect that making 100 pyramids into some mountains will take around 30 seconds, Same with another implementation i have called openSCAD, the CSG is slow. I think that a processor can run under 10 cubes in realtime, and it will struggle afterwards at slow frame rates. I think that example with 4 houses is probably at the limits of a processor for csg, perhaps it’s even on a graphics card. you can save meshes and make nice meshes using a landscape generator with this code very easily, just place some pyramids randomly around on top of a giant cube that can be an underlying plane or something. The code isnt tested at all though, i can figure it could crash with more than 100 cubes. 1000 cubes takes me 5 minutes on a purpuse built csg program, and i am wondering if this program will freeze far beyond 100 i’ll have to give it a try. actually, i don’t know why they used 4 houses, maybe its the same house for all 4 instances, so indeed less than 10 cubes at current frame rates.

I am currently getting a crash when i try to merge 200 cubes into a chain.

at least unity still hasn’t finised 10 minutes later, and it’s a 2 minute task.

A CSG engine shouldn’t do that. openscad can run 2000 cubes into a mesh so this one should else it is unreliable.

It’s a plain C# using OpenTK for rendering.

~55 fps with 4 houses
~120 fps with 2 houses
40% CPU (i5-2500K @4GHz)

As far as I understand, all the houses are built from a bunch of primitives/brushes every frame. Each house consists of 112 brushes.

Hi Antony - yes, it works works with any normal mesh as well as unity primitives.
Not sure what bug you have there. You should not use it with the Demo.cs - its a different system now.
You should see a Menu Item under the Windows menu:
Windows->CSG Editor
Hi alex - yes, in fact I am using the tool I have made to build constructive geometry features like walls with windows and so on. The main problem is the way unions and intersections are being done is for generic solutions. So I need to optimize a number of the loops or push it to CUDA (this is my current preference).
The pic below is a quick wall with window node canvas - you can save each canvas too. Then I want to make a node tool that lets you iterate objects with transforms, instances and distortions (warps, shears etc). so you can construct buildings and so on.

The CSG system is actually quite ok. It just needs to be made to suit either GPU;s or some Vector/Multicore CPU features. There is a huge amount of room for optimizing this package. It will take me some time (probably a week or so, for the first pass) but I expect at least a 10x improvement with fairly basic optimization methods.

If you are having problems getting the package to work, I’ll try to do some testing on it tonight. It should work fine from an empty scene. Im not sure how it will work with other packages (again, very new to the Node Editor tool).
Cheers,
Dave

Thanks Dave i’ll see if i can find the CSG option in window i didn’t see it previously…

Indeed optimization is disastrous…

I think other CSG libraries must use octrees and vector proximity from the current mesh to see which mesh to process, here is the performance with cubes:

1-2 cubes = 10fps, 50 cubes = 3fps, 100 cubes = 0.8 fps, 200 cubes is 0.25 fps…

to add a cube to a 1200 vertex object takes 4 seconds.
Didn’t find topics for optimize CSG very easily, optimizing obscure programming routines is difficult to have specific info’s about and especially code examples, so i don’t know how it’s done, indeed CGAL take 5 mins for 1000 cubes and here it would be over 1 hour.

CGAL library is optimized, perhaps see from them how it’s done.

To CUDA would be awesome, perhaps it is like making a cuda version of MC in terms of complexity, i.e. coding doctor challenge :smile: would be fascinating to learn how that is done :smile:

Alex: Quick question. I havent looked at the library you mentioned. Do you think it might be worth putting in place of the original one from the OP? Im not sure I want to try out another library, but the toolkit I have is now fairly detached from the underlying library, and before moving into do some perf work it might be worth looking at the other one - does it support UV / Material mapping during operations? Im currently implementing an environment based mapping method (planar, sphere etc), but it would be nice if this worked already.

Also, I have added a primitive node into the toolkit. This way you dont need to supply game objects if you dont want to. However all gameobjects must have the mesh at its root and single mesh only (start simple).

Should have another update in a few hours.
Cheers,
Dave

I don’t know yet. I’m still figuring out the principles it’s based on and trying to assemble a working prototype in Unity.

I don’t know very much about the CGAL library, just have used an implementation in a openSCAD which is a very simple free algorythmic 3d mesh program. CGAL doesn’t have a .net version, it’s c++ only and i don’t know anything about libraries they seem very advanced programming tasks, it may be worth seeing if there is some csg documentation in the cgal website, to have an idea of csg loops structures. the ultimate processing power of a csg library is crucial to know in advance of a development.

Alex - thanks. I’ll look at it anyway.
Antony - thanks, CGAL is a library I have used before. Not likely to use it again due to its license issues. The csg editor I want to be pretty much MIT/Apache type licensing - so anyone can use it or commercialize it if they want (no restrictions - GPL is very restrictive).

I didn’t get a build up last night. Still working on some more operators and effects as well as fixing some bugs in the primitive generators. Should have something up tonight.