Perspective view with horizon
This commit is contained in:
1 parent
aa349624e3
commit
09f1e9a1cb
1 file changed
+66
-42
+66
-42
@@ -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);
|
||||||
|
|||||||
Reference in new issue
Block a user