terrain-generator

digital terrain generation and animation
git clone https://tongong.net/git/terrain-generator.git
Log | Files | Refs | README

commit fbb2f8fab250ca522ff9fe1a98c6710d97ba7c85
parent bcc0e6e6693e8620763d9b7675f053a1d5530068
Author: tongong <tongong@gmx.net>
Date:   Mon, 12 Aug 2019 10:57:24 +0200

formatting code

Diffstat:
Mscripts/main.js | 89++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mscripts/render.js | 296++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mscripts/rotation.js | 48++++++++++++++++++++++++------------------------
Mscripts/terrain.js | 209+++++++++++++++++++++++++++++++++++++++++--------------------------------------
4 files changed, 325 insertions(+), 317 deletions(-)

diff --git a/scripts/main.js b/scripts/main.js @@ -16,19 +16,19 @@ var currentField; var endField; var startMillis; -const time = () => (typeof(startMillis)=="undefined")?0:millis()-startMillis; +const time = () => (typeof(startMillis) == "undefined") ? 0 : millis() - startMillis; function setup() { CENTER = createVector(WIDTH / 2, HEIGHT / 2); CENTER_HORIZON = createVector(0, 0); LEFT_HORIZON = createVector(-500, 0); - SIZE = ((HEIGHT>WIDTH)?WIDTH:HEIGHT)/2-50; - + SIZE = ((HEIGHT > WIDTH) ? WIDTH : HEIGHT) / 2 - 50; + createCanvas(WIDTH, HEIGHT); stroke(255); strokeJoin(ROUND); fill(0); - + endField = new Terrain(2, true); currentField = new Terrain(2, false); @@ -37,45 +37,45 @@ function setup() { function draw() { background(0); - + switch (state) { - case 0: - statePercentage = time()/20; - line(CENTER.x,HEIGHT,CENTER.x,CENTER.y*(2-statePercentage/100)); - if (statePercentage >= 100) { - state = 1; - statePercentage = 0; - } - break; - case 1: - statePercentage = time()/10-200; - currentField.render(statePercentage/100*SIZE, SIZE, getRotation()); - if (statePercentage >= 100) { - state = 2; - statePercentage = 0; - } - break; - case 2: - statePercentage = time()/10-300; - currentField.transform(endField,0.1); - currentField.render(SIZE, SIZE, getRotation()); - if (statePercentage >= 100) { - state = 3; - statePercentage = 0; - currentField = currentField.scaleUp(); - endField = currentField.addRandom(RANDOM_FACTOR); - } - break; - case 3: - statePercentage = time()/10-100*(4+stateNumber); - currentField.transform(endField,0.1); - currentField.render(SIZE/pow(2,stateNumber+1), SIZE, getRotation()); - if (statePercentage >= 100 && stateNumber < MAX_STATE-2) { - statePercentage = 0; - stateNumber++; - currentField = currentField.scaleUp(); - endField = currentField.addRandom(pow(RANDOM_FACTOR,stateNumber+1)); - } - break; + case 0: + statePercentage = time() / 20; + line(CENTER.x, HEIGHT, CENTER.x, CENTER.y * (2 - statePercentage / 100)); + if (statePercentage >= 100) { + state = 1; + statePercentage = 0; + } + break; + case 1: + statePercentage = time() / 10 - 200; + currentField.render(statePercentage / 100 * SIZE, SIZE, getRotation()); + if (statePercentage >= 100) { + state = 2; + statePercentage = 0; + } + break; + case 2: + statePercentage = time() / 10 - 300; + currentField.transform(endField, 0.1); + currentField.render(SIZE, SIZE, getRotation()); + if (statePercentage >= 100) { + state = 3; + statePercentage = 0; + currentField = currentField.scaleUp(); + endField = currentField.addRandom(RANDOM_FACTOR); + } + break; + case 3: + statePercentage = time() / 10 - 100 * (4 + stateNumber); + currentField.transform(endField, 0.1); + currentField.render(SIZE / pow(2, stateNumber + 1), SIZE, getRotation()); + if (statePercentage >= 100 && stateNumber < MAX_STATE - 2) { + statePercentage = 0; + stateNumber++; + currentField = currentField.scaleUp(); + endField = currentField.addRandom(pow(RANDOM_FACTOR, stateNumber + 1)); + } + break; } -} +} +\ No newline at end of file diff --git a/scripts/render.js b/scripts/render.js @@ -1,165 +1,165 @@ function render(points, polygons, modes, rotation) { - //Modes: 0: polygon, 1-4: wall - rotation *= TWO_PI; - - // extract points - polygons.forEach(function(polygon, index) { - polygons.push([]); - polygon.forEach(corner => { - polygons[polygons.length - 1].push(Object.assign({}, points[corner])); - }); - }); - polygons = polygons.slice(polygons.length / 2); - - // sort the polygons - let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000); - - polygons.forEach((polygon,index) => { - let sum = createVector(0, 0); - polygon.forEach(corner => { - sum.x += corner.x; - sum.y += corner.y; - sum.z += corner.z; - }); - sum.x /= polygon.length; - sum.y /= polygon.length; - sum.z /= polygon.length; - polygon.average = Object.assign({}, sum); - polygon.depth = depth(polygon.average, rot); - polygon.size = abs(createVector(polygon[0].x,polygon[0].y).dist(createVector(polygon[polygon.length-1].x,polygon[polygon.length-1].y))); - polygon.mode = modes[index]; - if (polygon.depth>0) { - polygon.depth *= polygon.size; - } else { - polygon.depth *= polygon.size; - } - }); - - polygons.sort(function(a, b) { - /*if (abs(a.depth - b.depth) <= 5) { - return abs(b.average.z) - abs(a.average.z); - }*/ - return a.depth - b.depth; - /*let start1 = a.average; - let start2 = b[0]; - let end1 = createVector(a.average.x+rot.x,a.average.y+rot.y); - let end2 = b[1]; - - // Two lines f(x) = m * x + n - let m1 = (end1.y - start1.y) / ((rot.x==0)?99999:end1.x - start1.x); - let m2 = (end2.y - start2.y) / ((end2.x == start2.x)?99999:end2.x - start2.x); - let n1 = end1.y - end1.x * m1; - let n2 = end2.y - end2.x * m2; + //Modes: 0: polygon, 1-4: wall + rotation *= TWO_PI; + + // extract points + polygons.forEach(function(polygon, index) { + polygons.push([]); + polygon.forEach(corner => { + polygons[polygons.length - 1].push(Object.assign({}, points[corner])); + }); + }); + polygons = polygons.slice(polygons.length / 2); + + // sort the polygons + let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000); + + polygons.forEach((polygon, index) => { + let sum = createVector(0, 0); + polygon.forEach(corner => { + sum.x += corner.x; + sum.y += corner.y; + sum.z += corner.z; + }); + sum.x /= polygon.length; + sum.y /= polygon.length; + sum.z /= polygon.length; + polygon.average = Object.assign({}, sum); + polygon.depth = depth(polygon.average, rot); + polygon.size = abs(createVector(polygon[0].x, polygon[0].y).dist(createVector(polygon[polygon.length - 1].x, polygon[polygon.length - 1].y))); + polygon.mode = modes[index]; + if (polygon.depth > 0) { + polygon.depth *= polygon.size; + } else { + polygon.depth *= polygon.size; + } + }); + + polygons.sort(function(a, b) { + /*if (abs(a.depth - b.depth) <= 5) { + return abs(b.average.z) - abs(a.average.z); + }*/ + return a.depth - b.depth; + /*let start1 = a.average; + let start2 = b[0]; + let end1 = createVector(a.average.x+rot.x,a.average.y+rot.y); + let end2 = b[1]; - let crossX = (n2 - n1) / (m1 - m2); - let crossY = crossX * m1 + n1; + // Two lines f(x) = m * x + n + let m1 = (end1.y - start1.y) / ((rot.x==0)?99999:end1.x - start1.x); + let m2 = (end2.y - start2.y) / ((end2.x == start2.x)?99999:end2.x - start2.x); + let n1 = end1.y - end1.x * m1; + let n2 = end2.y - end2.x * m2; - if (mouseIsPressed) { - console.log(crossX,crossY); - } - return a.depth + crossX * rot.y + crossY * rot.x;*/ + let crossX = (n2 - n1) / (m1 - m2); + let crossY = crossX * m1 + n1; - }); - - // draw to the screen - polygons.forEach(polygon => { - if (polygon.mode!==0) { - drawWall(polygon.mode, polygon, rotation); - } else { - drawPolygon(polygon, rotation); - } - }); + if (mouseIsPressed) { + console.log(crossX,crossY); + } + return a.depth + crossX * rot.y + crossY * rot.x;*/ + + }); + + // draw to the screen + polygons.forEach(polygon => { + if (polygon.mode !== 0) { + drawWall(polygon.mode, polygon, rotation); + } else { + drawPolygon(polygon, rotation); + } + }); } function depth(point, rotation) { - return - point.x * rotation.y - point.y * rotation.x; + return -point.x * rotation.y - point.y * rotation.x; } function drawPolygon(points, rotation) { - points.forEach(function(item) { - let newVec = calc3D(item.x, item.y, item.z-ANGLE, rotation); - item.x = newVec.x; - item.y = newVec.y; - }); - beginShape(); - points.forEach(function(item) { - vertex(CENTER.x + item.x, CENTER.y - item.y - ANGLE+SIZE/2); - }); - vertex(CENTER.x + points[0].x, CENTER.y - points[0].y - ANGLE+SIZE/2); - endShape(); + points.forEach(function(item) { + let newVec = calc3D(item.x, item.y, item.z - ANGLE, rotation); + item.x = newVec.x; + item.y = newVec.y; + }); + beginShape(); + points.forEach(function(item) { + vertex(CENTER.x + item.x, CENTER.y - item.y - ANGLE + SIZE / 2); + }); + vertex(CENTER.x + points[0].x, CENTER.y - points[0].y - ANGLE + SIZE / 2); + endShape(); } function drawWall(side, points, rotation) { - points.forEach(function(item) { - let newVec = calc3D(item.x, item.y, item.z-ANGLE, rotation); - item.x = newVec.x; - item.y = newVec.y; - }); - beginShape(); - switch(side) { - case 1: - vertex(CENTER.x + points[0].x, 0); - break; - case 2: - vertex(WIDTH, CENTER.y - points[0].y - ANGLE+SIZE/2); - break; - case 3: - vertex(CENTER.x + points[0].x, HEIGHT); - break; - case 4: - vertex(0, CENTER.y - points[0].y - ANGLE+SIZE/2); - break; - } - points.forEach(function(item) { - vertex(CENTER.x + item.x, CENTER.y - item.y - ANGLE+SIZE/2); - }); -switch(side) { - case 1: - vertex(CENTER.x + points[points.length-1].x, 0); - break; - case 2: - vertex(WIDTH, CENTER.y - points[points.length-1].y - ANGLE+SIZE/2); - break; - case 3: - vertex(CENTER.x + points[points.length-1].x, HEIGHT); - break; - case 4: - vertex(0, CENTER.y - points[points.length-1].y - ANGLE+SIZE/2); - break; - } - endShape(); + points.forEach(function(item) { + let newVec = calc3D(item.x, item.y, item.z - ANGLE, rotation); + item.x = newVec.x; + item.y = newVec.y; + }); + beginShape(); + switch (side) { + case 1: + vertex(CENTER.x + points[0].x, 0); + break; + case 2: + vertex(WIDTH, CENTER.y - points[0].y - ANGLE + SIZE / 2); + break; + case 3: + vertex(CENTER.x + points[0].x, HEIGHT); + break; + case 4: + vertex(0, CENTER.y - points[0].y - ANGLE + SIZE / 2); + break; + } + points.forEach(function(item) { + vertex(CENTER.x + item.x, CENTER.y - item.y - ANGLE + SIZE / 2); + }); + switch (side) { + case 1: + vertex(CENTER.x + points[points.length - 1].x, 0); + break; + case 2: + vertex(WIDTH, CENTER.y - points[points.length - 1].y - ANGLE + SIZE / 2); + break; + case 3: + vertex(CENTER.x + points[points.length - 1].x, HEIGHT); + break; + case 4: + vertex(0, CENTER.y - points[points.length - 1].y - ANGLE + SIZE / 2); + break; + } + endShape(); } function calc3D(x, y, z, rotation) { - - let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000); - let out3D = createVector(x * rot.x - y * rot.y, x * rot.y + y * rot.x, z); - - let zIsZero = false; - let xIsZero = false; - if (out3D.z === 0) { - out3D.z = 1; - zIsZero = true; - } - if (out3D.x === 0) { - out3D.x = 1; - xIsZero = true; - } - let start1 = CENTER_HORIZON; - let start2 = LEFT_HORIZON; - let end1 = createVector(out3D.x, out3D.z); - let end2 = createVector(out3D.x + out3D.y, out3D.z); - - // Two lines f(x) = m * x + n - let m1 = (end1.y - start1.y) / (end1.x - start1.x); - let m2 = (end2.y - start2.y) / (end2.x - start2.x); - let n1 = end1.y - end1.x * m1; - let n2 = end2.y - end2.x * m2; - - let crossX = (n2 - n1) / (m1 - m2); - let crossY = zIsZero ? 0 : crossX * m1 + n1; - if (xIsZero) { - crossX = 0; - } - return createVector(crossX, crossY); + + let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000); + let out3D = createVector(x * rot.x - y * rot.y, x * rot.y + y * rot.x, z); + + let zIsZero = false; + let xIsZero = false; + if (out3D.z === 0) { + out3D.z = 1; + zIsZero = true; + } + if (out3D.x === 0) { + out3D.x = 1; + xIsZero = true; + } + let start1 = CENTER_HORIZON; + let start2 = LEFT_HORIZON; + let end1 = createVector(out3D.x, out3D.z); + let end2 = createVector(out3D.x + out3D.y, out3D.z); + + // Two lines f(x) = m * x + n + let m1 = (end1.y - start1.y) / (end1.x - start1.x); + let m2 = (end2.y - start2.y) / (end2.x - start2.x); + let n1 = end1.y - end1.x * m1; + let n2 = end2.y - end2.x * m2; + + let crossX = (n2 - n1) / (m1 - m2); + let crossY = zIsZero ? 0 : crossX * m1 + n1; + if (xIsZero) { + crossX = 0; + } + return createVector(crossX, crossY); } \ No newline at end of file diff --git a/scripts/rotation.js b/scripts/rotation.js @@ -8,28 +8,28 @@ var currentRotation = 0; var mouseState = false; function getRotation() { - let aktMillis = millis(); - if (mouseIsPressed) { - if (!mouseState) { - startPress = mouseX + currentRotation * 1000; - startPressTime = millis(); - startPressRotation = currentRotation; - mouseState = true; - } - currentRotation = - (mouseX - startPress) / 1000; - } else { - if (mouseState) { - spin = (currentRotation - startPressRotation) / (millis() - startPressTime); - mouseState = false; - } - if (spin > NORMAL_SPIN) { - spin = NORMAL_SPIN + (spin - NORMAL_SPIN) * 0.9; - } - if (spin < NORMAL_SPIN) { - spin = spin + (NORMAL_SPIN - spin) * 0.1; - } - currentRotation += spin * (aktMillis - lastMillis); - } - lastMillis = aktMillis; - return currentRotation; + let aktMillis = millis(); + if (mouseIsPressed) { + if (!mouseState) { + startPress = mouseX + currentRotation * 1000; + startPressTime = millis(); + startPressRotation = currentRotation; + mouseState = true; + } + currentRotation = -(mouseX - startPress) / 1000; + } else { + if (mouseState) { + spin = (currentRotation - startPressRotation) / (millis() - startPressTime); + mouseState = false; + } + if (spin > NORMAL_SPIN) { + spin = NORMAL_SPIN + (spin - NORMAL_SPIN) * 0.9; + } + if (spin < NORMAL_SPIN) { + spin = spin + (NORMAL_SPIN - spin) * 0.1; + } + currentRotation += spin * (aktMillis - lastMillis); + } + lastMillis = aktMillis; + return currentRotation; } \ No newline at end of file diff --git a/scripts/terrain.js b/scripts/terrain.js @@ -1,110 +1,117 @@ class Terrain { - - constructor(dimension, filled) { - this.dimension = dimension; - this.field = []; - - let length = dimension*2-1; - for (let i = 0; i < length; i++) { - this.field.push([]); - for (let j = 0; j < length; j++) { - this.field[i].push(filled?Math.random():0.5); - } - } - } - - transform(destination, speed) { - let length = this.dimension * 2 - 1; - for (let i = 0; i < length; i++) { - for (let j = 0; j < length; j++) { - this.field[i][j] += (destination.field[i][j] - this.field[i][j])*speed; - } - } - } - - scaleUp() { - let ret = new Terrain(this.dimension*2-1, false); - - let length = this.dimension*2-1; - for (let i = 0; i < length; i++) { - for (let j = 0; j < length; j++) { - ret.field[2*i][2*j] = this.field[i][j]; - if (i<length-1){ - ret.field[2*i+1][2*j] = (this.field[i][j]+this.field[i+1][j])/2; + + constructor(dimension, filled) { + this.dimension = dimension; + this.field = []; + + let length = dimension * 2 - 1; + for (let i = 0; i < length; i++) { + this.field.push([]); + for (let j = 0; j < length; j++) { + this.field[i].push(filled ? Math.random() : 0.5); + } + } + } + + transform(destination, speed) { + let length = this.dimension * 2 - 1; + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + this.field[i][j] += (destination.field[i][j] - this.field[i][j]) * speed; + } + } } - if (j<length-1){ - ret.field[2*i][2*j+1] = (this.field[i][j]+this.field[i][j+1])/2; + + scaleUp() { + let ret = new Terrain(this.dimension * 2 - 1, false); + + let length = this.dimension * 2 - 1; + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + ret.field[2 * i][2 * j] = this.field[i][j]; + if (i < length - 1) { + ret.field[2 * i + 1][2 * j] = (this.field[i][j] + this.field[i + 1][j]) / 2; + } + if (j < length - 1) { + ret.field[2 * i][2 * j + 1] = (this.field[i][j] + this.field[i][j + 1]) / 2; + } + if (i < length - 1 && j < length - 1) { + ret.field[2 * i + 1][2 * j + 1] = (this.field[i][j] + this.field[i + 1][j + 1]) / 2; + } + } + } + + return ret; } - if (i<length-1 && j<length-1){ - ret.field[2*i+1][2*j+1] = (this.field[i][j]+this.field[i+1][j+1])/2; + + addRandom(factor) { + let ret = new Terrain(this.dimension, false); + + length = this.dimension * 2 - 1; + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + ret.field[i][j] = this.field[i][j] * (1 - factor) + Math.random() * factor; + } + } + return ret; } - } - } - - return ret; - } - - addRandom(factor) { - let ret = new Terrain(this.dimension, false); - - length = this.dimension*2-1; - for (let i = 0; i < length; i++) { - for (let j = 0; j < length; j++) { - ret.field[i][j] = this.field[i][j]*(1-factor) + Math.random()*factor; - } - } - return ret; - } - - render(scaleXY, scaleZ, rotation) { - let points = []; - let length = this.dimension*2-1; - - //Terrain points - for (let i = 0; i < length; i++) { - for (let j = 0; j < length; j++) { - points.push(tri(createVector( - (j-this.dimension+1)*scaleXY, - (i-this.dimension+1)*scaleXY, - this.field[i][j]*scaleZ - ))); - } - } - - //Terrain triangles - let polygons = []; - let modes = []; - for (let i = 0; i < length-1; i++) { - for (let j = 0; j < length-1; j++) { - if (j-i+1<this.dimension && i-j<this.dimension) { - modes.push(0,0); - polygons.push([i*length+j, i*length+j+1,(i+1)*length+j+1]); - polygons.push([j*length+i, (j+1)*length+i,(j+1)*length+i+1]); + + render(scaleXY, scaleZ, rotation) { + let points = []; + let length = this.dimension * 2 - 1; + + //Terrain points + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + points.push(tri(createVector( + (j - this.dimension + 1) * scaleXY, + (i - this.dimension + 1) * scaleXY, + this.field[i][j] * scaleZ + ))); + } + } + + //Terrain triangles + let polygons = []; + let modes = []; + for (let i = 0; i < length - 1; i++) { + for (let j = 0; j < length - 1; j++) { + if (j - i + 1 < this.dimension && i - j < this.dimension) { + modes.push(0, 0); + polygons.push([i * length + j, i * length + j + 1, (i + 1) * length + j + 1]); + polygons.push([j * length + i, (j + 1) * length + i, (j + 1) * length + i + 1]); + } + } + } + + //Walls + let walls = [ + [], + [], + [], + [], + [], + [] + ]; + for (let i = 0; i < this.dimension; i++) { + walls[0].push(i); + walls[1].push(i * length); + walls[2].push(this.dimension + i * (length + 1) - 1); + walls[3].push((this.dimension - 1) * length + i * (length + 1)); + walls[4].push(length * length - i - 1); + walls[5].push(length * (length - i) - 1); + } + polygons.push(walls[0], walls[1], walls[2], walls[3], walls[4], walls[5]); + modes.push(3, 3, 3, 3, 3, 3); + + render(points, polygons, modes, rotation); } - } - } - - //Walls - let walls = [[],[],[],[],[],[]]; - for (let i = 0; i < this.dimension; i++) { - walls[0].push(i); - walls[1].push(i*length); - walls[2].push(this.dimension+i*(length+1)-1); - walls[3].push((this.dimension-1)*length+i*(length+1)); - walls[4].push(length*length-i-1); - walls[5].push(length*(length-i)-1); - } - polygons.push(walls[0],walls[1],walls[2],walls[3],walls[4],walls[5]); - modes.push(3,3,3,3,3,3); - - render(points,polygons,modes,rotation); - } } function tri(input) { - return createVector( - input.x - input.y/2, - input.y * sqrt(3/4), - input.z - ); + return createVector( + input.x - input.y / 2, + input.y * sqrt(3 / 4), + input.z + ); } \ No newline at end of file