Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package engine.terrain;
- import java.util.ArrayList;
- import java.util.List;
- import org.joml.Vector2f;
- import org.joml.Vector3f;
- import engine.entity.camera.Camera;
- import engine.model.RawModel;
- import engine.render.Renderer;
- public class TerrainNode extends Node {
- public static final float[] lodRanges = new float[] {400, 200, 100, 40};
- public static final int vertexCount = 5;
- private HeightsGenerator generator;
- private TerrainTile terrainTile;
- private RawModel rawModel;
- private List<Node> childrenBackup = new ArrayList<Node>();
- private float[][] heights;
- private float scale;
- private int gridX;
- private int gridZ;
- private int lod;
- private boolean isLeaf = false;
- private Vector3f temp = new Vector3f();
- private Vector2f location;
- public TerrainNode(TerrainTile terrainTile, Vector2f location, float scale, int lod) {
- super();
- heights = new float[vertexCount][vertexCount];
- this.generator = terrainTile.getGenerator();
- this.gridX = terrainTile.getGridX();
- this.gridZ = terrainTile.getGridZ();
- this.terrainTile = terrainTile;
- this.location = location;
- this.isLeaf = true;
- this.scale = scale;
- this.lod = lod;
- generateHeights();
- generateModel();
- }
- public void addChildNodes() {
- isLeaf = false;
- if(childrenBackup.isEmpty()) {
- for(int x = 0; x < 2; x++) {
- for(int y = 0; y < 2; y++) {
- addChild(new TerrainNode(terrainTile, new Vector2f(location.x + x * (scale / 2), location.y + y * (scale / 2)), scale / 2, lod + 1));
- }
- }
- childrenBackup.addAll(getChildren());
- }else {
- for(Node n : childrenBackup) {
- addChild(n);
- }
- }
- }
- @Override
- public void update() {
- if(lod < lodRanges.length) {
- float size = terrainTile.getSize();
- temp.set(location.x + (scale / 2) + size*gridX, 0, location.y + (scale / 2) + size*gridZ);
- if(Camera.getInstance().getPosition().sub(temp, temp).length() <= lodRanges[lod]) {
- if(getChildren().isEmpty()) {
- addChildNodes();
- }
- for(Node n : getChildren()) {
- TerrainNode tn = (TerrainNode) n;
- tn.update();
- }
- }else {
- if(!getChildren().isEmpty()) {
- removeChildNodes();
- }
- for(Node n : getChildren()) {
- TerrainNode tn = (TerrainNode) n;
- tn.update();
- }
- }
- }
- }
- public void removeChildNodes() {
- isLeaf = true;
- getChildren().clear();
- }
- public void render() {
- if(isLeaf) {
- if(rawModel.getVao() != null) {
- Renderer.terrainRenderer.counter++;
- Renderer.terrainRenderer.prepareTerrain(rawModel);
- Renderer.terrainRenderer.renderTerrain(this);
- Renderer.terrainRenderer.unloadTerrain();
- }
- }
- super.render();
- }
- private void generateHeights() {
- for(int x = 0; x < vertexCount; x++) {
- for(int y = 0; y < vertexCount; y++) {
- heights[x][y] = getGeneratedHeight(x, y);
- }
- }
- applyCorrection();
- }
- private void generateModel() {
- int count = vertexCount * vertexCount;
- float[] vertices = new float[count * 3];
- float[] normals = new float[count * 3];
- float[] textureCoords = new float[count * 2];
- int[] indices = new int[6*(vertexCount-1)*(vertexCount-1)];
- int vertexPointer = 0;
- float size = terrainTile.getSize();
- for(int y=0;y<vertexCount;y++){
- for(int x=0;x<vertexCount;x++){
- vertices[vertexPointer*3] = location.x + x * (scale / (vertexCount - 1)) + size*gridX;
- vertices[vertexPointer*3+1] = getHeight(x, y);
- vertices[vertexPointer*3+2] = location.y + y * (scale / (vertexCount - 1)) + size*gridZ;
- Vector3f normal = calculateNormal(x, y);
- normals[vertexPointer*3] = normal.x;
- normals[vertexPointer*3+1] = normal.y;
- normals[vertexPointer*3+2] = normal.z;
- textureCoords[vertexPointer*2] = (location.x + x * (scale / (vertexCount - 1))) / size;
- textureCoords[vertexPointer*2+1] = (location.y + y * (scale / (vertexCount - 1))) / size;
- vertexPointer++;
- }
- }
- int pointer = 0;
- for(int gz=0;gz<vertexCount-1;gz++){
- for(int gx=0;gx<vertexCount-1;gx++){
- int topLeft = (gz*vertexCount)+gx;
- int topRight = topLeft + 1;
- int bottomLeft = ((gz+1)*vertexCount)+gx;
- int bottomRight = bottomLeft + 1;
- indices[pointer++] = topLeft;
- indices[pointer++] = bottomLeft;
- indices[pointer++] = topRight;
- indices[pointer++] = topRight;
- indices[pointer++] = bottomLeft;
- indices[pointer++] = bottomRight;
- }
- }
- this.rawModel = new RawModel(vertices, textureCoords, normals, indices);
- }
- private Vector3f calculateNormal(float x, float z) {
- float nx = x + 0;
- float nz = z + 0;
- float heightL = getGeneratedHeight(nx - 1, nz);
- float heightR = getGeneratedHeight(nx + 1, nz);
- float heightU = getGeneratedHeight(nx, nz - 1);
- float heightD = getGeneratedHeight(nx, nz + 1);
- Vector3f normal = new Vector3f(heightL - heightR, 2f, heightU - heightD);
- normal.normalize();
- return normal;
- }
- private float getHeight(int x, int y) {
- return heights[x][y];
- }
- private float getGeneratedHeight(float x, float y) {
- float size = terrainTile.getSize();
- return generator.generateHeight(location.x + x * (scale / (vertexCount - 1)) + size*gridX, location.y + y * (scale / (vertexCount - 1)) + size*gridZ);
- }
- private void applyCorrection() {
- // heights[0][1] = Maths.mix(heights[0][0], heights[0][2], 0.5f);
- // heights[0][3] = Maths.mix(heights[0][2], heights[0][4], 0.5f);
- // heights[4][1] = Maths.mix(heights[4][0], heights[4][2], 0.5f);
- // heights[4][3] = Maths.mix(heights[4][2], heights[4][4], 0.5f);
- // heights[1][0] = Maths.mix(heights[0][0], heights[2][0], 0.5f);
- // heights[3][0] = Maths.mix(heights[2][0], heights[4][0], 0.5f);
- // heights[1][4] = Maths.mix(heights[0][4], heights[2][4], 0.5f);
- // heights[3][4] = Maths.mix(heights[2][4], heights[4][4], 0.5f);
- }
- public RawModel getRawModel() {
- return rawModel;
- }
- public void setRawModel(RawModel rawModel) {
- this.rawModel = rawModel;
- }
- public int getGridX() {
- return gridX;
- }
- public void setGridX(int gridX) {
- this.gridX = gridX;
- }
- public int getGridZ() {
- return gridZ;
- }
- public void setGridZ(int gridZ) {
- this.gridZ = gridZ;
- }
- public float[][] getHeights() {
- return heights;
- }
- public void setHeights(float[][] heights) {
- this.heights = heights;
- }
- public HeightsGenerator getGenerator() {
- return generator;
- }
- public void setGenerator(HeightsGenerator generator) {
- this.generator = generator;
- }
- public Vector2f getLocation() {
- return location;
- }
- public void setLocation(Vector2f location) {
- this.location = location;
- }
- public float getScale() {
- return scale;
- }
- public void setScale(float scale) {
- this.scale = scale;
- }
- public boolean isLeaf() {
- return isLeaf;
- }
- public void setLeaf(boolean isLeaf) {
- this.isLeaf = isLeaf;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement