terrain-generator

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

render.js (4851B)


      1 function render(points, polygons, modes, rotation) {
      2     //Modes: 0: polygon, 1-4: wall
      3     rotation *= TWO_PI;
      4 
      5     // extract points
      6     polygons.forEach(function(polygon, index) {
      7         polygons.push([]);
      8         polygon.forEach(corner => {
      9             polygons[polygons.length - 1].push(Object.assign({}, points[corner]));
     10         });
     11     });
     12     polygons = polygons.slice(polygons.length / 2);
     13 
     14     // sort the polygons
     15     let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000);
     16 
     17     polygons.forEach((polygon, index) => {
     18         let sum = createVector(0, 0);
     19         polygon.forEach(corner => {
     20             sum.x += corner.x;
     21             sum.y += corner.y;
     22             sum.z += corner.z;
     23         });
     24         sum.x /= polygon.length;
     25         sum.y /= polygon.length;
     26         sum.z /= polygon.length;
     27         polygon.average = Object.assign({}, sum);
     28         polygon.depth = depth(polygon.average, rot);
     29         polygon.mode = modes[index];
     30         polygon.size = (polygon.mode > 0) ? SIZE : 1;
     31         polygon.depth *= polygon.size;
     32     });
     33 
     34     polygons.sort(function(a, b) {
     35         return a.depth - b.depth;
     36     });
     37 
     38     // draw to the screen
     39     polygons.forEach(polygon => {
     40         if (polygon.mode !== 0) {
     41             drawWall(polygon.mode, polygon, rotation);
     42         } else {
     43             drawPolygon(polygon, rotation);
     44         }
     45     });
     46 }
     47 
     48 function depth(point, rotation) {
     49     return -point.x * rotation.y - point.y * rotation.x;
     50 }
     51 
     52 function drawPolygon(points, rotation) {
     53     points.forEach(function(item) {
     54         let newVec = calc3D(item.x, item.y, item.z - ANGLE, rotation);
     55         item.x = newVec.x;
     56         item.y = newVec.y;
     57     });
     58     beginShape();
     59     points.forEach(function(item) {
     60         vertex(CENTER.x + item.x, CENTER.y - item.y - ANGLE + SIZE / 2 + addHeight);
     61     });
     62     vertex(CENTER.x + points[0].x, CENTER.y - points[0].y - ANGLE + SIZE / 2 + addHeight);
     63     endShape();
     64 }
     65 
     66 function drawWall(side, points, rotation) {
     67     let endX;
     68     let startX;
     69     let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000);
     70     let swap = depth(points[0], rot) > depth(points[points.length - 1], rot);
     71     points.forEach(function(item, index) {
     72         let newVec = calc3D(item.x, item.y, item.z - ANGLE, rotation);
     73         item.x = newVec.x;
     74         item.y = newVec.y;
     75         if (index == 0) {
     76             startX = newVec.x;
     77         }
     78         if (index == points.length - 1) {
     79             endX = newVec.x;
     80         }
     81     });
     82     if (swap)[startX, endX] = [endX, startX];
     83     if ((abs(endX) - abs(startX)) < 0) {
     84         beginShape();
     85         switch (side) {
     86             case 1:
     87                 vertex(CENTER.x + points[0].x, 0);
     88                 break;
     89             case 2:
     90                 vertex(WIDTH, CENTER.y - points[0].y - ANGLE + SIZE / 2 + addHeight);
     91                 break;
     92             case 3:
     93                 vertex(CENTER.x + points[0].x, HEIGHT + addHeight);
     94                 break;
     95             case 4:
     96                 vertex(0, CENTER.y - points[0].y - ANGLE + SIZE / 2 + addHeight);
     97                 break;
     98         }
     99         points.forEach(function(item) {
    100             vertex(CENTER.x + item.x, CENTER.y - item.y - ANGLE + SIZE / 2 + addHeight);
    101         });
    102         switch (side) {
    103             case 1:
    104                 vertex(CENTER.x + points[points.length - 1].x, 0);
    105                 break;
    106             case 2:
    107                 vertex(WIDTH, CENTER.y - points[points.length - 1].y - ANGLE + SIZE / 2 + addHeight);
    108                 break;
    109             case 3:
    110                 vertex(CENTER.x + points[points.length - 1].x, HEIGHT + addHeight);
    111                 break;
    112             case 4:
    113                 vertex(0, CENTER.y - points[points.length - 1].y - ANGLE + SIZE / 2 + addHeight);
    114                 break;
    115         }
    116         endShape();
    117     }
    118 }
    119 
    120 function calc3D(x, y, z, rotation) {
    121 
    122     let rot = createVector(round(cos(rotation) * 1000) / 1000, round(-sin(rotation) * 1000) / 1000);
    123     let out3D = createVector(x * rot.x - y * rot.y, x * rot.y + y * rot.x, z);
    124 
    125     let zIsZero = false;
    126     let xIsZero = false;
    127     if (out3D.z === 0) {
    128         out3D.z = 1;
    129         zIsZero = true;
    130     }
    131     if (out3D.x === 0) {
    132         out3D.x = 1;
    133         xIsZero = true;
    134     }
    135     let start1 = CENTER_HORIZON;
    136     let start2 = LEFT_HORIZON;
    137     let end1 = createVector(out3D.x, out3D.z);
    138     let end2 = createVector(out3D.x + out3D.y, out3D.z);
    139 
    140     // Two lines f(x) = m * x + n
    141     let m1 = (end1.y - start1.y) / (end1.x - start1.x);
    142     let m2 = (end2.y - start2.y) / (end2.x - start2.x);
    143     let n1 = end1.y - end1.x * m1;
    144     let n2 = end2.y - end2.x * m2;
    145 
    146     let crossX = (n2 - n1) / (m1 - m2);
    147     let crossY = zIsZero ? 0 : crossX * m1 + n1;
    148     if (xIsZero) {
    149         crossX = 0;
    150     }
    151     return createVector(crossX, crossY);
    152 }