three.js - triangulate planet
by mmalex
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.js"></script>
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://mbnsay.com/rayys/assets/js/Delaunator.js"></script>
<button id="btn" onclick="start()">Generate</button>
<div id="progress">Click to start mesh generation process, it will take a while.</div>
CSS
#progress {
position: fixed;
padding-left: 100px;
top: 0;
left: 0;
right: 0;
z-index: 9;
height: 32px;
line-height: 32px;
font-size: 11px;
font-family: monospace;
background-color: rgba(0, 0, 0, 0.75);
color: white;
}
#btn {
z-index: 10;
position: fixed;
top: 5px;
left: 5px;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
JavaScript
/* Draw GeoJSON
Iterates through the latitude and longitude values, converts the values to XYZ coordinates, and draws the geoJSON geometries.
*/
let TRIANGULATION_DENSITY = 5;
let WIREFRAME = false;
function verts2array(coords) {
let flat = [];
for (let k = 0; k < coords.length; k++) {
flat.push(coords[k][0], coords[k][1]);
}
return flat;
}
function array2verts(arr) {
let coords = [];
for (let k = 0; k < arr.length; k += 2) {
coords.push([arr[k], arr[k + 1]]);
}
return coords;
}
function findBBox(points) {
let min = {
x: 1e99,
y: 1e99
};
let max = {
x: -1e99,
y: -1e99
};
for (var point_num = 0; point_num < points.length; point_num++) {
if (points[point_num][0] < min.x) {
min.x = points[point_num][0];
}
if (points[point_num][0] > max.x) {
max.x = points[point_num][0];
}
if (points[point_num][1] < min.y) {
min.y = points[point_num][1];
}
if (points[point_num][1] > max.y) {
max.y = points[point_num][1];
}
}
return {
min: min,
max: max
};
}
function isInside(point, vs) {
// ray-casting algorithm based on
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
var x = point[0],
y = point[1];
var inside = false;
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
var xi = vs[i][0],
yi = vs[i][1];
var xj = vs[j][0],
yj = vs[j][1];
var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
function genInnerVerts(points) {
let res = [];
for (let k = 0; k < points.length; k++) {
res.push(points[k]);
}
let bbox = findBBox(points);
let step = TRIANGULATION_DENSITY;
let k = 0;
for (let x = bbox.min.x + step / 2; x < bbox.max.x; x += step) {
for (let y = bbox.min.y + step / 2; y < bbox.max.y; y += step) {
let newp = [x, y];
if (isInside(newp, points)) {
...