Planet Generation Question
I am doing a project for a Computer Graphics course at Uni and want to create a procedurally generated planet using Perlin Noise for creating the terrain.
I've been able to get a basic terrain generator working with a basic 3D function for height values, just for the time being.
pow(cos(x/4) + cos(z/4), 3)/2
I am not sure how best to go about mapping this to a sphere. I'm open to suggestions. I was thinking about using Quaternions to rotate each of the vertexes around a central point (i.e the planet origin), but I'm not sure if this will be the easiest and best solution. I have tried to find resources about how best to do it but have come up empty. If anyone knows a decent detailed tutorial please post a link. Any other suggestions or criticism is welcome. Oh and I know I have issues with my normals which is not as big a concern right now as mapping the terrain to a sphere, since I know what the problem is, just haven't gotten around to fixing it yet.
Thanks in advance!
P.S. I'm using opengl with glut as the graphics api and windowing system.
Have a look at libnoise: http://libnoise.sourceforge.net
The author of that library generates spherical noise by generating it in 3 dimensions (X, Y, Z) then sampling it through spherical coordinates.
The author of that library generates spherical noise by generating it in 3 dimensions (X, Y, Z) then sampling it through spherical coordinates.
Well, the above link just goes to the libnoise project that generates the heightmap for the planet. I have developed a rather extensive planetary rendering system which has a paging / LOD system. However I cannot release it due to it being part of a commercial project :(
I can, however, give you some tip / pointers on how to generate a fully 3D planet from heightmaps.
The basic premise is that you take 6 heightmaps and apply them to each of the 6 sides of a 3D cube. The cube is then deformed to fit the round shape of the planet. It is then further divided into pages and different LOD's.
As for the math that "spherizes" the cube I'll try to explain it here as best as I can.
First you have your vector which contains the 3D point on the cube (you can setup a series of loops to iterate through each side and all of the vertices on the grids for each side).
vPoint
You then scale that point by the inverse of half vertex width (aka x or y dimension of the heightmap). Which means 1/(X/2) and is represented here as dInvHalfWidth.
vPoint *= dInvHalfWidth;
The next set of equations get the squares and half the squares of each axis of the vector.
const double dX2 = vPoint.x * vPoint.x;
const double dY2 = vPoint.y * vPoint.y;
const double dZ2 = vPoint.z * vPoint.z;
const double dX2Half = dX2 * 0.5;
const double dY2Half = dY2 * 0.5;
const double dZ2Half = dZ2 * 0.5;
The last set of equations are what actually spherize the vector. The math that results in these equation is rather complex so don't ask me to try and explain it (also because I can't even remember all the math :P )
vPoint.x *= Sqrt(1-(dY2Half)-(dZ2Half)+((dY2 * dZ2) * (1.0f / 3.0f)));
vPoint.y *= Sqrt(1-(dZ2Half)-(dX2Half)+((dZ2 * dX2) * (1.0f / 3.0f)));
vPoint.z *= Sqrt(1-(dX2Half)-(dY2Half)+((dX2 * dY2) * (1.0f / 3.0f)));
That being said, this code plus the link in the above post should get you started.
I can, however, give you some tip / pointers on how to generate a fully 3D planet from heightmaps.
The basic premise is that you take 6 heightmaps and apply them to each of the 6 sides of a 3D cube. The cube is then deformed to fit the round shape of the planet. It is then further divided into pages and different LOD's.
As for the math that "spherizes" the cube I'll try to explain it here as best as I can.
First you have your vector which contains the 3D point on the cube (you can setup a series of loops to iterate through each side and all of the vertices on the grids for each side).
vPoint
You then scale that point by the inverse of half vertex width (aka x or y dimension of the heightmap). Which means 1/(X/2) and is represented here as dInvHalfWidth.
vPoint *= dInvHalfWidth;
The next set of equations get the squares and half the squares of each axis of the vector.
const double dX2 = vPoint.x * vPoint.x;
const double dY2 = vPoint.y * vPoint.y;
const double dZ2 = vPoint.z * vPoint.z;
const double dX2Half = dX2 * 0.5;
const double dY2Half = dY2 * 0.5;
const double dZ2Half = dZ2 * 0.5;
The last set of equations are what actually spherize the vector. The math that results in these equation is rather complex so don't ask me to try and explain it (also because I can't even remember all the math :P )
vPoint.x *= Sqrt(1-(dY2Half)-(dZ2Half)+((dY2 * dZ2) * (1.0f / 3.0f)));
vPoint.y *= Sqrt(1-(dZ2Half)-(dX2Half)+((dZ2 * dX2) * (1.0f / 3.0f)));
vPoint.z *= Sqrt(1-(dX2Half)-(dY2Half)+((dX2 * dY2) * (1.0f / 3.0f)));
That being said, this code plus the link in the above post should get you started.
I used triangle subdivision when I made an asteroid/planet generator. I start with a regular octahedron and subdivide each edge (this divides each face into four new faces), then normalize the new vertices based on the average "height" of its parent edge from the artificial "center" of the planet, and add/subtract a random height value.
This is the same general idea as plasma-style fractal heightfields.
I'm not sure if this would be compatible with your noise function or not.
The last thing I was trying to do was somehow keep deterministic random seeds in such a way that I could generate only a subset of the planet (the part that the player would be able to see) without having to generate everything the player couldn't see. I lost interest and focused on other projects since then.
This is the same general idea as plasma-style fractal heightfields.
I'm not sure if this would be compatible with your noise function or not.
The last thing I was trying to do was somehow keep deterministic random seeds in such a way that I could generate only a subset of the planet (the part that the player would be able to see) without having to generate everything the player couldn't see. I lost interest and focused on other projects since then.
Quote:Original post by chessmaster42This, and the post before it about mapping a square to a circle, has the derivation of the equation if anyone is interested.
...
The math that results in these equation is rather complex so don't ask me to try and explain it (also because I can't even remember all the math :P )
...
if you apply a heightmap to a sphere, you should really use a geodesic sphere rather than a traditional sphere since in a geodesic sphere triangles are all pretty much the same size which gives much nicer results when a heightmap is applied - detail is constant rather than it being extremely detailed at the poles, and un-detailed in comparison at the equator.
I did this myself a while back, writing my own functions to generate the geodesic sphere and perlin noise and applying it with normal calculations for triangle vertices etc, worked rather nicely.
http://www.ngup.net/view?file=528
no texturing just a brown coloured darkened via slope calculated from normal
I did this myself a while back, writing my own functions to generate the geodesic sphere and perlin noise and applying it with normal calculations for triangle vertices etc, worked rather nicely.
http://www.ngup.net/view?file=528
no texturing just a brown coloured darkened via slope calculated from normal
Hi
Im currently trying some Procedural modeling but having a hard time wrapping my head around the theory, mainly making spheres. Ive made a procedural cube using vertex and index arrays but I want to extend this to make a procedural sphere and make it woble/morph a bit in-game. Does anyone have any good links that explains the basics of it? I had a look at 'Kalidor' link but more help would be appreciated.
Thanks
Im currently trying some Procedural modeling but having a hard time wrapping my head around the theory, mainly making spheres. Ive made a procedural cube using vertex and index arrays but I want to extend this to make a procedural sphere and make it woble/morph a bit in-game. Does anyone have any good links that explains the basics of it? I had a look at 'Kalidor' link but more help would be appreciated.
Thanks
Quote:Original post by luca-deltodesco
if you apply a heightmap to a sphere, you should really use a geodesic sphere rather than a traditional sphere since in a geodesic sphere triangles are all pretty much the same size which gives much nicer results when a heightmap is applied - detail is constant rather than it being extremely detailed at the poles, and un-detailed in comparison at the equator.
My method doesn't generate a traditional sphere and it's not a geodescic sphere either. It's very odd looking but it works great. Here's a screenshot of a test I did in an earlier version. It shows the paging / LOD systems when I first started them:
As you can see it takes 6 maps and seamlessly morphs them to a perfect sphere. There is a very slight distortion at the seams but it is quite negligible in practice. Plus the grid nature means that heightmaps are very easy to apply.
[Edited by - chessmaster42 on February 21, 2008 12:13:32 AM]
This might be helpful : http://glprogramming.com/red/chapter02.html
See Examples 2-13 to 2-18, search for "Building an Icosahedron".
See Examples 2-13 to 2-18, search for "Building an Icosahedron".
Quote:Original post by chessmaster42
As you can see it takes 6 maps and seamlessly morphs them to a perfect sphere. There is a very slight distortion at the seams but it is quite negligible in practice. Plus the grid nature means that heightmaps are very easy to apply.
This technique tends to be named 'exploded cube', seeing as you subdivide and raise to radius the cube faces. I think Ysaneya's engine uses the same.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement