summaryrefslogtreecommitdiff
path: root/src/Terrain.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/Terrain.js')
-rw-r--r--src/Terrain.js139
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);
+ }
+ }
+}