Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411490 Posts in 69371 Topics- by 58428 Members - Latest Member: shelton786

April 24, 2024, 09:11:26 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Procedural Planetary Generation
Pages: 1 [2] 3 4 ... 8
Print
Author Topic: Procedural Planetary Generation  (Read 25347 times)
fentlewoodlewix
Level 1
*


View Profile WWW
« Reply #20 on: May 02, 2012, 06:26:16 AM »

If you take a subdivided cube (like a wireframe rubics cube but it works for any levels of subdivision) and assuming the vectors representing the vertices are from the centre, normalise them, you will get a sphere.
Oh god, so simple? :D

yup works with any shape, (try it on a teapot!)
the shape you choose varies the distribution of points over the sphere, so if you do choose a teapot, you may get more verts in some places than others.

normalise basically makes all points the same distance from the centre, i.e. spherical.
Logged
rivon
Level 10
*****



View Profile
« Reply #21 on: May 02, 2012, 09:58:17 AM »

Yeah, I understand how it works. It's just that it's so simple. I would never have thought there is so easy way to do this.
Logged
Hedgehodg
Level 1
*


...


View Profile
« Reply #22 on: May 03, 2012, 02:03:07 AM »

Wow, Thanks for all the posts!

Sean, are you saying that I should create a tessellating triangle rather then a tessellating quad in the case that I go with "An Example: Building an Icosahedron" since applying a quad to a triangle seems like quite an impossible task. However, from what I have read, most seem to use a cube to sphere algorithm of sorts, the planet noise is initially generated on a 6 sided cube (assumption), then when the user gets further away from the cube, it slowly morphs into a sphere. But if you recommend your away I would gladly implement it. And what do you mean with your initial post? :3

Eigenbom, would you recommend that I implement fbm, perlin and ridged multi-fractal noise (RMN)? Or just one of them, I've got a Java version of the RMN and pasted it into my C# project, and tested it against a basic mesh supporting a height-map. It seems to produce similar results to Perlin noise - what is the difference? Here is what I used: http://www.hayles.demon.co.uk/perlin/ridgedmf.html. In addition, how would I apply the RMN to the tessellating quad? It is easy enough with a height-map-mesh-thing since there are always the same amount of vertices, but I don't see how I can do it with the quad.

Logged

Previously known as "darestium"...
fentlewoodlewix
Level 1
*


View Profile WWW
« Reply #23 on: May 03, 2012, 03:16:59 AM »


Sean, are you saying that I should create a tessellating triangle rather then a tessellating quad in the case that I go with "An Example: Building an Icosahedron" since applying a quad to a triangle seems like quite an impossible task.

i wouldnt attempt to take your quad noise mesh and apply it to a triangle. The example is meant to show there is more than one approach.

A triangle can be subdivided by adding a new vert at the middle of each edge and joining the old and new verts edges to  make 4 new smaller ones.



(from) http://www.rhythm.com/~ivan/dispMap.html

Now those triangles can be the triangles that make up the surface of a sphere.



(from) http://www.skofnunggames.com/?p=4

If you add an additional pseudo-random offset to the length of the vector representing each new each time you subdivide then you end up with a landscape.

With the spherical approach you can add  the pseudo-random (perlin or whatever you like) noise to the length of the vectors that represent these new verts.

Hey, i just found this... http://www.unifycommunity.com/wiki/index.php?title=MeshSubdivision

However, from what I have read, most seem to use a cube to sphere algorithm of sorts, the planet noise is initially generated on a 6 sided cube (assumption), then when the user gets further away from the cube, it slowly morphs into a sphere.

I dont think they generally morph between cube and sphere as you approach, but that the sphere/cube issue is one of the steps to get your quad patches onto the surface of a sphere.

But if you recommend your away I would gladly implement it.

I recommend finding an open source project that has already implemented it and using the code. ;-)
I used this approach for an elite space trading thing i was working on a few years back worked for me as i wasnt going to do any texturing and wanted all wireframe & flat triangles for that retro look.

And what do you mean with your initial post? :3

I'm not sure how low level to take it but basically if you have a mesh described by vectors measured from the centre. Or in other words a mesh at/around the origin. Then you apply the Normalise function (divide each vector by its length) to each of the vectors describing the verts. Now each of these vectors has a length of 1.0. Try it.



(from) http://mathproofs.blogspot.co.uk/2005/07/mapping-cube-to-sphere.html
Logged
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #24 on: May 03, 2012, 03:47:30 PM »

I personally wouldn't just copy/paste, except for the perlin_noise() function. I only suggest noise -> fbm -> ridged multifractal because you can incrementally build up one after the other. Terrain functions (as are most procedural methods) are very difficult to tune to get what you want, so I'd take my time with this step.

Ridged multi-fractal noise has a lot of fine detail, so if you're applying it to a coarse meh, then it will probably look like any other method. Try applying it to a really fine mesh. You will have to tweak the various parameters until you get something worthwhile..

Oh btw, I dug up some procedural stuff I did 6 years ago, pretty crappy texturing, but I was just learning computer graphics at that stage! Tongue

Logged

Hedgehodg
Level 1
*


...


View Profile
« Reply #25 on: May 03, 2012, 11:41:47 PM »

Wow! That looks completely awesome! Smiley So, I would prefer to go with the method using tessellating quads rather then triangles for no other reason then I think it makes more sense in my head that way. But how would I apply the noise to the quad and how do I apply the quad to the sphere? Any suggestions? Also, when you say "I only suggest noise -> fbm -> ridged multifractal because you can incrementally build up one after the other." does that mean I can mix them together?  Undecided
Logged

Previously known as "darestium"...
Fallsburg
Level 10
*****


Fear the CircleCat


View Profile
« Reply #26 on: May 04, 2012, 05:02:57 AM »

Well, I'd recommend not worrying about the sphere, for now.

For instance,
The highest mountain on Earth is 8.8 km and the Earth's radius is ~6371 km.
A billiard ball's radius is 2.25 in and by regulation can't have any marring of more than 0.005 in.

This means that the maximum perturbation on Earth is 0.1381% of the radius and on a billiard ball is 0.2222%. So the Earth is ~63% as bumpy as a billiard ball.

So, I'd suggest getting a heightmap working with perlin (or some other noise) on a flat plane.  Only when you have that would I worry about mapping that on to a sphere.

To do that, I'd recommend looking into geodesy.  There are quite a few wikipedia articles on geodesy that might help you out, but basically, you are going to want to have work in a couple of coordinate systems for convenience.
I'd recommend thinking of your height maps as Lon/Lat/Alt and then converting them to ECEF (Earth-Centered, Earth-Fixed) or ECI (Earth-Centered Inertial).
Logged
Hedgehodg
Level 1
*


...


View Profile
« Reply #27 on: May 04, 2012, 03:37:27 PM »

Sean, regarding your initial post, are you saying if I make a cube out of the quads and I just normalise each vertex I get a sphere? and could you please explain the following: "assuming the vectors representing the vertices are from the centre, normalise them, you will get a sphere." but I don't see how that works...
Logged

Previously known as "darestium"...
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #28 on: May 04, 2012, 03:43:29 PM »

But how would I apply the noise to the quad and how do I apply the quad to the sphere? Any suggestions?

The terrain function just perturbs the vertices of the quad. To do this (in general) you need (a) the "coordinates" of the vertex, and (b) the normal of the vertex. In a 2-d plane, the coordinates can just be the absolute coordinates of the vertex, and the normal is "up".

So in that case (assuming Y is up), your perturb function would be something like...
Code:
function perturb(v)
  v.pos += vec3(0,1,0) * terrain(v.x,v.z)
end

And your "terrain" function might be...
Code:
function terrain(x,y)
  return abs(noise(x,y))
end

When mapped to a sphere, the coordinates could be either the absolute 3D coordinates or planet local coordinates e.g., (latitude,longitude). Probably the absolute coords would be easiest, but then you need a terrain function that acts on 3d coords. The normal of the vertex on a sphere is the vector pointing attaching the center of the sphere to the vertex. But again, I'd leave this until you show us some awesome terrain acting on a 2d plane..

Quote
Also, when you say "I only suggest noise -> fbm -> ridged multifractal because you can incrementally build up one after the other." does that mean I can mix them together?  Undecided

well noise is the basic building block. fbm justs sums a bunch of noise functions. and ridge multifractal also sums a bunch of noises, but in a more complex way.

If you want to really investigate this area, I'd start with a noise function, then trying different ways to use it, e.g.,

Code:
function my_terrain_1(x,y,z)
  return abs(noise(x,y,z))
end

function my_terrain_2(x,y,z)
  return noise(2*x,y+sin(x),z)
end

function my_terrain_3(x,y,z)
  float val = 0
  for(int i=0;i<4;i++)
    val = noise(x,y,z) * pow(2,-i)
  return val
end

Each of these should have "different" characteristics.

And definitely you can combine functions. A good trick is to have a bunch of different terrain functions, e.g., RockyMountain, Desert, and Plains, and combine them in different ways, so you have a desert region in one part of the map that morphs into mountains in another part, and so on...

Logged

Hedgehodg
Level 1
*


...


View Profile
« Reply #29 on: May 04, 2012, 06:58:48 PM »

Ok, sounds like a good idea. I'll take your advice and play with some noise functions Wink. Could you recommend and good implementations of Perlin/Simplex Noise? I've read the following http://freespace.virgin.net/hugo.elias/models/m_perlin.htm and found I quite interesting :)But there appears to be little C# examples of a perlin noise module. And so I guess I'll start out with 2D noise?

So, like you said I'll just have to play with it until I get the type of functions that I want i.e if I want a function makes the terrain more like the moon (craters), or one that is more mountainous, etc?
« Last Edit: May 04, 2012, 07:46:11 PM by Darestium » Logged

Previously known as "darestium"...
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #30 on: May 04, 2012, 10:21:36 PM »

A reference implementation of Perlin noise is on Ken Perlin's own site. If you're able to adapt that to c# then you're on your way.

Understanding how Perlin noise works takes a few more brain cycles. Perlin wrote up a presentation explaining it, but the Texturing & Modelling book I referenced above does a much better job at describing a number of different noise functions, including Perlin noise. But you don't really need to know how it works to use it.

Yes, have a play, you learn through play. Gomez If you get frustrated, maybe download a demo of one of the more advanced terrain generators out there, like Terragen, and see if your can reverse engineer their terrain defaults. Likely they'll use the same names for parameters, like lacunarity which is used in a lot of fractal noise functions ..

Also I don't know anything about Simplex noise. Smiley
Logged

Hedgehodg
Level 1
*


...


View Profile
« Reply #31 on: May 05, 2012, 12:09:07 AM »

Cool beans, just ported the class to c#:

Code:
public class PerlinNoise {
        private static int[] permutation = new int[] { 151,160,137,91,90,15,
           131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
           190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
           88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
           77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
           102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
           135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
           5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
           223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
           129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
           251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
           49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
           138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
        };

        private static int[] p = new int[512];

        public static void Initialize() {
            for (int i = 0; i < 256; i++) {
                p[256 + i] = p[i] = permutation[i];
            }
        }

        public static double Noise(double x, double y, double z) {
            // Find unit cube that contains point
            int X = (int)Math.Floor(x) & 255;
            int Y = (int)Math.Floor(y) & 255;
            int Z = (int)Math.Floor(z) & 255;

            // Find relative X, Y, Z of point in Cube
            x -= Math.Floor(x);
            y -= Math.Floor(y);
            z -= Math.Floor(z);

            // Compute fade curves for each of X, Y, Z
            double u = Fade(x);
            double v = Fade(y);
            double w = Fade(z);

            // Hash coordinates of the 8 cube corners
            int A = p[X] + Y;
            int AA = p[A] + Z;
            int AB = p[A + 1] + Z;
            int B = p[X + 1] + Y;
            int BA = p[B] + Z;
            int BB = p[B + 1] + Z;

            // And add blended results from 8 corners of cube
            return Lerp(w, Lerp(v, Lerp(u, Grad(p[AA], x, y, z),
                                     Grad(p[BA], x - 1, y, z)),
                             Lerp(u, Grad(p[AB], x, y - 1, z),
                                     Grad(p[BB], x - 1, y - 1, z))),
                     Lerp(v, Lerp(u, Grad(p[AA + 1], x, y, z - 1),
                                     Grad(p[BA + 1], x - 1, y, z - 1)),
                             Lerp(u, Grad(p[AB + 1], x, y - 1, z - 1),
                                     Grad(p[BB + 1], x - 1, y - 1, z - 1))));
        }

        private static double Fade(double t) {
            return t * t * t * (t * (t * 6 - 15) + 10);
        }

        private static double Lerp(double t, double a, double b) {
            return a + t * (b - a);
        }

        private static double Grad(int hash, double x, double y, double z) {
            // Convert LO 4 bits of hash code
            int h = hash & 15;
           
            // Into 12 Gradient directions
            double u = h < 8 ? x : y;
            double v = h < 4 ? y : h == 12 || h == 14 ? x : z;

            return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
        }
    }

So you recommend that I purchase the book? Wizard And I can just use that Noise function to offset points on my terrain? No additional coding required?
« Last Edit: May 05, 2012, 12:18:16 AM by Darestium » Logged

Previously known as "darestium"...
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #32 on: May 05, 2012, 01:31:34 AM »

It's a great book, written by some of the pioneers of procedural terrain and texturing.

Yep, you can now use the PerlinNoise::noise(x,y,z) as the basis for your terrain displacement..
Logged

Hedgehodg
Level 1
*


...


View Profile
« Reply #33 on: May 05, 2012, 07:20:30 PM »

I am a n00b when it comes to noise... So this may sound like a n00by question but... Why does the Noise function always return 0f? And how would I implement extra parameters in the Noise function (persistence, amplitude, and frequency)?

And, by the way, just checked out your game... It looks awesome Smiley I'm from Australia too Cool
Logged

Previously known as "darestium"...
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #34 on: May 05, 2012, 10:56:52 PM »

By the look of that code, I think you need to call Initialize() when the program starts .. before you call Noise.

You have to think of Noise(x,y,z) as a black box, you give it an x,y,z and it returns a value (probably in the range -1 to 1). If you want a higher 'amplitude' just multiply the result. If you want to increase the frequency, then call Noise(A*x,A*y,A*z), where A scales your domain.. (e.g, A=2 will give you noise of twice the frequency.)

Persistence - I don't know what you mean by that.

cheers cobber Wink
Logged

Hedgehodg
Level 1
*


...


View Profile
« Reply #35 on: May 05, 2012, 11:41:10 PM »

Oh, lol, I wrote that function and didn't call it Facepalm (in the Java version it is called automatically, but I had to put it in a function for the c# version because c# is silly). I have also decided to purchase the book Smiley I sure hope it's not too technical for me (I'm in year 9 and still haven't done trigonometry yet Sad )

Update: Just tried calling the init function, applying amplitude and frequency to the function, and scaling the result - it still returns 0f. Maybe I made an error when porting it... Oh, and is using multiple octaves for perlin noise necessary? If so how would I implement it?

Thanks Mate Wink
« Last Edit: May 06, 2012, 12:34:25 AM by darestium » Logged

Previously known as "darestium"...
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #36 on: May 06, 2012, 02:37:39 PM »

Year 9? hmm, in that case ..  the book may be too mathematical in places, but it has lots of code snippets too .. still, it's a good investment, and as the years go by you'll start to understand more and more of it. Wink

I'm curious, does the following (C# equivalent) code print out 0? (it shouldn't)
Code:
PerlinNoise::Initialize();
print(PerlinNoise::Noise(.5,.5,.5));




Logged

Hedgehodg
Level 1
*


...


View Profile
« Reply #37 on: May 06, 2012, 11:42:27 PM »

How curious it prints out -0.25, so it *must* be doing something.

Code:
            PerlinNoise.Initialize();

            Console.WriteLine(PerlinNoise.Noise(0.5, 0.5, 0.5));

I tried the same with the following:

Code:
            float[,] data = new float[100, 100];
            float frequency = 1;
            float amplitude = 1;

            PerlinNoise.Initialize();

            for (int x = 0; x < data.GetLength(0); x++) {
                for (int y = 0; y < data.GetLength(1); y++) {
                    data[x, y] = (float)PerlinNoise.Noise(8 * frequency, 8 * frequency, 8 * frequency) * amplitude;

                    Console.WriteLine(data[x, y]);
                }
            }

It printed out  10,000 '0's Smiley I tried replacing the '8' with 0.5 and, like the above it printed out (10,000) -0.25
Logged

Previously known as "darestium"...
eigenbom
Level 10
*****


@eigenbom


View Profile WWW
« Reply #38 on: May 07, 2012, 12:11:30 AM »

Oh I see. Perlin Noise is zero at every integer coordinate. So the following will print 0 ...

noise(1,2,1)
noise(0,0,0)
noise(0,1,1001)
noise(-1,0,9999999)

You should sample this function between 0 and 1. So if you have terrain that is 100 vertices wide, with vertices at x=0, x=1, ..., x=99, then call it like this:

noise(x*0.01,y*0.01,0)

After you've done that, you'll get maybe one or two "hills". You can call that the base "frequency" (the lowest frequency). Then you can scale the domain again to get more hills ... (e.g., A=4 might give you around 16 hills...)

noise(A*x*0.01,A*y*0.01,0)


Logged

fentlewoodlewix
Level 1
*


View Profile WWW
« Reply #39 on: May 07, 2012, 06:26:21 AM »

Sean, regarding your initial post, are you saying if I make a cube out of the quads and I just normalise each vertex I get a sphere? and could you please explain the following: "assuming the vectors representing the vertices are from the centre, normalise them, you will get a sphere." but I don't see how that works...

you already know that normalise returns a vector with the same direction but a length of 1.0.
this means that all the vectors now point to a place within 1.0 units of the origin.



(from, http://www.mathworks.com/matlabcentral/fileexchange/36248-normalize-n-d-vectors-in-single-matrix-or-n-component-matrices)

if your cube is made of vectors that point to places away from the origin all on one side, say (1, 10, 10), (1, 10, 10), (10, 1, 10), (10, 10, 1) etc.  The normalise function will squish them and shorten them so they all have the same length, but they will all still be on the same side and though they will be on the surface of a sphere, they wont nicely describe a complete sphere



Logged
Pages: 1 [2] 3 4 ... 8
Print
Jump to:  

Theme orange-lt created by panic