Boolean (CSG union, intersect, etc) 3D shapes into p5js model

A few years ago a feature request on p5.js’ github asked about boolean 3d modeling – which was determined to be best added as a library. Researching the topic now with a student and that thread informed us about CSG, specifically the csg.js library – which is amazing, however unclear how to make this compatible with p5.js models and WEBGL geometry.

I’ve made an attempt with csg.js in this demo – which successfully displays the vertices, however doesn’t form a useful model that would allow texture or shaded fill on it. Curious if someone here has enough experience with p5.js + WEBGL + meshes/geometry for guidance on bringing the outputs of csg.js closer to what p5.js works with when importing an obj.

There’s a few brigdges out there for csg.js » three.js:
ThreeCSG, THREE-CSGMesh, threejs-csg, three-2-csg, more…
Maybe one of them can help solve the issue? End result – library/function/bridge to create custom solid 3d shapes with this library or similar.

hello again :slight_smile: I checked the code and obviously normalMaterial needs normal of each vertex. You can get the information from csg.js, but there is another problem that p5.js’ begin/endShape doesn’t support setting normals (Processing does). There is an ongoing discussion here:

Meanwhile I made a simple visualization of normals:

For the texture, similar to the normals you need texture coordinates. I don’t think it comes with csg.js so you may need to implement your own:

Use your own vertex class instead of this one to provide additional features like texture coordinates and vertex colors.
csg.js/csg.js at master · evanw/csg.js · GitHub


Hellooo – thanks for the quick insight and tip about those normal values being included with csg (saw them, but didn’t quite get what it was for… clear now). Ahh that’s too bad (at the moment) we can’t set custom normals within the beginShape()/endShape() – but would be amazing if this proposed solution was accepted. I guess this would help when using lights() and colors, but not necessarily texture’s as you mention it would still need a uv set… hmm curious how they’re solving this in the three.js implementations that are based on this original lib… guessing they’ve added such a custom vertex class.

I’m getting close but not sure why some normals are wrong. (Edit: I fixed the issue. At first I stored vertex position in the dictionary, but obviously there are same vertices that have different normals, so the dictionary also needs to distinguish these vertices)

It seems in this three.js library, they use face normals instead of vertex normals but I cannot access that property, maybe it’s a custom vert attribute they added

ThreeCSG/threeCSG.es6 at master · chandlerprall/ThreeCSG · GitHub


Woooow - this is huge!

Here’s a small remix, adding mouseX/Y interaction, building the shape in the draw and disabling that if .geometryInHash(gId) statement, so it can constantly update = works fine for me. Probably not efficient to keep rendering/processing values – but maybe not sooo heavy? Normals/shading are working perfect on my end! Got greedy and tested a uv/texture… haha, not so fast… but this is a huge step for wrapping CSG to p5!

1 Like

Getting ever so slightly closer…! Seems like dumb luck that plugging the normal’s x/y values into the p5.geometry UV’s draws the texture within the form… nevertheless… almost there !

Curious if to do it right and have the texture also around the outside of this object requires the custom vertex class in csg as previously mentioned… ooor… wondered if it’s possible to use a modulate within the parsing of vertices to alternative the [0,0] » [0,1]… etc etc… I know far too little about WEBGL, obj, uv’s etc…

Curious why you had previously disabled the ‘ib’ and ‘ic’ normals? when reactivated, one gets the very smooth materialNormal() shading rather than more polygon style – both interesting, but smooth seems more expected (just tested disabling again with texture applied… and yeah, needs both active to not be pixelated).

1 Like

nice! I think part of the problem with UV is that there is no “standard” way to map texture. For example, for a cube, you can map the same texture to every side (0-1) or you can do something like this:

But in a way, if you don’t need to accurately map, you can use any smooth values like normals or xy/xz coordinates, for example.

The reason why I didn’t use normals of ib / ic was because simply I forgot to comment them back in :slight_smile: at first something was wrong with normals (because of how I set up the dictionary) but later I fixed it, and during debugging they were commented out.

1 Like

This thread links to a potential answer, the function to recomputeUVs() based on the existing normals…

Aha - that’s interesting! Just swapped using normal for vertex on the UVs = semi glitchy, but full image wrapped around obj!

this looks like simply mapping xy / yz / zx to uv depending on the normal’s direction. I tried something similar (but weird where normal changes)

see also Mapping Types — Blender Manual

1 Like

Aha, nice and some pretty weird/wild glitches where some of those joints/normals meet!

Haven’t tried it yet – but I think once we figure out how to transform loadModel() shapes/objects into csg object (fromPolygons()) – (here’s an example for three.js) – then it’s the start of a really useful library (or atleast gist for including). It’s not very p5-like in the syntax, setting the position, size, etc of a shape before modifying it – but that doesn’t matter… being csg.js-like is more important for those familiar or learning CSG – and the i/o to p5 being pretty painless is important.