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

**URL:** <https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613>\
**Category:** Coding Questions\
**Created:** [April 24, 2021, 8:18pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613 "2021-04-24T20:18:45Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 24, 2021, 8:18pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/1 "2021-04-24T20:18:45Z")

</div>

A few years ago a feature request on p5.js’ github asked about [boolean 3d modeling](https://github.com/processing/p5.js/issues/2130) – which was determined to be best added as a library. Researching the topic now with a student and that thread informed us about [CSG](https://en.wikipedia.org/wiki/Constructive_solid_geometry), specifically the [csg.js](https://evanw.github.io/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](https://editor.p5js.org/ffd8/sketches/ltqoUz4b6) – 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](https://github.com/chandlerprall/ThreeCSG), [THREE-CSGMesh](https://github.com/manthrax/THREE-CSGMesh), [threejs-csg](https://github.com/looeee/threejs-csg), [three-2-csg](https://github.com/knee-cola/three-2-csg), [more…](https://github.com/search?q=csg+threejs)  
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.

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [April 24, 2021, 8:45pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/2 "2021-04-24T20:45:19Z")

</div>

hello again 🙂 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](https://processing.org/reference/normal_.html)). There is an ongoing discussion here:

> <https://github.com/processing/p5.js/issues/5022>
>
> Currently 3d shapes drawn using beginShape/vertex/endShape have all vertexes ass…igned a normal of \`(0, 0, 1)\`. When drawing custom geometry with these functions it should be possible to specify the normal vector for each vertex.
> 
> \### How would this new feature help \[increase access\]
> 
> Individuals learning the fundamentals of 3d computer graphics for the first time would benefit from being able to use vertex normals when drawing custom geometry using beginShape/vertex/endShape. I think this is more accessible to users who are new to 3d graphics then jumping straight to loading 3d model files, or creating custom p5.Geometry objects. It also presents an opportunity to introduce vector math concepts such as cross product, addition, and normalization.
> 
> \#### Most appropriate sub-area of p5.js?
> 
> \- \[\] Accessibility (Web Accessibility)
> \- \[\] Build tools and processes
> \- \[\] Color
> \- \[\] Core/Environment/Rendering
> \- \[\] Data
> \- \[\] DOM
> \- \[\] Events
> \- \[\] Friendly error system
> \- \[\] Image
> \- \[\] IO (Input/Output)
> \- \[\] Localization
> \- \[\] Math
> \- \[\] Unit Testing
> \- \[\] Typography
> \- \[\] Utilities
> \- \[x\] WebGL
> \- \[\] Other (specify if possible)
> 
> \#### New feature details:
> 
> I propose adding a function \`vertexNormal\` that sets the normal vector to be used in subsequent calls to \`vertex\`. This vector would default to \`(0, 0, 1)\` thereby preserving the current behavior by default. This value would be stored/restored as part of push/pop operations. As far as I know this would only be relevant for drawing using the WebGL renderer, and would have no effect when using other renderers.

Meanwhile I made a simple visualization of normals:

> **[p5.js Web Editor](https://editor.p5js.org/micuat/sketches/yaor-qFjd)**
>
> A web editor for p5.js, a JavaScript library with the goal of making coding accessible to artists, designers, educators, and beginners.

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](https://github.com/evanw/csg.js/blob/master/csg.js#L359)

---

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 24, 2021, 9:11pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/3 "2021-04-24T21:11:39Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [April 25, 2021, 10:26am UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/4 "2021-04-25T10:26:47Z")

</div>

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)

[https://editor.p5js.org/micuat/sketches/KDY2VMqN4](https://editor.p5js.org/micuat/sketches/KDY2VMqN4)

~~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](https://github.com/chandlerprall/ThreeCSG/blob/master/threeCSG.es6#L154)

---

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 25, 2021, 11:09am UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/5 "2021-04-25T11:09:58Z")

</div>

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!

[https://editor.p5js.org/ffd8/sketches/LKKTsV5Vz](https://editor.p5js.org/ffd8/sketches/LKKTsV5Vz)

---

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 26, 2021, 1:14pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/6 "2021-04-26T13:14:08Z")

</div>

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 !

[https://editor.p5js.org/ffd8/sketches/0wne6UHig](https://editor.p5js.org/ffd8/sketches/0wne6UHig)

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).

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [April 26, 2021, 2:31pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/7 "2021-04-26T14:31:43Z")

</div>

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:  
[![](https://www.panda3d.org/manual/images/4/4e/Exploded_cube_map.png) ](https://www.panda3d.org/manual/images/4/4e/Exploded_cube_map.png)

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 🙂 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.

---

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 26, 2021, 3:34pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/8 "2021-04-26T15:34:05Z")

</div>

[This thread](https://discourse.threejs.org/t/material-with-texture-for-csg-object/10820) links to a potential answer, the function to [recomputeUVs()](http://jsfiddle.net/Lnuqmthr/) based on the existing normals…

---

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 26, 2021, 3:45pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/9 "2021-04-26T15:45:22Z")

</div>

> [@micuat](#):
>
> 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.

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

[https://editor.p5js.org/ffd8/sketches/y4sArq2Kq](https://editor.p5js.org/ffd8/sketches/y4sArq2Kq)

---

<div class="post-metadata">

**Author:** ![micuat](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/micuat/32/19407_2.png) [@micuat](https://discourse.processing.org/u/micuat)\
**Post date:** [April 26, 2021, 6:47pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/10 "2021-04-26T18:47:27Z")

</div>

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)  
[https://editor.p5js.org/micuat/sketches/l--evHjMe](https://editor.p5js.org/micuat/sketches/l--evHjMe)

see also [Mapping Types — Blender Manual](https://docs.blender.org/manual/en/2.79/editors/uv_image/uv/editing/unwrapping/mapping_types.html#unwrap)

---

<div class="post-metadata">

**Author:** ![ffd8](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/ffd8/32/815_2.png) [@ffd8](https://discourse.processing.org/u/ffd8)\
**Post date:** [April 26, 2021, 8:04pm UTC](https://discourse.processing.org/t/boolean-csg-union-intersect-etc-3d-shapes-into-p5js-model/29613/11 "2021-04-26T20:04:46Z")

</div>

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](https://gist.github.com/knee-cola/0a53b4e860b3c00ed6c9027c2206452c)) – 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.
