diff options
author | sanine <sanine.not@pm.me> | 2023-04-01 00:15:05 -0500 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-04-01 00:15:05 -0500 |
commit | 54c34ca3051743fd3f1c02f73a321299af456b8a (patch) | |
tree | 01241e3cb1cdcf8b06245914eb9b6a54ffc52831 /src/Terrain.js | |
parent | 18ed948462bd71e4cb3b1e8fa3f55df84ef0ff33 (diff) |
attempt implementing convex hull algorithmtectonics
Diffstat (limited to 'src/Terrain.js')
-rw-r--r-- | src/Terrain.js | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/Terrain.js b/src/Terrain.js new file mode 100644 index 0000000..a51c0a3 --- /dev/null +++ b/src/Terrain.js @@ -0,0 +1,139 @@ +import { Mat3, Vec3, Point, RandomNormal, Shape, ConvexHull } from './Geometry.js'; + + +export function RandomPoints(n) { + const points = []; + for (let i=0; i<n; i++) { + points.push(RandomNormal()); + } + return points; +} + + +export class Plate { + constructor(points) { + this.color = `hsl(${360*Math.random()}, 100%, 50%)` + this.points = points; + this.hull = ConvexHull(points); + let [avgX, avgY, avgZ] = [0, 0, 0]; + for (let point of points) { + avgX += point.x; + avgY += point.y; + avgZ += point.z; + } + avgX /= points.length; + avgY /= points.length; + avgZ /= points.length; + this.center = new Vec3(avgX, avgY, avgZ).normalize(); + this.extent = 0; + for (let point of points) { + this.extent = Math.max(this.extent, this.center.dot(point)); + } + + this.speed = Math.random(); + this.axis = RandomNormal().cross(this.center).normalize(); + } + + filterColliding(plate) { + const extent = Math.max(this.extent, plate.extent); + return this.center.dot(plate.center) < extent; + } + + checkColliding(plate) { + if (!this.filterColliding(plate)) { + return false; + } + + console.log("check", this, plate); + + const threshold = 0.00001; + let collisionTotal = 0; + for (let pa of this.points) { + for (let pb of plate.points) { + collisionTotal += pa.dot(pb); + } + } + collisionTotal /= this.points.length * plate.points.length; + console.log(this, plate, collisionTotal); + if (collisionTotal > threshold) { + return true; + } + return false; + } + + move() { + const matrix = new Mat3().rotation(this.axis, this.speed * 0.01 * Math.PI); + for (let i=0; i<this.points.length; i++) { + this.points[i] = matrix.mulv(this.points[i]); + } + this.hull.translate(this.axis, this.speed * 0.01 * Math.PI); + this.center = matrix.mulv(this.center); + } + + render(ct, view) { + ct.fillStyle = this.color; + for (let point of this.points) { + point.render(ct, view); + } + this.hull.render(ct, view); + } +} + + +function randomChoice(array) { + const index = Math.floor(array.length * Math.random()); + return array[index]; +} + + +export class PlateManager { + constructor(points, plateCount) { + this.points = points; + this.plates = this.buildPlates(plateCount); + } + + + buildPlates(plateCount) { + const seedPoints = []; + const points = []; + for (let i=0; i<plateCount; i++) { + seedPoints.push(randomChoice(this.points)); + points.push([]); + } + + for (let point of this.points) { + let maxDot = -1; + let index = -1; + for (let i=0; i<plateCount; i++) { + const seed = seedPoints[i]; + const d = seed.dot(point); + if (d > maxDot) { + maxDot = d; + index = i; + } + } + if (index == -1) { + console.error("no closest point", point); + } + points[index].push(point); + } + + const plates = []; + for (let p of points) { + plates.push(new Plate(p)); + } + return plates; + } + + update() { + for (let plate of this.plates) { + plate.move(); + } + } + + render(ct, view) { + for (let plate of this.plates) { + plate.render(ct, view); + } + } +} |