Threejs - csg

by black strings

HTML

<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/MTLLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/OBJLoader.js"></script>

<div id="floater">
  <button id="hideBtn">
  hide
  </button>
  <div class="child">
    <p>
  The CSG library cuts and maintains original UV. Faces which are generated from new cuts, will use the projected UV from the geometry cut from. In short, geometry brushes will project their UVs onto new faces.
The cutting shape will project it's UV onto the result, which is how the new surfaces will get its UVs.
  </p>
   <p>
  The return result is one bufferGeometry. It does not return an array of meshes, although it may look like so. To separate loose elements, you must further process the result bufferGeometry with other means by relying on the group property which the resulting buffer geometry will carry.
  </p>
  <p>
  The CSG brush encapsulates a buffer geometry structure as it extends the THREE.Mesh
  </p>
  </div>
  

</div>

SCSS

/* fix mouse click offset errors when doing drags */
body {
  margin: 0;
}
#floater {
  position: absolute;
  top: 0;
  left: 0;
  width: 500px;
  border: thin solid red;
  background-color: white;
  padding: 5px;
  margin: 5px;
  font-family: "Times New Roman", serif;
  font-size: 1rem;
  max-height: 120px;
  div.child {
    max-height: 100px;
    overflow: auto;
  }
}
#floater.hide {
  top: -100%;
}

JavaScript

import * as Csg from 'https://esm.run/three-bvh-csg';

var scene, renderer, camera;
var controls;

init();
lightSetup();
animate();

// mini setup initializer to make it like an app
const uiInit = () => {
console.log('initing');
  // by changing the class name it will take care of the animation
  const hideHelper = () => {
  	console.log('hiding helper');
    document.getElementById('floater').className = 'hide';
  };

  const showHelper = () => {
    // by changing the class name it will take care of the animation
    document.getElementById('floater').className = '';
  };

  const init = () => {
    const btn = document.getElementById('hideBtn');
    if(btn) {
    	btn.addEventListener('click', () => {
      	console.log('click');
        hideHelper();
      });
    } else {
    	console.error('btn missing');
    }
  };

  // use session storage as mini database
  /* const hideButtonAfterInit = () => {
    const key = 'firstTime';
    const firstTime = sessionStorage.getItem(key);
    if (firstTime === 'true' || firstTime === null || firstTime === undefined) {
      sessionStorage.setItem(key, 'false');
    } else {
      hideHelper();
      sessionStorage.setItem(key, 'false');
    }
  };
  hideButtonAfterInit(); */
  
  init();
};
uiInit();

function init() {
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  var width = window.innerWidth;
  var height = window.innerHeight;
  renderer.setSize(width, height);
  document.body.appendChild(renderer.domElement);

  scene = new THREE.Scene();
   scene.rotation.x = -Math.PI / 2;
  
  var gridXZ = new THREE.GridHelper(1000, 100);
  scene.add(gridXZ);
  gridXZ.rotation.x = -Math.PI / 2;
 

  var axes = new THREE.AxesHelper(1000);
  scene.add(axes);

  camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
  camera.position.y = 20;
  camera.position.z = 40;
  camera.lookAt(new THREE.Vector3(0, 0, 0));

  controls = new THREE.OrbitControls(camera, renderer.domElement);

	example1();
 ...