diff --git a/assets/index.html b/assets/index.html
index 40bb252..c30194f 100644
--- a/assets/index.html
+++ b/assets/index.html
@@ -62,19 +62,88 @@
}
}
- class Landscape {
- constructor() {
- this.gridSize = 80;
- this.gridRange = 50;
- this.offsetX = 0;
- this.offsetZ = 0;
- this.points = new Map();
- this.waterLevel = -10;
- this.updateOffset();
+ class Triangle {
+ constructor(p1, p2, p3) {
+ this.p1 = p1;
+ this.p2 = p2;
+ this.p3 = p3;
+ this.calculateNormal();
+ this.visible = true;
}
- getKey(x, z) {
- return `${Math.round(x / this.gridSize)},${Math.round(z / this.gridSize)}`;
+ calculateNormal() {
+ const v1 = { x: this.p2.x - this.p1.x, y: this.p2.y - this.p1.y, z: this.p2.z - this.p1.z };
+ const v2 = { x: this.p3.x - this.p1.x, y: this.p3.y - this.p1.y, z: this.p3.z - this.p1.z };
+ this.normal = {
+ x: v1.y * v2.z - v1.z * v2.y,
+ y: v1.z * v2.x - v1.x * v2.z,
+ z: v1.x * v2.y - v1.y * v2.x
+ };
+ const len = Math.sqrt(this.normal.x**2 + this.normal.y**2 + this.normal.z**2);
+ if (len > 0) {
+ this.normal.x /= len;
+ this.normal.y /= len;
+ this.normal.z /= len;
+ }
+ const light = { x: 0.5, y: 0.5, z: 1 };
+ const dot = this.normal.x * light.x + this.normal.y * light.y + this.normal.z * light.z;
+ this.intensity = Math.max(0, dot);
+ }
+
+ isBackfaceCulled() {
+ const v1 = { x: this.p2.x - this.p1.x, y: this.p2.y - this.p1.y, z: this.p2.z - this.p1.z };
+ const v2 = { x: this.p3.x - this.p1.x, y: this.p3.y - this.p1.y, z: this.p3.z - this.p1.z };
+ const crossZ = v1.x * v2.y - v1.y * v2.x;
+ return crossZ >= 0;
+ }
+
+ drawFilled() {
+ const proj1 = this.p1.project();
+ const proj2 = this.p2.project();
+ const proj3 = this.p3.project();
+
+ if (this.isBackfaceCulled()) return;
+
+ const colorVal = Math.floor(30 + this.intensity * 150);
+ const color = `rgba(0, ${colorVal}, 0, 0.8)`;
+
+ ctx.beginPath();
+ ctx.moveTo(proj1.x, proj1.y);
+ ctx.lineTo(proj2.x, proj2.y);
+ ctx.lineTo(proj3.x, proj3.y);
+ ctx.closePath();
+ ctx.fillStyle = color;
+ ctx.fill();
+ }
+
+ drawWireframe() {
+ const proj1 = this.p1.project();
+ const proj2 = this.p2.project();
+ const proj3 = this.p3.project();
+
+ if (this.isBackfaceCulled()) return;
+
+ const color = this.p1.isWater || this.p2.isWater || this.p3.isWater ? '#00ccff' : '#00ff00';
+
+ ctx.strokeStyle = color;
+ ctx.lineWidth = 1;
+ ctx.beginPath();
+ ctx.moveTo(proj1.x, proj1.y);
+ ctx.lineTo(proj2.x, proj2.y);
+ ctx.lineTo(proj3.x, proj3.y);
+ ctx.closePath();
+ ctx.stroke();
+ }
+ }
+
+ class Landscape {
+ constructor() {
+ this.gridSize = 60;
+ this.gridRange = 40;
+ this.offsetX = 0;
+ this.offsetZ = 0;
+ this.triangles = [];
+ this.waterLevel = -10;
}
generateHeight(x, z) {
@@ -92,9 +161,31 @@
return y < this.waterLevel;
}
- updateOffset() {
+ update() {
this.offsetX -= 1;
this.offsetZ -= 1;
+ this.generateTriangles();
+ }
+
+ generateTriangles() {
+ this.triangles = [];
+ const minIdx = -this.gridRange;
+ const maxIdx = this.gridRange;
+
+ for (let x = minIdx; x <= maxIdx; x++) {
+ for (let z = minIdx; z <= maxIdx; z++) {
+ const p1 = this.getPoint(x, z);
+ const p2 = this.getPoint(x + 1, z);
+ const p3 = this.getPoint(x + 1, z + 1);
+ const p4 = this.getPoint(x, z + 1);
+
+ const tri1 = new Triangle(p1, p2, p3);
+ const tri2 = new Triangle(p1, p3, p4);
+
+ this.triangles.push(tri1);
+ this.triangles.push(tri2);
+ }
+ }
}
getPoint(x, z) {
@@ -106,52 +197,9 @@
return point;
}
- update() {
- this.updateOffset();
- }
-
draw() {
- ctx.lineWidth = 1;
- ctx.globalAlpha = 0.6;
-
- const minIdx = -this.gridRange;
- const maxIdx = this.gridRange;
-
- for (let x = minIdx; x <= maxIdx; x++) {
- for (let z = minIdx; z <= maxIdx; z++) {
- const p1 = this.getPoint(x, z);
- const p2 = this.getPoint(x + 1, z);
- const p3 = this.getPoint(x, z + 1);
-
- const proj1 = p1.project();
- const proj2 = p2.project();
- const proj3 = p3.project();
-
- if (p1.isWater || p2.isWater || p3.isWater) {
- ctx.strokeStyle = '#00ccff';
- ctx.globalAlpha = 0.5;
- } else {
- ctx.strokeStyle = '#00ff00';
- ctx.globalAlpha = 0.6;
- }
-
- if (x < maxIdx) {
- ctx.beginPath();
- ctx.moveTo(proj1.x, proj1.y);
- ctx.lineTo(proj2.x, proj2.y);
- ctx.stroke();
- }
-
- if (z < maxIdx) {
- ctx.beginPath();
- ctx.moveTo(proj1.x, proj1.y);
- ctx.lineTo(proj3.x, proj3.y);
- ctx.stroke();
- }
- }
- }
-
- ctx.globalAlpha = 1;
+ this.triangles.forEach(tri => tri.drawFilled());
+ this.triangles.forEach(tri => tri.drawWireframe());
}
}