Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

878556 Posts in 32927 Topics- by 24337 Members - Latest Member: kellerx25

May 22, 2013, 07:07:46 AM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)Procedural Planetary Generation
Pages: 1 2 [3] 4 5 ... 10
Print
Author Topic: Procedural Planetary Generation  (Read 7754 times)
eigenbom
Level 10
*****



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 Email
« 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
*****



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 Email
« 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
*****



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 Email
« 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
*****



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 Email
« 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
*****



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

sean
Level 1
*



View Profile WWW Email
« 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

motorherp
Level 2
**



View Profile WWW Email
« Reply #40 on: May 08, 2012, 08:19:05 AM »

Heya sean and darestium, just for clarification, the method you describe where you normalise the vertices of the cube to get a sphere and the one you linked to on 'Maths Proof' aren't quite the same. 

Using a normalisation approach like you describe is the simplest way to map from a cube to a sphere but also results in a fair amount of warping.  What you'll find is that there will be a regions with a high density of verts on the resulting sphere which correspond to where the cube corners used to be, and regions with a low dnesity of verts which correspond to the faces.  The un-even distribution of vertices will result in a stretching of your textures when you then texture map the sphere.

The mapping equation given on 'Maths Proof' is slightly different. Its more like 'bending' the faces of the cube around a sphere and stretching the surface more evenly.  This results in a more even distribution of vertices on the resulting sphere and hence less texture warping.


@darestium - I've been working a bit here and there on some procedural space stuff myself in my spare time.  I'm not tackling the issue of generating planet terrain meshes like you are but you might find some of it useful or helpful anyway.  Take a look at the link in my sig if you're interested.
Logged

Hedgehodg
Level 1
*


...


View Profile Email
« Reply #41 on: May 09, 2012, 11:16:46 PM »

@motorherp Wow... You beast Tongue I just hope what I make looks as good as yours!

@eigenbom Okay, I've got this thus far (I've just started on it now been studying for tests and doing assignments Sad damn school getting in the way of my coding :D and just come back to this today...)



with the following code:

Code:
       private void ConstructHeightmap() {
            float[,] data = new float[100, 100];
            float frequency = 1;
            float amplitude = 8;

            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(x * 0.1f * frequency, y * 0.1f * frequency, 0) * amplitude;
                }
            }

            map = new Heightmap(data);
            mesh.ApplyHeightmap(map);
        }

oh, and I blew $60 AU on the book Smiley so I hope it arrives soon (I ordered it 4 days ago and it's coming from the UK). And by the way was does lacunarity mean exactly? FYI, I subscribed to the moonman feed Smiley looks like an awesome game, I will be sure to purchase it when you release it!
« Last Edit: May 09, 2012, 11:46:38 PM by darestium » Logged

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



View Profile WWW
« Reply #42 on: May 10, 2012, 12:19:14 AM »

And you're on your way! I think lacunarity is similar to fractal dimension.. but i could be wrong. it'll be in the book anyway. Tongue

and thx for following moonman. it'll be released .. one day... O_O
Logged

Hedgehodg
Level 1
*


...


View Profile Email
« Reply #43 on: May 10, 2012, 03:12:52 AM »

So right now you recommend that I just experiment with the noise functions (all of them together?) but how would I go about creating higher terrain in one place then the other? For example in the following screen shot everything is pretty much at the same height (used perlin + ridged):



But in the following image there are both slopes and "hills" and things based on different "levels":



How do I achieve with the terrain like the one directly above? Is it with the accumulation of ridged noise, e.g: you build the terrain with a mid amplitude low frequency noise, then you apply all the bumps with a high frequency very low amplitude noise? Any other advice would be much appreciated Wink
Logged

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



View Profile
« Reply #44 on: May 10, 2012, 06:39:46 AM »

Do a few passes with various scales? Example: generate terrain in 1024x1024 resolution, then subdivide it so that you have 4 smaller parts, then apply 1024x1024 terrain to each of the smaller parts. Then do it again for smaller parts. Something like that. Experiment with different scales etc.
Logged
Pages: 1 2 [3] 4 5 ... 10
Print
Jump to:  

Theme orange-lt created by panic