4D perlin noise terrain

Started by
18 comments, last by Facehat 10 years, 8 months ago

Yep that's about right. It might pay to remember that when you generate the mesh, you define an arbitrary box (say, 32x32x32) and then for each voxel in this box you do the checking and so on to get your triangle out. This is why the method is very good for implementation on the GPU since you can run all of the individual voxels separately and run them all in parallel to lower the run time.

Advertisement


and then for each voxel in this box you do the checking and so on

Ok. Does voxel==marching cube?

Do most GPUs have the capability? Which one is easier to implement?

I'm still new to perlin noise. So I mentioned that I am using 3D PN to generate the terrain image for the planets. I am not using PN to create an actual mesh for the planet. The image for each planet is 720x360. As I get closer to the planet, the program will guess where the ship is going to land and start generating the 3D terrain meshes. I need to use the same terrain as the image to do this because I don't want the player to be heading toward a mountain and, when the 3D terrain is generated, now be heading toward an ocean. How far down (zoomed in) can I do the PN calculation? Will it translate or will I need to come up with a method that takes the original terrain into account?

Ok. I'm looking at the code I got from "Polygonising a scalar field" article you recommended. I can't figure out how to utilize it. I know I need to generate a random volume with PN, but where would I put that data in the CIsoSurface class? Can you give me a simple example of how to use it?

From that website, it assumes a GRIDCELL struct is provided defined as:


typedef struct {
   XYZ p[8];
   double val[8];
} GRIDCELL;

The polygonise function take that as an input. The p array is just an array of vectors defining the corners of the voxel, and the val array is the 'density' and each of those corners. It assumes that these values are already set. So what would be happening in the given example is you would prepare this struct with positions and the output of the density function at that position and then let the polygonise function go on that. Something like the following c++ code:


// You could define this anywhere really, probably better using pre-allocated memory in your case
TRIANGLE *triList = new TRIANGLE[maxTriCount];
int trisMade = 0; // keep track of where we are going to write to in the array

for (int x = 0; x < grid_width; ++x)
  for (int y = 0; y < grid_height; ++y)
    for (int z = 0; z < grid_height; ++z)
    {
      GRIDCELL cell;
      
      // setup all the positions for the cell
      cell.p[0] = { x, y, z };
      cell.p[1] = { x + 1, y, z };
      cell.p[2] = { x + 1, y, z + 1 };
      cell.p[3] = { x, y, z + 1 };
      
      cell.p[4] = { x, y + 1, z };
      cell.p[5] = { x + 1, y + 1, z };
      cell.p[6] = { x + 1, y + 1, z + 1 };
      cell.p[7] = { x, y + 1, z + 1 };
      
      // fill the density values for each corner
      for (int i = 0; i < 8; ++i)
        cell.val[i] = DensityFunction(cell.p[i][0] /* x */, cell.p[i][1] /* y */, cell.p[i][2] /* z */);
      
      // the polygonise function adds triangles to the list provided at the trisMade index and returns how many triangles written to the list
      // this way we can keep calling this and it will always write to the end of the list.
      int count = Polygonise(cell, 0.0 /* isolevel */, &triList[trisMade]);
      trisMade += count;
    }

(Note: this code is untested, I just made it up on the spot)

I hope this clears it up a little bit, I suggest trying to look at where the example on the web site gets its inputs and how it uses them to generate each individual triangle.

I looked at the code on the website and compared it to the files. GRIDCELL doesn't appear in the code......

Here is what I "think" it should be:


CIsoSurface<float> testTerrain;

defined somewhere.

Then:


testTerrain.GenerateSurface(.....);

to generate the surface.... Don't know where I would grab the vertex buffer to render it though.......

The GenerateSurface is defined as:


void GenerateSurface(const T* ptScalarField, T tIsoLevel, unsigned int nCellsX, unsigned int nCellsY,  unsigned int nCellsZ, float fCellLengthX, float fCellLengthY, float fCellLengthZ);

I assume ptScalarField is a pointer to a linearized version of the random valued volume. tIsoLevel is the "density" value each voxel will be tested against. And the others seem straight forward.

From looking at the code (I previously hadn't looked at it myself) you are right that the ptScalarField is a list of the density values at each corner in the grid to be generated. This array would be generated by you

If you were going to use this as a base implementation to suit to your needs, then you would need to add a method to extract the list of triangles that were generated and stored in the m_trivecTriangles vector of triangles.

Yea, that's what I thought..... Well, I can't ask the author to do EVERYTHING for me.rolleyes.gif

It shouldn't be hard to do that. Looking at the code leads me to believe the author was trying to be as generic as possible. I think I could adapt the classes to use DX vectors. Or would I even need to.....

I think I could adapt the classes to use DX vectors. Or would I even need to.....

It could potentially save some hassle else where, and I don't imagine it would be terribly difficult, just out of curiosity which math library are you using?

What do you mean? I am using the one that is standard with the compiler and all the maths that comes with DX9.

You might want to look into Simplex noise (like perlin noise, but N-dimensional and potentially faster).

This topic is closed to new replies.

Advertisement