Threejs cubic bezier curve 3.1

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/geometries/ConvexGeometry.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/math/ConvexHull.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>

CSS

/* fix mouse click offset errors when doing drags */
body {
  margin: 0;
}

JavaScript

var scene, renderer, camera;
var cube;
var controls;
var curves = [];

var plane = new THREE.Plane();
plane.setFromCoplanarPoints(new THREE.Vector3(), new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 0, 1));
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects;
var dragging = false;
var dragObject;
var pointOfIntersection = new THREE.Vector3();
var planeNormal = new THREE.Vector3(0, 0, 1);
var shift = new THREE.Vector3();

function fitCurve(points, maxError, progressCallback) {
  if (!Array.isArray(points)) {
    throw new TypeError("First argument should be an array");
  }
  points.forEach((point) => {
    if (!Array.isArray(point) || point.some(item => typeof item !== 'number') ||
      point.length !== points[0].length) {
      throw Error("Each point should be an array of numbers. Each point should have the same amount of numbers.");
    }
  });

  // Remove duplicate points
  points = points.filter((point, i) =>
    i === 0 || !point.every((val, j) => val === points[i - 1][j])
  );

  if (points.length < 2) {
    return [];
  }

  const len = points.length;
  const leftTangent = createTangent(points[1], points[0]);
  const rightTangent = createTangent(points[len - 2], points[len - 1]);

  return fitCubic(points, leftTangent, rightTangent, maxError, progressCallback);
}

/**
 * Fit a Bezier curve to a (sub)set of digitized points.
 * Your code should not call this function directly. Use {@link fitCurve} instead.
 *
 * @param {Array<Array<Number>>} points - Array of digitized points, e.g. [[5,5],[5,50],[110,140],[210,160],[320,110]]
 * @param {Array<Number>} leftTangent - Unit tangent vector at start point
 * @param {Array<Number>} rightTangent - Unit tangent vector at end point
 * @param {Number} error - Tolerance, squared error between points and fitted curve
 * @returns {Array<Array<Array<Number>>>} Array of Bezier curves, where each element is [first-point, control-point-1, control-point-2, second-point] and points are [x,...