有没有办法提升我这段过程生成代码的性能?

huangapple 未分类评论46阅读模式
英文:

Is there any way to improve performance of my procedural generation code?

问题

package Terrain;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import Entities.Entity;
import Maths.Vector3f;
import Models.RawModel;
import Render.Loader;

public class Terrain {
    // ... (Variable and constructor definitions are omitted for brevity)

    public void loadMarchingTerrain(){
        // ... (Implementation details are omitted for brevity)
    }
    
    public int configIndex(float[] cube){
        // ... (Implementation details are omitted for brevity)
    }
    
    public float sampleTerrain(Vector3f point){
        // ... (Implementation details are omitted for brevity)
    }
    
    public Vector3f smoothPoint(Vector3f vert1, Vector3f vert2, int indice, float[] cube){
        // ... (Implementation details are omitted for brevity)
    }

    public void marchCube(Vector3f position){
        // ... (Implementation details are omitted for brevity)
    }

    public double sumOctaves(int iterations, double x, double y, double z, double persistance, double scale, double low, double high){
        // ... (Implementation details are omitted for brevity)
    }

    public double sumOctaves(int iterations, int x, int y, double persistance, double scale, double low, double high){
        // ... (Implementation details are omitted for brevity)
    }

    public List<Entity> getCubes(){
        return cubes;
    }

    public float getX() {
        return x;
    }

    public float getZ() {
        return z;
    }

    public float getY() {
        return y;
    }

    public RawModel getRawModel(){
        return model;
    }
}

Please note that I've only provided the code portion that was originally in English and asked for translation. The provided code is a Java class for terrain generation using procedural methods and the Marching Cubes algorithm. If you have any specific questions about the code or need further assistance, feel free to ask.

英文:

I've been working on a project lately that creates procedurally generated terrain which uses 3d simplex noise as well as the Marching cubes algorithm. I am currently running it on my cpu which takes around 10-20 seconds to render a 200x200x200 terrain which isn't optimal if I want to make the world infinite. Is there any way to improve the speed which the terrain renders or is this the maximum speed I can achieve. (I've already tried using compute shaders but limitations with GLSL didn't allow me to pursue that idea.)

Terrain Generation Code

package Terrain;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import Entities.Entity;
import Maths.Vector3f;
import Models.RawModel;
import Render.Loader;


public class Terrain {
	private int width = 200, height = 2, interval = 8;
	
	private float x,y,z = 2f;
	private int x1,y1,z1;
	
	private Loader loader;
	
	private List&lt;Entity&gt; cubes = new ArrayList&lt;Entity&gt;();
	

	private RawModel model;

	private double perlin2DScale = 0.01, perlin3DScale = 0.01;//, maskScale = 0.00;
	
	private double perlin3Dratio = 0.8;// ratio of 3d noise to 2d;
	
	private double amp = 1; //height of mountains
	
	List&lt;Vector3f&gt; verticeArray = new ArrayList&lt;Vector3f&gt;();
	float[][][] terrainMap = new float[width+1][height+1][width+1];
	float[] SimplexMap3D = new float[(width+1)*(height+1)*(width+1)];
	float[] SimplexMap2D = new float[(width+1)*(width+1)];

	private float surfaceLevel = 1f;
		
	int seed;
	
	//SimplexComputeBuffer compute = new SimplexComputeBuffer();
	public Terrain(float x, float z, Loader loader){
		this.loader = loader; 
		this.x1 = (int) (x*width);
		this.z1 = (int) (z*width);
		this.x = x*width*interval;
		this.z = z*width*interval;
		Random rand = new Random();
		seed = rand.nextInt(100000);
		
		loadMarchingTerrain();
	}
	public void changeAmp(double i){
		x+=i;
		System.out.println(&quot;amp =&quot;+amp);
		verticeArray.clear();
		loadMarchingTerrain();
	}
	public void changeSurface(double i){
		surfaceLevel+=i;
		System.out.println(&quot;surface =&quot;+surfaceLevel);
		verticeArray.clear();
		loadMarchingTerrain();
	}
	public void loadMarchingTerrain(){
		for(int x = x1; x&lt;x1+width+1; x++){
			for(int y = y1; y&lt;y1+height+1; y++){
				for(int z = z1; z&lt;z1+width+1; z++){	
					double noise3d = this.sumOctaves(4,x,y,z,0.5,perlin3DScale,0,1); // creates 3d terrain like caves and overhangs
					double noise2d = this.sumOctaves(4,x,z,0.5,perlin2DScale,0,1); // creates 2d terrain like mountains and hills (gives only height)
					//double mask =  this.sumOctaves(1,x,z,0.5,maskScale,0,1); // creates a 2d mask to vary heights of regions
					float curHeight = (float)height*(float)(noise2d*(1-perlin3Dratio)+noise3d*perlin3Dratio); // mixing them together with correct ratio of 3d and 2d data
					terrainMap[x-x1][y-y1][z-z1] = (float)-y+curHeight;
				}
			}
		}
		for(int x = 0; x&lt;width; x++){
			for(int y = 0; y&lt;height; y++){
				for(int z = 0; z&lt;width; z++){
					marchCube(new Vector3f(x,y,z));	
				}
			}
		}
		float[] vertices = new float[verticeArray.size()*3];
		int[] indice = new int[verticeArray.size()];
		int vertexCount = 0;
		for(Vector3f v : verticeArray){
			vertices[vertexCount++] =v.x*interval;
			vertices[vertexCount++] =v.y*interval;
			vertices[vertexCount++] =v.z*interval;
		}
		for(int i = 0; i&lt;indice.length; i++){
			indice[i] = i;
		}
		model = loader.loadToVao(vertices, null, indice);
	}
	
	public int configIndex(float[] cube){
		int configIndex = 0;
		for(int i = 0; i&lt;8; i++){
			if(cube[i] &gt; surfaceLevel){
				configIndex |= 1 &lt;&lt; i;
			}
		}		
		return configIndex;
	}
	
	public float sampleTerrain(Vector3f point){
		return terrainMap[(int) point.x][(int) point.y][(int) point.z];
	}
	
	public Vector3f smoothPoint(Vector3f vert1, Vector3f vert2, int indice, float[] cube){
		float sampleVert1 = cube[MarchingCubeTable.edges[indice][0]];
		float sampleVert2 = cube[MarchingCubeTable.edges[indice][1]];
		
		float difference = sampleVert1-sampleVert2;
		
		if(difference == 0){
			difference = surfaceLevel;
		}else{
			difference = (surfaceLevel-sampleVert1)/difference;
		}
		Vector3f a2 = vert1.subtract(vert2).scale(difference);
		
		Vector3f vertPos = vert1.add(a2);

		return vertPos;
	}
	public void marchCube(Vector3f position){
		//create cube
		float[] cube = new float[8];
		for(int i = 0; i&lt;8; i++){		
			Vector3f corner = position.add(MarchingCubeTable.cornerTable[i]);		
			cube[i] = terrainMap[(int) corner.x][(int) corner.y][(int) corner.z];		
		}
		//search through index
		int currentConfigIndex = configIndex(cube);		
		if(currentConfigIndex == 0 || currentConfigIndex == 255){
			return;
		}		
		//search through points
		int edgeIndex = 0;
		for(int j = 0; j&lt;5; j++){
			for(int i = 0; i&lt;3; i++){
				int indice = MarchingCubeTable.getIndex(currentConfigIndex)[edgeIndex];			
				if(indice == -1){
					return;
				}
				Vector3f vert2 = position.add(MarchingCubeTable.cornerTable[MarchingCubeTable.edges[indice][0]]);
				Vector3f vert1 = position.add(MarchingCubeTable.cornerTable[MarchingCubeTable.edges[indice][1]]);			
				Vector3f vertPos = this.smoothPoint(vert1, vert2, indice, cube);				
				verticeArray.add(vertPos);
				edgeIndex++;
			}
		}
	}
	
	/*
	 * Simplex Noise functions
	 */
	public double sumOctaves(int iterations, double x, double y, double z, double persistance, double scale, double low, double high){
		double maxamp = 0;
		double amp = this.amp;
		double frequency = scale;
		double noise = 0;
		
		for(int i = 0; i&lt;iterations; i++){
			noise += SimplexNoise.noise((x)*frequency, (y)*frequency, (z)*frequency)*amp;
			maxamp += amp;
			amp *= persistance;
			frequency *= 2;
		}
		
		noise /= maxamp;
		
		noise = noise * (high - low) / 2 + (high + low) / 2;
		return noise;
	}
	
	public double sumOctaves(int iterations, int x, int y, double persistance, double scale, double low, double high){
		double maxamp = 0;
		double amp = this.amp;
		double frequency = scale;
		double noise = 0;
		
		for(int i = 0; i&lt;iterations; i++){
			noise += SimplexNoise.noise((x)*frequency, (y)*frequency)*amp;
			maxamp += amp;
			amp *= persistance;
			frequency *= 2;
		}
		
		noise /= maxamp;
		
		noise = noise * (high - low) / 2 + (high + low) / 2;
		return noise;
	}
	
	public List&lt;Entity&gt; getCubes(){
		return cubes;
	}
	public float getX() {
		return x;
	}

	public float getZ() {
		return z;
	}
	
	public float getY() {
		return y;
	}
	public RawModel getRawModel(){
		return model;
	}
}

huangapple
  • 本文由 发表于 2020年7月24日 07:40:58
  • 转载请务必保留本文链接:https://java.coder-hub.com/63064690.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定