Jump to content
  • Advertisement
Sign in to follow this  
workingclass77

trouble mapping 3d noise to a sphere

This topic is 4864 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

ok, i've been struggling with this one for three or four days now, so its time to ask for some help. when generating a spherical texture with 3d perlin noise, i'm getting a wierd result that i can't figure out: http://img342.imageshack.us/my.php?image=noise0008ct.jpg mapped to a square, it looks like this: http://img342.imageshack.us/my.php?image=noise0013bf.jpg the code for generating the texture (well, the heightmap the texture is based on) is:
float * HeightMapGenerateSpherical (
    uint32  width, 
    uint32  height, 
    float   rangeMin,
    float   rangeMax,
    float * dest
) {
    assert(dest);
    assert(rangeMax >= rangeMin);
    
    const float  persistance    = 0.75f;
    const uint16 octaves        = 4;
    const float  initScale      = 1.0f;
    const uint32 seed           = (uint32)time(0);
    const float  range          = rangeMax - rangeMin;
    
    float * destPos = dest;
    for (uint32 y = 0; y < height; ++y) {
        for (uint32 x = 0; x < width; ++x) {
            float rotY = ((float)x / (float)width) * (2.0f * MATH_PI);
            float rotX = ((float)y / (float)height) * MATH_PI;
            
            float tX = -sin(rotX) * -sin(rotY);
            float tY =  cos(rotX);
            float tZ = -sin(rotX) *  cos(rotY);
                        
            tX += 1.0f;
            tY += 1.0f;
            tZ += 1.0f;
            
            tX /= 2.0f;
            tY /= 2.0f;
            tZ /= 2.0f;
            
            float noise = NoisePerlin3d(
                tX * initScale,
                tY * initScale,
                tZ * initScale,
                persistance,
                octaves,
                seed
            );
            
            
            noise += 1.0f;
            noise /= 2.0f;
            noise *= range;
            noise += rangeMin;
            
            *destPos = noise;
            ++destPos;
        }
    }
    
    return dest;
}




and the noise generator functions are:
float NoiseFixed3d (int32 x, int32 y, int32 z, uint32 seed) {
     int n = x + y * 57 + z * 139; 
     n     = (n << 13) ^ n; 
     return 1.0f - (seed * (n * (n * n * 15731 + 789221) + 1376412589) & 0x7FFFFFFF) / 1073741824.0f; 
}

float NoiseInterpolated3d (float x, float y, float z, uint32 seed) {
    int   intX = (int) x;
    int   intY = (int) y;
    int   intZ = (int) z;
    
    float fraX = x - intX;
    float fraY = y - intY;
    float fraZ = z - intZ;
    
    float v1 = NoiseFixed3d(intX,     intY,     intZ, seed);
    float v2 = NoiseFixed3d(intX + 1, intY,     intZ, seed);
    float v3 = NoiseFixed3d(intX,     intY + 1, intZ, seed);
    float v4 = NoiseFixed3d(intX + 1, intY + 1, intZ, seed);
    
    float v5 = NoiseFixed3d(intX,     intY,     intZ + 1, seed);
    float v6 = NoiseFixed3d(intX + 1, intY,     intZ + 1, seed);
    float v7 = NoiseFixed3d(intX,     intY + 1, intZ + 1, seed);
    float v8 = NoiseFixed3d(intX + 1, intY + 1, intZ + 1, seed);
    
    float i1 = Lerp(v1, v2, fraX);
    float i2 = Lerp(v3, v4, fraX);
    float i3 = Lerp(v5, v7, fraX);
    float i4 = Lerp(v6, v8, fraX);
    
    float i5 = Lerp(i1, i2, fraY);
    float i6 = Lerp(i3, i4, fraY);
    
    return Lerp(i5, i6, fraZ);
}

float NoisePerlin3d (
    float   x, 
    float   y, 
    float   z, 
    float   persistance, 
    uint8   octaves, 
    uint32  seed
) {
    float noise     = 0.0f;
    float frequency = 1.0f;
    float amplitude = 1.0f;
    
    for (uint8 i = 0; i < octaves; ++i) {
        noise += NoiseInterpolated3d(x * frequency, y * frequency, z * frequency, seed) * amplitude;
        
        frequency *= 2.0f;
        amplitude *= persistance;
    }
    
    if (noise > 1.0f)
        noise = 1.0f;
    else if (noise < -1.0f)
        noise = -1.0f;
    
    return noise;
}




if anyone can help me out here, i would be most grateful. thanks. oh, and i don't use forums very often at all, so i don't know how to make those url's into links or to show the images directly in the post. also, the sphere i'm using is just one generated by gluSphere right now, before anyone asks. i'm going to replace it with a different algorithm probably, but i'm just trying to get this noise stuff working right now. [Edited by - workingclass77 on July 22, 2005 12:57:53 PM]

Share this post


Link to post
Share on other sites
Advertisement
I can't see the pictures you posted so I can't tell what the problem really is. I'm not sure if this is the case, but ugly distortions at the "poles" is caused by using sphere mapping. I use cube mapping to solve this and it has the added benifit of being easy to texture procedurally.

For each "side" of the cube
Loop through all texels
Take the U,V of the texel as X,Y and 1/2 Texture size as Z of a vector
(note that what you use for U,V changes with each "side")
Make this a unit vector (length of 1, makes the cube a sphere)
Use the vector as the input to your 3D noise function
Convert noise output to a color and write to texture

Of course you may be stuck with spherical mapping with your current system in which case I would suggest looking very hard at the trig functions you use to map the texure space coordinates to object space coordinates and how the sphere's vertices are mapped to the texture.

Share this post


Link to post
Share on other sites
You can use HTML img tags if your hosting server allows it... or just links:

clicky
clicky2

Looks like your interpolation doesn't work correctly, but you didn't post the code to the "lerp" function so I can't see if the problem is there (my first guess). At a glance the rest of the code seems OK.

Share this post


Link to post
Share on other sites
Actually, on a closer look.. this is wrong:

float i3 = Lerp(v5, v7, fraX);
float i4 = Lerp(v6, v8, fraX);

i3 should be interpolated betwee v5->v6, i4 should be v7->v8.

Share this post


Link to post
Share on other sites
Quote:

Actually, on a closer look.. this is wrong:

float i3 = Lerp(v5, v7, fraX);
float i4 = Lerp(v6, v8, fraX);

i3 should be interpolated betwee v5->v6, i4 should be v7->v8.


changing that fixed part of the image...notice anything else like that? that corrected about 1/4 of the texture. that was just a typo there...hate when thats the problem

oh, and my lerp is:

float Lerp (float a, float b, float x) {
return a * (1.0f - x) + b * x;
}



1 octave:
Image Hosted by ImageShack.us

3 octaves:
Image Hosted by ImageShack.us

5 octaves:
Image Hosted by ImageShack.us

Share this post


Link to post
Share on other sites
actually, disregard that, i was passing negative values in by accident...your fix to my NoiseInterpolated3d() function works perfectly. awesome. thanks.

Share this post


Link to post
Share on other sites
No problem.. The "x - (int)x" is potentially dangerous as you found out. You should use the floor() function instead of casting to int. It should always round down correctly (as in floor(-2.5) == -3.0) so it won't break down when you pass zero.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!