Threejs - Cookie Cutter

by black strings

HTML

<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.3/dat.gui.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/polybool.min.js"></script>

CSS

body {
  margin: 0px;
  background-color: #050505;
  color: #fff;
  overflow: hidden;
}

#container {
  position: absolute;
  top: 0px;
  left: 0px;
}

JavaScript

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 20);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

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

var gui = new dat.GUI();

var shape = {
  regions: [
    [
      [-10, -10],
      [-10, 10],
      [5, 10],
      [10, 4],
      [10, -11],
      [2, -11],
      [2, -9],
      [-5, -9],
      [-5, -10]
    ]
  ],
  inverted: false
};

var cutter = {
  regions: [],
  inverted: false
};

for (let i = 0; i < 10; i++) {
  let add = -11 + i * 2 * 1.1;
  cutter.regions.push(
    [
      [-11, 0 + add],
      [-11, 2 + add],
      [11, 2 + add],
      [11, 0 + add]
    ]
  );
}

var result = PolyBool.intersect(shape, cutter, name);

showContour(result, 0x404040, "result", true, true);
showContour(cutter, "gray", "cutter", false, false);
showContour(shape, "aqua", "shape", false, false);

function showContour(pbObject, color, name, isMesh, visible) {
	let group = new THREE.Group();
  group.visible = visible;
  pbObject.regions.forEach(r => {
    let v2s = r.map(rp => {
      return new THREE.Vector2(rp[0], rp[1])
    });

    let contourGeom = isMesh ? new THREE.ShapeBufferGeometry(new THREE.Shape(v2s)) : new THREE.BufferGeometry().setFromPoints(v2s);
    let contourMat = isMesh ? new THREE.MeshBasicMaterial({ color: color, side: THREE.DoubleSide}) : new THREE.LineBasicMaterial({
      color: color
    });
    let contour = isMesh ? new THREE.Mesh(contourGeom, contourMat) : new THREE.LineLoop(contourGeom, contourMat);
    group.add(contour);
  });
  
  scene.add(group);
  gui.add(group, "visible").name(name);

}


render();

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}