Newer
Older
Import / research / 3d-z-maps / procedural-editor / noise.cpp
/*
 * =====================================================================================
 *
 *       Filename:  noise.cpp
 *
 *    Description:  Various noise functions
 *
 *        Version:  1.0
 *        Created:  11/08/2011 20:51:00
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  John Ryland (jryland), jryland@xiaofrog.com
 *        Company:  InvertedLogic
 *
 * =====================================================================================
 */

#include <noise.h>
#include <math.h>

//
// ideas
//
//   fractal mountains - tessalation
//   procedural cities
//   procedural textures
//   procedural grass, trees / growth
//   procedrual waves
//   clouds
//   particles
//
//   the maskable angle/normal table
//   using the normal table to project spherical rays to make a sphere map for environment mapping
//
//   voxelizer using OpenGL to render Z-buffer at different angles and a put-voxel routine that
//   blends in the values as the view is changed. Perhaps use the normal table to add views.
//

vec3 Add(vec3 v1, vec3 v2)
{
    return vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}


float DotProduct(vec3 v1, vec3 v2)
{
    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}

float Length(vec3 v)
{
    return sqrt(DotProduct(v, v));
}

vec3& Normalize(vec3 v)
{
    float len = Length(v);
    if ( len )
    {
        float one_over_len = 1.0f / len;
        v.x *= one_over_len;
        v.y *= one_over_len;
        v.z *= one_over_len;
    }
    return v;
}

vec3 normalTable[1 << 16];

void initNormalTable()
{
    for (int i = 0; i < (1<<16); i++)
    {
        normalTable[i].x = 0;
        normalTable[i].y = 0;
        normalTable[i].z = 0;
    }
}

// I think the vectors shouldn't be expanded fully out to being normalized at first
// as the opposing vectors need to pass through the center and it doesn't work as
// well if they don't but could still kinda work


void recursiveBuildNormalTable(int i, int a, int b, int c, int depth)
{
    if ( depth >= 12 )
        return;

    depth += 3;

    int i1 = i + (1 << depth);
    int i2 = i + (2 << depth);
    int i3 = i + (3 << depth);
    int i4 = i + (0 << depth);

    normalTable[i1] = Normalize(Add(normalTable[a], normalTable[b]));
    normalTable[i2] = Normalize(Add(normalTable[a], normalTable[c]));
    normalTable[i3] = Normalize(Add(normalTable[b], normalTable[c]));

    recursiveBuildNormalTable(i4, a, i1, i2, depth);
    recursiveBuildNormalTable(i1, i1, i3, b, depth);
    recursiveBuildNormalTable(i2, i2, c, i3, depth);
    recursiveBuildNormalTable(i3, i3, i1, i2, depth);
}


void buildNormalTable()
{
    normalTable[0] = vec3( 0, 1, 0 );
    normalTable[1] = vec3( 0, -1, 0 );
    normalTable[2] = vec3( 0, 0, 1 );
    normalTable[3] = vec3( 0, 0, -1 );
    normalTable[4] = vec3( 1, 0, 0 );
    normalTable[5] = vec3( -1, 0, 0 );

    recursiveBuildNormalTable(0, 0, 2, 4, 0 );
    recursiveBuildNormalTable(1, 2, 5, 0, 0 );
    recursiveBuildNormalTable(2, 3, 4, 0, 0 );
    recursiveBuildNormalTable(3, 5, 0, 3, 0 );
    
    recursiveBuildNormalTable(4, 1, 2, 4, 0 );
    recursiveBuildNormalTable(5, 1, 2, 5, 0 );
    recursiveBuildNormalTable(6, 4, 1, 3, 0 );
    recursiveBuildNormalTable(7, 1, 3, 5, 0 );
}


float perlinNoise(float x, float y, float z)
{
    float a = 0.13f;
    float b = 0.23f;
    float c = 0.33f;
    float d = 0.43f;
    return x * a + y * b + z * c + d;
}


vec3 perlinNoise3(float x, float y, float z)
{
    float dNoise = perlinNoise(x, y, z);
    float dx = 0.213f;
    float dy = 0.123f;
    float dz = 0.133f;
    return vec3( dNoise / dx, dNoise / dy, dNoise / dz ); 
}


float noiseA(float x, float y, float z);
float noiseB(float x, float y, float z);
float noiseC(float x, float y, float z);