Advertisement
Guest User

TerrainNode

a guest
Jul 17th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.79 KB | None | 0 0
  1. package engine.terrain;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import org.joml.Vector2f;
  7. import org.joml.Vector3f;
  8.  
  9. import engine.entity.camera.Camera;
  10. import engine.model.RawModel;
  11. import engine.render.Renderer;
  12.  
  13. public class TerrainNode extends Node {
  14.    
  15.     public static final float[] lodRanges = new float[] {400, 200, 100, 40};
  16.     public static final int vertexCount = 5;
  17.    
  18.     private HeightsGenerator generator;
  19.     private TerrainTile terrainTile;
  20.     private RawModel rawModel;
  21.     private List<Node> childrenBackup = new ArrayList<Node>();
  22.     private float[][] heights;
  23.     private float scale;
  24.     private int gridX;
  25.     private int gridZ;
  26.     private int lod;
  27.     private boolean isLeaf = false;
  28.     private Vector3f temp = new Vector3f();
  29.     private Vector2f location;
  30.    
  31.    
  32.     public TerrainNode(TerrainTile terrainTile, Vector2f location, float scale, int lod) {
  33.         super();
  34.         heights = new float[vertexCount][vertexCount];
  35.         this.generator = terrainTile.getGenerator();
  36.         this.gridX = terrainTile.getGridX();
  37.         this.gridZ = terrainTile.getGridZ();
  38.         this.terrainTile = terrainTile;
  39.         this.location = location;
  40.         this.isLeaf = true;
  41.         this.scale = scale;
  42.         this.lod = lod;
  43.         generateHeights();
  44.         generateModel();
  45.     }
  46.    
  47.     public void addChildNodes() {
  48.         isLeaf = false;
  49.         if(childrenBackup.isEmpty()) {
  50.             for(int x = 0; x < 2; x++) {
  51.                 for(int y = 0; y < 2; y++) {
  52.                     addChild(new TerrainNode(terrainTile, new Vector2f(location.x + x * (scale / 2), location.y + y * (scale / 2)), scale / 2, lod + 1));
  53.                 }
  54.             }
  55.             childrenBackup.addAll(getChildren());
  56.         }else {
  57.             for(Node n : childrenBackup) {
  58.                 addChild(n);
  59.             }
  60.         }
  61.     }
  62.    
  63.     @Override
  64.     public void update() {
  65.         if(lod < lodRanges.length) {
  66.             float size = terrainTile.getSize();
  67.             temp.set(location.x + (scale / 2) + size*gridX, 0, location.y + (scale / 2) + size*gridZ);
  68.             if(Camera.getInstance().getPosition().sub(temp, temp).length() <= lodRanges[lod]) {
  69.                 if(getChildren().isEmpty()) {
  70.                     addChildNodes();
  71.                 }
  72.                 for(Node n : getChildren()) {
  73.                     TerrainNode tn = (TerrainNode) n;
  74.                     tn.update();
  75.                 }
  76.             }else {
  77.                 if(!getChildren().isEmpty()) {
  78.                     removeChildNodes();
  79.                 }
  80.                 for(Node n : getChildren()) {
  81.                     TerrainNode tn = (TerrainNode) n;
  82.                     tn.update();
  83.                 }
  84.             }
  85.         }
  86.     }
  87.    
  88.     public void removeChildNodes() {
  89.         isLeaf = true;
  90.         getChildren().clear();
  91.     }
  92.    
  93.     public void render() {
  94.         if(isLeaf) {
  95.             if(rawModel.getVao() != null) {
  96.                 Renderer.terrainRenderer.counter++;
  97.                 Renderer.terrainRenderer.prepareTerrain(rawModel);
  98.                 Renderer.terrainRenderer.renderTerrain(this);
  99.                 Renderer.terrainRenderer.unloadTerrain();
  100.             }
  101.         }
  102.         super.render();
  103.     }
  104.    
  105.     private void generateHeights() {
  106.         for(int x = 0; x < vertexCount; x++) {
  107.             for(int y = 0; y < vertexCount; y++) {
  108.                 heights[x][y] = getGeneratedHeight(x, y);
  109.             }
  110.         }
  111.         applyCorrection();
  112.     }
  113.    
  114.     private void generateModel() {
  115.         int count = vertexCount * vertexCount;
  116.         float[] vertices = new float[count * 3];
  117.         float[] normals = new float[count * 3];
  118.         float[] textureCoords = new float[count * 2];
  119.         int[] indices = new int[6*(vertexCount-1)*(vertexCount-1)];
  120.         int vertexPointer = 0;
  121.         float size = terrainTile.getSize();
  122.         for(int y=0;y<vertexCount;y++){
  123.             for(int x=0;x<vertexCount;x++){
  124.                 vertices[vertexPointer*3] = location.x + x * (scale / (vertexCount - 1)) + size*gridX;
  125.                 vertices[vertexPointer*3+1] = getHeight(x, y);
  126.                 vertices[vertexPointer*3+2] = location.y + y * (scale / (vertexCount - 1)) + size*gridZ;
  127.                 Vector3f normal = calculateNormal(x, y);
  128.                 normals[vertexPointer*3] = normal.x;
  129.                 normals[vertexPointer*3+1] = normal.y;
  130.                 normals[vertexPointer*3+2] = normal.z;
  131.                 textureCoords[vertexPointer*2] = (location.x + x * (scale / (vertexCount - 1))) / size;
  132.                 textureCoords[vertexPointer*2+1] = (location.y + y * (scale / (vertexCount - 1))) / size;
  133.                 vertexPointer++;
  134.             }
  135.         }
  136.         int pointer = 0;
  137.         for(int gz=0;gz<vertexCount-1;gz++){
  138.             for(int gx=0;gx<vertexCount-1;gx++){
  139.                 int topLeft = (gz*vertexCount)+gx;
  140.                 int topRight = topLeft + 1;
  141.                 int bottomLeft = ((gz+1)*vertexCount)+gx;
  142.                 int bottomRight = bottomLeft + 1;
  143.                 indices[pointer++] = topLeft;
  144.                 indices[pointer++] = bottomLeft;
  145.                 indices[pointer++] = topRight;
  146.                 indices[pointer++] = topRight;
  147.                 indices[pointer++] = bottomLeft;
  148.                 indices[pointer++] = bottomRight;
  149.             }
  150.         }
  151.         this.rawModel = new RawModel(vertices, textureCoords, normals, indices);
  152.     }
  153.    
  154.     private Vector3f calculateNormal(float x, float z) {
  155.         float nx = x + 0;
  156.         float nz = z + 0;
  157.         float heightL = getGeneratedHeight(nx - 1, nz);
  158.         float heightR = getGeneratedHeight(nx + 1, nz);
  159.         float heightU = getGeneratedHeight(nx, nz - 1);
  160.         float heightD = getGeneratedHeight(nx, nz + 1);
  161.         Vector3f normal = new Vector3f(heightL - heightR, 2f, heightU - heightD);
  162.         normal.normalize();
  163.         return normal;
  164.     }
  165.    
  166.     private float getHeight(int x, int y) {
  167.         return heights[x][y];
  168.     }
  169.    
  170.     private float getGeneratedHeight(float x, float y) {
  171.         float size = terrainTile.getSize();
  172.         return generator.generateHeight(location.x + x * (scale / (vertexCount - 1)) + size*gridX, location.y + y * (scale / (vertexCount - 1)) + size*gridZ);
  173.     }
  174.    
  175.     private void applyCorrection() {
  176. //      heights[0][1] = Maths.mix(heights[0][0], heights[0][2], 0.5f);
  177. //      heights[0][3] = Maths.mix(heights[0][2], heights[0][4], 0.5f);
  178. //      heights[4][1] = Maths.mix(heights[4][0], heights[4][2], 0.5f);
  179. //      heights[4][3] = Maths.mix(heights[4][2], heights[4][4], 0.5f);
  180. //      heights[1][0] = Maths.mix(heights[0][0], heights[2][0], 0.5f);
  181. //      heights[3][0] = Maths.mix(heights[2][0], heights[4][0], 0.5f);
  182. //      heights[1][4] = Maths.mix(heights[0][4], heights[2][4], 0.5f);
  183. //      heights[3][4] = Maths.mix(heights[2][4], heights[4][4], 0.5f);
  184.     }
  185.  
  186.     public RawModel getRawModel() {
  187.         return rawModel;
  188.     }
  189.  
  190.     public void setRawModel(RawModel rawModel) {
  191.         this.rawModel = rawModel;
  192.     }
  193.  
  194.     public int getGridX() {
  195.         return gridX;
  196.     }
  197.  
  198.     public void setGridX(int gridX) {
  199.         this.gridX = gridX;
  200.     }
  201.  
  202.     public int getGridZ() {
  203.         return gridZ;
  204.     }
  205.  
  206.     public void setGridZ(int gridZ) {
  207.         this.gridZ = gridZ;
  208.     }
  209.  
  210.     public float[][] getHeights() {
  211.         return heights;
  212.     }
  213.  
  214.     public void setHeights(float[][] heights) {
  215.         this.heights = heights;
  216.     }
  217.  
  218.     public HeightsGenerator getGenerator() {
  219.         return generator;
  220.     }
  221.  
  222.     public void setGenerator(HeightsGenerator generator) {
  223.         this.generator = generator;
  224.     }
  225.  
  226.     public Vector2f getLocation() {
  227.         return location;
  228.     }
  229.  
  230.     public void setLocation(Vector2f location) {
  231.         this.location = location;
  232.     }
  233.  
  234.     public float getScale() {
  235.         return scale;
  236.     }
  237.  
  238.     public void setScale(float scale) {
  239.         this.scale = scale;
  240.     }
  241.  
  242.     public boolean isLeaf() {
  243.         return isLeaf;
  244.     }
  245.  
  246.     public void setLeaf(boolean isLeaf) {
  247.         this.isLeaf = isLeaf;
  248.     }
  249.  
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement