RoundedCornerLine
by Paul West
HTML
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
function roundedCornerLine(points, radius, smoothness, closed) {
radius = radius !== undefined ? radius : .1;
smoothness = smoothness !== undefined ? Math.floor(smoothness) : 3;
closed = closed !== undefined ? closed : false;
let newGeometry = new THREE.BufferGeometry();
if (points === undefined) {
console.log("RoundedCornerLine: 'points' is undefined");
return newGeometry;
}
if (points.length < 3) {
console.log("RoundedCornerLine: 'points' has insufficient length (should be equal or greater than 3)");
return newGeometry.setFromPoints(points);
}
// minimal segment
let minVector = new THREE.Vector3();
let minLength = minVector.subVectors(points[0], points[1]).length();
for (let i = 1; i < points.length - 1; i++) {
minLength = Math.min(minLength, minVector.subVectors(points[i], points[i + 1]).length());
}
if (closed) {
minLength = Math.min(minLength, minVector.subVectors(points[points.length - 1], points[0]).length());
}
radius = radius > minLength * .5 ? minLength * .5 : radius; // radius can't be greater than a half of a minimal segment
let startIndex = 1;
let endIndex = points.length - 2;
if (closed) {
startIndex = 0;
endIndex = points.length - 1;
}
let positions = [];
if (!closed) {
positions.push(points[0].clone())
};
for (let i = startIndex; i <= endIndex; i++) {
let iStart = i - 1 < 0 ? points.length - 1 : i - 1;
let iMid = i;
let iEnd = i + 1 > points.length - 1 ? 0 : i + 1;
let pStart = points[iStart];
let pMid = points[iMid];
let pEnd = points[iEnd];
// key points
let vStartMid = new THREE.Vector3().subVectors(pStart, pMid).normalize();
let vEndMid = new THREE.Vector3().subVectors(pEnd,...
CSS
body {
overflow: hidden;
margin: 0;
}
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 points = [
new THREE.Vector3(0, -2, -10),
new THREE.Vector3(-10, -10, -10),
new THREE.Vector3(-10, 5, -10),
new THREE.Vector3(0, -5, 0),
new THREE.Vector3(10, 5, 10),
new THREE.Vector3(10, -5, 0)
];
var radius = 1;
var smoothness = 12;
var geom = roundedCornerLine(points, radius, smoothness, true);
var line = new THREE.Line(geom, new THREE.LineBasicMaterial({
color: "yellow"
}));
scene.add(line);
var baseLine = new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(baseLine);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}