Perspective view with horizon

This commit is contained in:
Richard Zink committed 2026-10-06 16:43:03 +02:00
1 parent aa349624e3
commit 09f1e9a1cb
1 file changed
+66 -42
+66 -42
View File
@@ -24,25 +24,24 @@
window.addEventListener('resize', resize); window.addEventListener('resize', resize);
resize(); resize();
var offX = 0, offY = 0; var offX = 0, offZ = 0;
function project(x, y, z) { function project(x, y, z) {
var scale = 600 / (600 + z); var fov = 800;
var sx = (x - y) * scale + W / 2; var scale = fov / (fov + z);
var sy = ((x + y) * 0.5 - z) * scale + H / 2; var isoX = (x - y) * 0.5;
var isoY = ((x + y) * 0.5) - z;
var sx = isoX * scale + W / 2;
var sy = isoY * scale + H / 2;
return [sx, sy]; return [sx, sy];
} }
function generateTriangle(p1, p2, p3, water) { function getHeight(x, z) {
return { p1: p1, p2: p2, p3: p3, water: water, depth: (p1[2] + p2[2] + p3[2]) / 3 };
}
function getHeight(x, y) {
var h = 0; var h = 0;
h += Math.sin(x / 300) * 50; h += Math.sin(x / 200) * 60;
h += Math.cos(y / 300) * 50; h += Math.cos(z / 200) * 60;
h += Math.sin(x / 150 + y / 300) * 25; h += Math.sin(x / 100 + z / 200) * 30;
h += Math.cos(y / 150 - x / 300) * 20; h += Math.cos(z / 100 - x / 200) * 25;
return h; return h;
} }
@@ -53,20 +52,20 @@
var range = 25; var range = 25;
var size = 100; var size = 100;
for (var x = -range; x <= range; x++) { for (var x = -range; x <= range; x++) {
for (var y = -range; y <= range; y++) { for (var z = -range; z <= range; z++) {
var wx = x * size + offX; var wx = x * size + offX;
var wy = y * size + offY; var wz = z * size + offZ;
var h1 = getHeight(wx, wy); var h1 = getHeight(wx, wz);
var h2 = getHeight(wx + size, wy); var h2 = getHeight(wx + size, wz);
var h3 = getHeight(wx + size, wy + size); var h3 = getHeight(wx + size, wz + size);
var h4 = getHeight(wx, wy + size); var h4 = getHeight(wx, wz + size);
var water = (h1 < 30 || h2 < 30 || h3 < 30 || h4 < 30); var water = (h1 < 30 || h2 < 30 || h3 < 30 || h4 < 30);
var p1 = [wx, h1, wy]; var p1 = [wx, h1, wz];
var p2 = [wx + size, h2, wy]; var p2 = [wx + size, h2, wz];
var p3 = [wx + size, h3, wy + size]; var p3 = [wx + size, h3, wz + size];
var p4 = [wx, h4, wy + size]; var p4 = [wx, h4, wz + size];
triangles.push(generateTriangle(p1, p2, p3, water)); triangles.push({ p1: p1, p2: p2, p3: p3, water: water, depth: (p1[2] + p2[2] + p3[2]) / 3 });
triangles.push(generateTriangle(p1, p3, p4, water)); triangles.push({ p1: p1, p2: p3, p3: p4, water: water, depth: (p1[2] + p3[2] + p4[2]) / 3 });
} }
} }
} }
@@ -75,9 +74,11 @@
triangles.sort(function(a, b) { return b.depth - a.depth; }); triangles.sort(function(a, b) { return b.depth - a.depth; });
for (var i = 0; i < triangles.length; i++) { for (var i = 0; i < triangles.length; i++) {
var t = triangles[i]; var t = triangles[i];
var p1 = project(t.p1[0], t.p1[2], t.p1[1]); var p1 = project(t.p1[0], t.p1[1], t.p1[2]);
var p2 = project(t.p2[0], t.p2[2], t.p2[1]); var p2 = project(t.p2[0], t.p2[1], t.p2[2]);
var p3 = project(t.p3[0], t.p3[2], t.p3[1]); var p3 = project(t.p3[0], t.p3[1], t.p3[2]);
if (p1[1] < -200 || p1[1] > H + 200) continue;
ctx.fillStyle = t.water ? 'rgba(0, 80, 200, 0.85)' : 'rgba(0, 160, 0, 0.85)'; ctx.fillStyle = t.water ? 'rgba(0, 80, 200, 0.85)' : 'rgba(0, 160, 0, 0.85)';
ctx.beginPath(); ctx.beginPath();
@@ -93,6 +94,16 @@
} }
} }
function drawHorizon() {
var hY = H / 2 - 50;
ctx.strokeStyle = 'rgba(255, 200, 100, 0.3)';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(0, hY);
ctx.lineTo(W, hY);
ctx.stroke();
}
var planeVertices = []; var planeVertices = [];
function initPlane() { function initPlane() {
planeVertices = []; planeVertices = [];
@@ -111,12 +122,10 @@
planeVertices.push([40, 30, 0]); planeVertices.push([40, 30, 0]);
} }
var yawT = 0, rollT = 0, pitchT = 0;
function drawPlane() { function drawPlane() {
var yaw = -0.4; var yaw = -0.4;
var roll = 0; var roll = 0;
var pitch = 0.2; var pitch = 0.15;
var transformed = planeVertices.map(function(v) { var transformed = planeVertices.map(function(v) {
var x = v[0], y = v[1], z = v[2]; var x = v[0], y = v[1], z = v[2];
@@ -138,27 +147,42 @@
ctx.shadowColor = '#ff0000'; ctx.shadowColor = '#ff0000';
for (var i = 0; i < transformed.length; i++) { for (var i = 0; i < transformed.length; i++) {
var p = project(transformed[i][0], transformed[i][2], transformed[i][1]); var p = project(transformed[i][0], transformed[i][1], transformed[i][2]);
ctx.fillStyle = '#ff0000'; ctx.fillStyle = '#ff0000';
ctx.beginPath(); ctx.beginPath();
ctx.arc(p[0], p[1], 3, 0, Math.PI * 2); ctx.arc(p[0], p[1], 3, 0, Math.PI * 2);
ctx.fill(); ctx.fill();
} }
for (var i = 0; i < transformed.length - 1; i++) { for (var i = 0; i < 7; i++) {
if (i >= 7 && i <= 10) continue; var p1 = project(transformed[i][0], transformed[i][1], transformed[i][2]);
var p1 = project(transformed[i][0], transformed[i][2], transformed[i][1]); var p2 = project(transformed[i + 1][0], transformed[i + 1][1], transformed[i + 1][2]);
var p2 = project(transformed[i + 1][0], transformed[i + 1][2], transformed[i + 1][1]); ctx.beginPath();
ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]);
ctx.stroke();
}
ctx.beginPath();
var pFirst = project(transformed[0][0], transformed[0][1], transformed[0][2]);
var pLast = project(transformed[7][0], transformed[7][1], transformed[7][2]);
ctx.moveTo(pFirst[0], pFirst[1]);
ctx.lineTo(pLast[0], pLast[1]);
ctx.stroke();
for (var i = 8; i <= 11; i++) {
var j = (i + 1 > 11) ? 8 : i + 1;
var p1 = project(transformed[i][0], transformed[i][1], transformed[i][2]);
var p2 = project(transformed[j][0], transformed[j][1], transformed[j][2]);
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(p1[0], p1[1]); ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]); ctx.lineTo(p2[0], p2[1]);
ctx.stroke(); ctx.stroke();
} }
for (var i = 7; i <= 10; i++) { for (var i = 12; i <= 15; i++) {
var j = (i + 1 > 10) ? 7 : i + 1; var j = (i + 1 > 15) ? 12 : i + 1;
var p1 = project(transformed[i][0], transformed[i][2], transformed[i][1]); var p1 = project(transformed[i][0], transformed[i][1], transformed[i][2]);
var p2 = project(transformed[j][0], transformed[j][2], transformed[j][1]); var p2 = project(transformed[j][0], transformed[j][1], transformed[j][2]);
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(p1[0], p1[1]); ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]); ctx.lineTo(p2[0], p2[1]);
@@ -175,10 +199,10 @@
ctx.fillRect(0, 0, W, H); ctx.fillRect(0, 0, W, H);
offX -= 1.5; offX -= 1.5;
offY -= 0.7; offZ -= 0.7;
generateLandscape(); generateLandscape();
drawLandscape(); drawLandscape();
drawHorizon();
drawPlane(); drawPlane();
requestAnimationFrame(frame); requestAnimationFrame(frame);