Advertisement
xeromino

terrain

May 14th, 2014
1,835
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 3.72 KB | None | 0 0
  1. /*
  2.   Processing port of http://www.playfuljs.com/realistic-terrain-in-130-lines/
  3.   by Jerome Herr and Abe Pazos
  4. */
  5.  
  6. TerrainP5 t;
  7. void setup() {
  8.   size(900, 500);
  9.   t = new TerrainP5(8);
  10.   doit();
  11. }
  12. void draw() {
  13. }
  14. void doit() {
  15.   background(#C1EDF2);
  16.   t.generate(0.7);
  17.   t.draw();
  18. }
  19. void mousePressed() {
  20.   doit();
  21. }
  22. void keyPressed() {
  23.   if(key == 's') {
  24.     saveFrame("####.jpg");
  25.   }
  26. }
  27.  
  28.  
  29. class TerrainP5 {
  30.   private final int tSize, tMax;
  31.   private float[] tMap;
  32.   private float tRoughness;
  33.  
  34.   TerrainP5(int detail) {
  35.     tSize = int(pow(2, detail)+1);
  36.     tMax = tSize-1;
  37.     tMap = new float[tSize*tSize];
  38.   }
  39.  
  40.   private float getp(int x, int y) {
  41.     if (x < 0 || x > tMax || y < 0 || y > tMax) return -1;
  42.     return tMap[x + tSize * y];
  43.   }
  44.  
  45.   private void setp(int x, int y, float val) {
  46.     tMap[x + tSize * y] = val;
  47.   }
  48.  
  49.   public void generate(float roughness) {
  50.     tRoughness = roughness;
  51.     setp(0, 0, tMax);
  52.     setp(tMax, 0, tMax / 2);
  53.     setp(tMax, tMax, 0);
  54.     setp(0, tMax, tMax / 2);
  55.  
  56.     divide(tMax);
  57.   }
  58.  
  59.   private void divide(int sz) {
  60.     int x, y, half = sz/2;
  61.     float scale = tRoughness * sz;
  62.     if (half < 1) return;
  63.  
  64.     for (y = half; y < tMax; y += sz) {
  65.       for (x = half; x < tMax; x += sz) {
  66.         square(x, y, half, random(-scale, scale));
  67.       }
  68.     }
  69.     for (y = 0; y <= tMax; y += half) {
  70.       for (x = (y + half) % sz; x <= tMax; x += sz) {
  71.         diamond(x, y, half, random(-scale, scale));
  72.       }
  73.     }
  74.     divide(sz/2);
  75.   }
  76.  
  77.   private float average(float[] values) {
  78.     int valid = 0;
  79.     float total = 0;
  80.     for (int i=0; i<values.length; i++) {
  81.       if (values[i] != -1) {
  82.         valid++;
  83.         total += values[i];
  84.       }
  85.     }
  86.     return valid == 0 ? 0 : total / valid;
  87.   }
  88.  
  89.   private void square(int x, int y, int sz, float offset) {
  90.     float ave = average(new float[] {
  91.       getp(x - sz, y - sz), // upper left
  92.       getp(x + sz, y - sz), // upper right
  93.       getp(x + sz, y + sz), // lower right
  94.       getp(x - sz, y + sz)  // lower left
  95.     }
  96.     );
  97.     setp(x, y, ave + offset);
  98.   }
  99.  
  100.   private void diamond(int x, int y, int sz, float offset) {
  101.     float ave = average(new float[] {
  102.       getp(x, y - sz), // top
  103.       getp(x + sz, y), // right
  104.       getp(x, y + sz), // bottom
  105.       getp(x - sz, y)  // left
  106.     }
  107.     );
  108.     setp(x, y, ave + offset);
  109.   }
  110.  
  111.   public void draw() {
  112.     float waterVal = tSize * 0.3;
  113.  
  114.     for (int y = 0; y < tSize; y++) {
  115.       for (int x = 0; x < tSize; x++) {
  116.         float val = getp(x, y);
  117.         PVector top = project(x, y, val);
  118.         PVector bottom = project(x + 1, y, 0);
  119.         PVector water = project(x, y, waterVal);
  120.  
  121.         color c1 = tBrightness(x, y, getp(x + 1, y) - val);
  122.         colorRect(top, bottom, c1);
  123.  
  124.         color c0 = color(50, 150, 200, 256 * 0.15);
  125.         colorRect(water, bottom, c0);
  126.       }
  127.     }
  128.   }
  129.   private void colorRect(PVector top, PVector bottom, color c) {
  130.     if (bottom.y < top.y) return;
  131.     noStroke();
  132.     fill(c);
  133.     rect(top.x, top.y, bottom.x - top.x, bottom.y - top.y);
  134.   }
  135.  
  136.   private color tBrightness(float x, float y, float slope) {
  137.     if (y == tMax || x == tMax) return color(0);
  138.     return color(slope * 50 + 128);
  139.   }
  140.  
  141.   private PVector iso(float x, float y) {
  142.     return new PVector(0.5 * (tSize + x - y), 0.5 * (x + y));
  143.   }
  144.  
  145.   private PVector project(float flatX, float flatY, float flatZ) {
  146.     PVector point = iso(flatX, flatY);
  147.     float x0 = width * 0.5;
  148.     float y0 = height * 0.2;
  149.     float z = tSize * 0.5 - flatZ + point.y * 0.75;
  150.     float x = (point.x - tSize * 0.5) * 6;
  151.     float y = (tSize - point.y) * 0.005 + 1;
  152.  
  153.     return new PVector(x0 + x/y, y0 + z/y);
  154.   }
  155. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement