optimizations, a few more interfaces

This commit is contained in:
David Rose 2006-01-04 00:31:00 +00:00
parent ac1a7e272e
commit 8cef27663e
15 changed files with 506 additions and 91 deletions

View File

@ -25,7 +25,8 @@
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise::
fade(double t) {
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
// return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
return (3.0 - 2.0 * t) * t * t;
}
////////////////////////////////////////////////////////////////////

View File

@ -33,9 +33,21 @@ bool PerlinNoise::_got_first_seed = false;
PerlinNoise::
PerlinNoise(int table_size, unsigned long seed) :
_table_size(table_size),
_table_size_mask(table_size - 1),
_mersenne(seed != 0 ? seed : get_next_seed())
{
// The _index table is just a randomly shuffled index.
// It is necessary for _table_size to be a power of 2.
#ifndef NDEBUG
if (_table_size != 0) {
bool table_size_power_2 = ((_table_size ^ _table_size_mask) == (_table_size + _table_size_mask));
nassertd(table_size_power_2) {
_table_size = 0;
_table_size_mask = 0;
}
}
#endif // NDEBUG
// The _index table is just a randomly shuffled index
// table.
_index.reserve(_table_size * 2);
int i;
@ -56,3 +68,32 @@ PerlinNoise(int table_size, unsigned long seed) :
_index.push_back(_index[i]);
}
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::Copy Constructor
// Access: Protected
// Description: Makes an exact copy of the existing PerlinNoise
// object, including its random seed.
////////////////////////////////////////////////////////////////////
PerlinNoise::
PerlinNoise(const PerlinNoise &copy) :
_table_size(copy._table_size),
_table_size_mask(copy._table_size_mask),
_mersenne(copy._mersenne),
_index(copy._index)
{
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise::Copy Assignment Operator
// Access: Protected
// Description: Makes an exact copy of the existing PerlinNoise
// object, including its random seed.
////////////////////////////////////////////////////////////////////
void PerlinNoise::
operator = (const PerlinNoise &copy) {
_table_size = copy._table_size;
_table_size_mask = copy._table_size_mask;
_mersenne = copy._mersenne;
_index = copy._index;
}

View File

@ -34,6 +34,8 @@
class EXPCL_PANDA PerlinNoise {
protected:
PerlinNoise(int table_size, unsigned long seed);
PerlinNoise(const PerlinNoise &copy);
void operator = (const PerlinNoise &copy);
INLINE static double fade(double t);
INLINE static double lerp(double t, double a, double b);
@ -49,6 +51,7 @@ PUBLISHED:
protected:
int _table_size;
int _table_size_mask;
Mersenne _mersenne;
static Mersenne _next_seed;

View File

@ -17,6 +17,49 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::Default Constructor
// Access: Published
// Description: The default constructor makes an invalid PerlinNoise2
// object. You must at least pass in a scale of each
// dimension.
//
// This constructor exists only so you can create a
// temporary placeholder PerlinNoise2 object, and later
// fill it in with the assignment operator.
////////////////////////////////////////////////////////////////////
INLINE PerlinNoise2::
PerlinNoise2() :
PerlinNoise(0, 1)
{
_input_xform.fill(0.0f);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::Copy Constructor
// Access: Published
// Description: Makes an exact copy of the existing PerlinNoise
// object, including its random seed.
////////////////////////////////////////////////////////////////////
INLINE PerlinNoise2::
PerlinNoise2(const PerlinNoise2 &copy) :
PerlinNoise(copy),
_input_xform(copy._input_xform)
{
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::Copy Assignment Operator
// Access: Published
// Description: Makes an exact copy of the existing PerlinNoise
// object, including its random seed.
////////////////////////////////////////////////////////////////////
INLINE void PerlinNoise2::
operator = (const PerlinNoise2 &copy) {
PerlinNoise::operator = (copy);
_input_xform = copy._input_xform;
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::noise
// Access: Published
@ -37,6 +80,36 @@ noise(const LVecBase2f &value) {
return (float)noise(value[0], value[1]);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::operator ()
// Access: Published
// Description: Returns the noise function of the two inputs.
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise2::
operator ()(double x, double y) {
return noise(x, y);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::noise
// Access: Published
// Description: Returns the noise function of the two inputs.
////////////////////////////////////////////////////////////////////
INLINE float PerlinNoise2::
operator ()(const LVecBase2f &value) {
return noise(value);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::noise
// Access: Published
// Description: Returns the noise function of the two inputs.
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise2::
operator ()(const LVecBase2d &value) {
return noise(value);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::grad
// Access: Private, Static
@ -46,8 +119,22 @@ noise(const LVecBase2f &value) {
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise2::
grad(int hash, double x, double y) {
// Convert lo 3 bits of hash code into 8 gradient directions.
// Convert low 3 bits of hash code into 8 gradient directions.
switch (hash & 7) {
// Four corners.
case 0: return x + y;
case 1: return x - y;
case 2: return -x + y;
case 3: return -x - y;
int h = hash & 7;
return _grad_table[h].dot(LVector2d(x, y));
// Four edges. Here we scale by 1.707 to make all the vectors equal
// length, and to make their lengths consistent with PerlinNoise3.
case 4: return 1.707 * x;
case 5: return 1.707 * y;
case 6: return -1.707 * x;
case 7: return -1.707 * y;
}
nassertr(false, 0);
return 0;
}

View File

@ -19,21 +19,6 @@
#include "perlinNoise2.h"
#include "cmath.h"
LVector2d PerlinNoise2::_grad_table[8] = {
// Four corners.
LVector2d(1, 1),
LVector2d(1, -1),
LVector2d(-1, 1),
LVector2d(-1, -1),
// Four edges. Here we scale by 1.707 to make all the vectors equal
// length, and to make their lengths consistent with PerlinNoise3.
LVector2d(1.707, 0),
LVector2d(0, 1.707),
LVector2d(-1.707, 0),
LVector2d(0, -1.707),
};
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise2::Constructor
// Access: Published
@ -77,22 +62,25 @@ noise(const LVecBase2d &value) {
double y = vec._v.v._1;
// Find unit square that contains point.
int X = cmod((int)cfloor(x), _table_size);
int Y = cmod((int)cfloor(y), _table_size);
double xf = cfloor(x);
double yf = cfloor(y);
int X = ((int)xf) & _table_size_mask;
int Y = ((int)yf) & _table_size_mask;
// Find relative x,y of point in square.
x -= cfloor(x);
y -= cfloor(y);
x -= xf;
y -= yf;
// Compute fade curves for each of x,y.
double u = fade(x);
double v = fade(y);
// Hash coordinates of the 4 square corners . . .
// Hash coordinates of the 4 square corners (A, B, A + 1, and B + 1)
int A = _index[X] + Y;
int B = _index[X + 1] + Y;
// . . . and add blended results from 8 corners of cube.
// and add blended results from 4 corners of square.
double result =
lerp(v, lerp(u, grad(_index[A], x, y),
grad(_index[B], x - 1, y)),

View File

@ -31,21 +31,26 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PerlinNoise2 : public PerlinNoise {
PUBLISHED:
INLINE PerlinNoise2();
PerlinNoise2(double sx, double sy,
int table_size = 256,
unsigned long seed = 0);
INLINE PerlinNoise2(const PerlinNoise2 &copy);
INLINE void operator = (const PerlinNoise2 &copy);
INLINE double noise(double x, double y);
INLINE float noise(const LVecBase2f &value);
double noise(const LVecBase2d &value);
INLINE double operator ()(double x, double y);
INLINE float operator ()(const LVecBase2f &value);
INLINE double operator ()(const LVecBase2d &value);
private:
INLINE static double grad(int hash, double x, double y);
private:
LMatrix3d _input_xform;
static LVector2d _grad_table[8];
};
#include "perlinNoise2.I"

View File

@ -17,6 +17,49 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::Default Constructor
// Access: Published
// Description: The default constructor makes an invalid PerlinNoise3
// object. You must at least pass in a scale of each
// dimension.
//
// This constructor exists only so you can create a
// temporary placeholder PerlinNoise3 object, and later
// fill it in with the assignment operator.
////////////////////////////////////////////////////////////////////
INLINE PerlinNoise3::
PerlinNoise3() :
PerlinNoise(0, 1)
{
_input_xform.fill(0.0f);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::Copy Constructor
// Access: Published
// Description: Makes an exact copy of the existing PerlinNoise
// object, including its random seed.
////////////////////////////////////////////////////////////////////
INLINE PerlinNoise3::
PerlinNoise3(const PerlinNoise3 &copy) :
PerlinNoise(copy),
_input_xform(copy._input_xform)
{
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::Copy Assignment Operator
// Access: Published
// Description: Makes an exact copy of the existing PerlinNoise
// object, including its random seed.
////////////////////////////////////////////////////////////////////
INLINE void PerlinNoise3::
operator = (const PerlinNoise3 &copy) {
PerlinNoise::operator = (copy);
_input_xform = copy._input_xform;
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::noise
// Access: Published
@ -37,6 +80,36 @@ noise(const LVecBase3f &value) {
return (float)noise(value[0], value[1], value[2]);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::operator ()
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise3::
operator ()(double x, double y, double z) {
return noise(x, y, z);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::noise
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE float PerlinNoise3::
operator ()(const LVecBase3f &value) {
return noise(value);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::noise
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise3::
operator ()(const LVecBase3d &value) {
return noise(value);
}
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::grad
// Access: Private, Static
@ -46,17 +119,38 @@ noise(const LVecBase3f &value) {
////////////////////////////////////////////////////////////////////
INLINE double PerlinNoise3::
grad(int hash, double x, double y, double z) {
// Convert lo 4 bits of hash code into 12 gradient directions.
int h = hash & 15;
return _grad_table[h].dot(LVector3d(x, y, z));
// Convert low 4 bits of hash code into 12 gradient directions.
/*
This is Perlin's reference code, but the table lookup above is
slightly faster (no jump instructions) and produces exactly the
same results.
This is Perlin's reference code, but the switch statement below is
slightly faster and produces exactly the same results.
int h = hash & 15;
double u = (h < 8) ? x : y;
double v = (h < 4) ? y : ((h == 12 || h == 14) ? x : z);
return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
*/
switch (hash & 15) {
case 0: return x + y;
case 1: return -x + y;
case 2: return x - y;
case 3: return -x - y;
case 4: return x + z;
case 5: return -x + z;
case 6: return x - z;
case 7: return -x - z;
case 8: return y + z;
case 9: return -y + z;
case 10: return y - z;
case 11: return -y - z;
case 12: return x + y;
case 13: return -y + z;
case 14: return -x + y;
case 15: return -y - z;
}
nassertr(false, 0);
return 0;
}

View File

@ -19,28 +19,6 @@
#include "perlinNoise3.h"
#include "cmath.h"
LVector3d PerlinNoise3::_grad_table[16] = {
LVector3d(1, 1, 0),
LVector3d(-1, 1, 0),
LVector3d(1, -1, 0),
LVector3d(-1, -1, 0),
LVector3d(1, 0, 1),
LVector3d(-1, 0, 1),
LVector3d(1, 0, -1),
LVector3d(-1, 0, -1),
LVector3d(0, 1, 1),
LVector3d(0, -1, 1),
LVector3d(0, 1, -1),
LVector3d(0, -1, -1),
LVector3d(1, 1, 0),
LVector3d(0, -1, 1),
LVector3d(-1, 1, 0),
LVector3d(0, -1, -1),
};
////////////////////////////////////////////////////////////////////
// Function: PerlinNoise3::Constructor
// Access: Published
@ -90,21 +68,26 @@ noise(const LVecBase3d &value) {
double z = vec._v.v._2;
// Find unit cube that contains point.
int X = cmod((int)cfloor(x), _table_size);
int Y = cmod((int)cfloor(y), _table_size);
int Z = cmod((int)cfloor(z), _table_size);
double xf = cfloor(x);
double yf = cfloor(y);
double zf = cfloor(z);
int X = ((int)xf) & _table_size_mask;
int Y = ((int)yf) & _table_size_mask;
int Z = ((int)zf) & _table_size_mask;
// Find relative x,y,z of point in cube.
x -= cfloor(x);
y -= cfloor(y);
z -= cfloor(z);
x -= xf;
y -= yf;
z -= zf;
// 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 . . .
// Hash coordinates of the 8 cube corners. The 8 corners correspond
// to AA, BA, AB, BB, AA + 1, BA + 1, AB + 1, and BB + 1.
int A = _index[X] + Y;
int AA = _index[A] + Z;
int AB = _index[A + 1] + Z;
@ -112,7 +95,7 @@ noise(const LVecBase3d &value) {
int BA = _index[B] + Z;
int BB = _index[B + 1] + Z;
// . . . and add blended results from 8 corners of cube.
// and add blended results from 8 corners of cube.
double result =
lerp(w, lerp(v, lerp(u, grad(_index[AA], x, y, z),
grad(_index[BA], x - 1, y, z)),

View File

@ -31,21 +31,26 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA PerlinNoise3 : public PerlinNoise {
PUBLISHED:
INLINE PerlinNoise3();
PerlinNoise3(double sx, double sy, double sz,
int table_size = 256,
unsigned long seed = 0);
INLINE PerlinNoise3(const PerlinNoise3 &copy);
INLINE void operator = (const PerlinNoise3 &copy);
INLINE double noise(double x, double y, double z);
INLINE float noise(const LVecBase3f &value);
double noise(const LVecBase3d &value);
INLINE double operator ()(double x, double y, double z);
INLINE float operator ()(const LVecBase3f &value);
INLINE double operator ()(const LVecBase3d &value);
private:
INLINE static double grad(int hash, double x, double y, double z);
private:
LMatrix4d _input_xform;
static LVector3d _grad_table[16];
};
#include "perlinNoise3.I"

View File

@ -17,6 +17,17 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::Default Constructor
// Access: Published
// Description: Creates a StackedPerlinNoise2 object with no levels.
// You should call add_level() to add each level by
// hand.
////////////////////////////////////////////////////////////////////
INLINE StackedPerlinNoise2::
StackedPerlinNoise2() {
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::noise
// Access: Published
@ -36,3 +47,33 @@ INLINE float StackedPerlinNoise2::
noise(const LVecBase2f &value) {
return (float)noise(value[0], value[1]);
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::operator ()
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE double StackedPerlinNoise2::
operator ()(double x, double y) {
return noise(x, y);
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::noise
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE float StackedPerlinNoise2::
operator ()(const LVecBase2f &value) {
return noise(value);
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::noise
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE double StackedPerlinNoise2::
operator ()(const LVecBase2d &value) {
return noise(value);
}

View File

@ -31,19 +31,70 @@
StackedPerlinNoise2::
StackedPerlinNoise2(double sx, double sy, int num_levels,
double scale_factor, double amp_scale,
int table_size, unsigned long seed) :
_amp_scale(amp_scale)
{
int table_size, unsigned long seed) {
_noises.reserve(num_levels);
double amp = 1.0;
for (int i = 0; i < num_levels; ++i) {
PerlinNoise2 noise(sx, sy, table_size, seed);
_noises.push_back(noise);
add_level(noise, amp);
seed = noise.get_seed();
amp *= amp_scale;
sx /= scale_factor;
sy /= scale_factor;
}
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::Copy Constructor
// Access: Published
// Description: Creates an exact duplicate of the existing
// StackedPerlinNoise2 object, including the random
// seed.
////////////////////////////////////////////////////////////////////
StackedPerlinNoise2::
StackedPerlinNoise2(const StackedPerlinNoise2 &copy) :
_noises(copy._noises)
{
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::Copy Assignment Operator
// Access: Published
// Description: Creates an exact duplicate of the existing
// StackedPerlinNoise2 object, including the random
// seed.
////////////////////////////////////////////////////////////////////
void StackedPerlinNoise2::
operator = (const StackedPerlinNoise2 &copy) {
_noises = copy._noises;
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::add_level
// Access: Published
// Description: Adds an arbitrary PerlinNoise2 object, and an
// associated amplitude, to the stack.
////////////////////////////////////////////////////////////////////
void StackedPerlinNoise2::
add_level(const PerlinNoise2 &level, double amp) {
_noises.push_back(Noise());
Noise &n = _noises.back();
n._noise = level;
n._amp = amp;
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::clear
// Access: Published
// Description: Removes all levels from the stack. You must call
// add_level() again to restore them.
////////////////////////////////////////////////////////////////////
void StackedPerlinNoise2::
clear() {
_noises.clear();
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise2::noise
// Access: Published
@ -51,13 +102,11 @@ StackedPerlinNoise2(double sx, double sy, int num_levels,
////////////////////////////////////////////////////////////////////
double StackedPerlinNoise2::
noise(const LVecBase2d &value) {
double result = 0.0f;
double amp = 1.0f;
double result = 0.0;
Noises::iterator ni;
for (ni = _noises.begin(); ni != _noises.end(); ++ni) {
result += (*ni).noise(value) * amp;
amp *= _amp_scale;
result += (*ni)._noise(value) * (*ni)._amp;
}
return result;

View File

@ -31,18 +31,32 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA StackedPerlinNoise2 {
PUBLISHED:
StackedPerlinNoise2(double sx, double sy, int num_levels = 3,
INLINE StackedPerlinNoise2();
StackedPerlinNoise2(double sx, double sy, int num_levels = 2,
double scale_factor = 4.0f, double amp_scale = 0.5f,
int table_size = 256, unsigned long seed = 0);
StackedPerlinNoise2(const StackedPerlinNoise2 &copy);
void operator = (const StackedPerlinNoise2 &copy);
void add_level(const PerlinNoise2 &level, double amp = 1.0);
void clear();
INLINE double noise(double x, double y);
INLINE float noise(const LVecBase2f &value);
double noise(const LVecBase2d &value);
private:
double _amp_scale;
INLINE double operator ()(double x, double y);
INLINE float operator ()(const LVecBase2f &value);
INLINE double operator ()(const LVecBase2d &value);
typedef pvector<PerlinNoise2> Noises;
private:
class Noise {
public:
PerlinNoise2 _noise;
double _amp;
};
typedef pvector<Noise> Noises;
Noises _noises;
};

View File

@ -17,6 +17,17 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::Default Constructor
// Access: Published
// Description: Creates a StackedPerlinNoise3 object with no levels.
// You should call add_level() to add each level by
// hand.
////////////////////////////////////////////////////////////////////
INLINE StackedPerlinNoise3::
StackedPerlinNoise3() {
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::noise
// Access: Published
@ -36,3 +47,33 @@ INLINE float StackedPerlinNoise3::
noise(const LVecBase3f &value) {
return (float)noise(value[0], value[1], value[2]);
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::operator ()
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE double StackedPerlinNoise3::
operator ()(double x, double y, double z) {
return noise(x, y, z);
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::noise
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE float StackedPerlinNoise3::
operator ()(const LVecBase3f &value) {
return noise(value);
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::noise
// Access: Published
// Description: Returns the noise function of the three inputs.
////////////////////////////////////////////////////////////////////
INLINE double StackedPerlinNoise3::
operator ()(const LVecBase3d &value) {
return noise(value);
}

View File

@ -31,20 +31,71 @@
StackedPerlinNoise3::
StackedPerlinNoise3(double sx, double sy, double sz, int num_levels,
double scale_factor, double amp_scale,
int table_size, unsigned long seed) :
_amp_scale(amp_scale)
{
int table_size, unsigned long seed) {
_noises.reserve(num_levels);
double amp = 1.0;
for (int i = 0; i < num_levels; ++i) {
PerlinNoise3 noise(sx, sy, sz, table_size, seed);
_noises.push_back(noise);
add_level(noise, amp);
seed = noise.get_seed();
amp *= amp_scale;
sx /= scale_factor;
sy /= scale_factor;
sz /= scale_factor;
}
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::Copy Constructor
// Access: Published
// Description: Creates an exact duplicate of the existing
// StackedPerlinNoise3 object, including the random
// seed.
////////////////////////////////////////////////////////////////////
StackedPerlinNoise3::
StackedPerlinNoise3(const StackedPerlinNoise3 &copy) :
_noises(copy._noises)
{
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::Copy Assignment Operator
// Access: Published
// Description: Creates an exact duplicate of the existing
// StackedPerlinNoise3 object, including the random
// seed.
////////////////////////////////////////////////////////////////////
void StackedPerlinNoise3::
operator = (const StackedPerlinNoise3 &copy) {
_noises = copy._noises;
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::add_level
// Access: Published
// Description: Adds an arbitrary PerlinNoise3 object, and an
// associated amplitude, to the stack.
////////////////////////////////////////////////////////////////////
void StackedPerlinNoise3::
add_level(const PerlinNoise3 &level, double amp) {
_noises.push_back(Noise());
Noise &n = _noises.back();
n._noise = level;
n._amp = amp;
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::clear
// Access: Published
// Description: Removes all levels from the stack. You must call
// add_level() again to restore them.
////////////////////////////////////////////////////////////////////
void StackedPerlinNoise3::
clear() {
_noises.clear();
}
////////////////////////////////////////////////////////////////////
// Function: StackedPerlinNoise3::noise
// Access: Published
@ -52,13 +103,11 @@ StackedPerlinNoise3(double sx, double sy, double sz, int num_levels,
////////////////////////////////////////////////////////////////////
double StackedPerlinNoise3::
noise(const LVecBase3d &value) {
double result = 0.0f;
double amp = 1.0f;
double result = 0.0;
Noises::iterator ni;
for (ni = _noises.begin(); ni != _noises.end(); ++ni) {
result += (*ni).noise(value) * amp;
amp *= _amp_scale;
result += (*ni)._noise(value) * (*ni)._amp;
}
return result;

View File

@ -31,18 +31,32 @@
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA StackedPerlinNoise3 {
PUBLISHED:
INLINE StackedPerlinNoise3();
StackedPerlinNoise3(double sx, double sy, double sz, int num_levels = 3,
double scale_factor = 4.0f, double amp_scale = 0.5f,
int table_size = 256, unsigned long seed = 0);
StackedPerlinNoise3(const StackedPerlinNoise3 &copy);
void operator = (const StackedPerlinNoise3 &copy);
void add_level(const PerlinNoise3 &level, double amp = 1.0);
void clear();
INLINE double noise(double x, double y, double z);
INLINE float noise(const LVecBase3f &value);
double noise(const LVecBase3d &value);
private:
double _amp_scale;
INLINE double operator ()(double x, double y, double z);
INLINE float operator ()(const LVecBase3f &value);
INLINE double operator ()(const LVecBase3d &value);
typedef pvector<PerlinNoise3> Noises;
private:
class Noise {
public:
PerlinNoise3 _noise;
double _amp;
};
typedef pvector<Noise> Noises;
Noises _noises;
};