From 9358dbf532ce17cde755f0081c20efb4b9d1e69b Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 7 Oct 2005 21:46:51 +0000 Subject: [PATCH] add Perlin noise --- panda/src/mathutil/Sources.pp | 26 ++++- panda/src/mathutil/mathHelpers.I | 23 ---- panda/src/mathutil/mathHelpers.h | 37 ------ panda/src/mathutil/mathutil_composite2.cxx | 4 + panda/src/mathutil/mersenne.cxx | 96 ++++++++++++++++ panda/src/mathutil/mersenne.h | 86 ++++++++++++++ panda/src/mathutil/perlinNoise.I | 85 ++++++++++++++ panda/src/mathutil/perlinNoise.cxx | 58 ++++++++++ panda/src/mathutil/perlinNoise.h | 60 ++++++++++ panda/src/mathutil/perlinNoise2.I | 53 +++++++++ panda/src/mathutil/perlinNoise2.cxx | 103 +++++++++++++++++ panda/src/mathutil/perlinNoise2.h | 54 +++++++++ panda/src/mathutil/perlinNoise3.I | 62 ++++++++++ panda/src/mathutil/perlinNoise3.cxx | 127 +++++++++++++++++++++ panda/src/mathutil/perlinNoise3.h | 54 +++++++++ 15 files changed, 863 insertions(+), 65 deletions(-) delete mode 100644 panda/src/mathutil/mathHelpers.I delete mode 100644 panda/src/mathutil/mathHelpers.h create mode 100644 panda/src/mathutil/mersenne.cxx create mode 100644 panda/src/mathutil/mersenne.h create mode 100644 panda/src/mathutil/perlinNoise.I create mode 100644 panda/src/mathutil/perlinNoise.cxx create mode 100644 panda/src/mathutil/perlinNoise.h create mode 100644 panda/src/mathutil/perlinNoise2.I create mode 100644 panda/src/mathutil/perlinNoise2.cxx create mode 100644 panda/src/mathutil/perlinNoise2.h create mode 100644 panda/src/mathutil/perlinNoise3.I create mode 100644 panda/src/mathutil/perlinNoise3.cxx create mode 100644 panda/src/mathutil/perlinNoise3.h diff --git a/panda/src/mathutil/Sources.pp b/panda/src/mathutil/Sources.pp index c86bbe1e84..6abdc08e51 100644 --- a/panda/src/mathutil/Sources.pp +++ b/panda/src/mathutil/Sources.pp @@ -21,8 +21,15 @@ geometricBoundingVolume.h \ linmath_events.h \ look_at.h look_at_src.I \ - look_at_src.cxx look_at_src.h omniBoundingVolume.I \ - omniBoundingVolume.h plane.h plane_src.I plane_src.cxx \ + look_at_src.cxx look_at_src.h \ + linmath_events.h \ + mersenne.h \ + omniBoundingVolume.I \ + omniBoundingVolume.h \ + perlinNoise.h perlinNoise.I \ + perlinNoise2.h perlinNoise2.I \ + perlinNoise3.h perlinNoise3.I \ + plane.h plane_src.I plane_src.cxx \ plane_src.h rotate_to.h rotate_to_src.cxx #define INCLUDED_SOURCES \ @@ -33,7 +40,12 @@ finiteBoundingVolume.cxx geometricBoundingVolume.cxx \ look_at.cxx \ linmath_events.cxx \ - omniBoundingVolume.cxx plane.cxx rotate_to.cxx + mersenne.cxx \ + omniBoundingVolume.cxx \ + perlinNoise.cxx \ + perlinNoise2.cxx \ + perlinNoise3.cxx \ + plane.cxx rotate_to.cxx #define INSTALL_HEADERS \ boundingHexahedron.I boundingHexahedron.h boundingLine.I \ @@ -45,8 +57,12 @@ geometricBoundingVolume.I geometricBoundingVolume.h look_at.h \ look_at_src.I look_at_src.h \ linmath_events.h \ - mathHelpers.I mathHelpers.h \ - omniBoundingVolume.I omniBoundingVolume.h plane.h plane_src.I \ + mersenne.h \ + omniBoundingVolume.I omniBoundingVolume.h \ + perlinNoise.h perlinNoise.I \ + perlinNoise2.h perlinNoise2.I \ + perlinNoise3.h perlinNoise3.I \ + plane.h plane_src.I \ plane_src.h rotate_to.h #define IGATESCAN all diff --git a/panda/src/mathutil/mathHelpers.I b/panda/src/mathutil/mathHelpers.I deleted file mode 100644 index c3f5fc3803..0000000000 --- a/panda/src/mathutil/mathHelpers.I +++ /dev/null @@ -1,23 +0,0 @@ -// Filename: mathHelpers.I -// Created by: mike (25Apr97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// -#include - -INLINE_MATHUTIL float distance(const LPoint3f &pos0, const LPoint3f &pos1) { - LVector3f v = pos0 - pos1; - return length(v); -} diff --git a/panda/src/mathutil/mathHelpers.h b/panda/src/mathutil/mathHelpers.h deleted file mode 100644 index eb462327a7..0000000000 --- a/panda/src/mathutil/mathHelpers.h +++ /dev/null @@ -1,37 +0,0 @@ -// Filename: mathHelpers.h -// Created by: mike (25Apr97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef MATHHELPERS_H -#define MATHHELPERS_H - -//////////////////////////////////////////////////////////////////// -// Includes -//////////////////////////////////////////////////////////////////// -#include "pandabase.h" - -#include "luse.h" - -BEGIN_PUBLISH - -INLINE_MATHUTIL float distance(const LPoint3f &pos0, const LPoint3f &pos1); - -END_PUBLISH - -#include "mathHelpers.I" - -#endif diff --git a/panda/src/mathutil/mathutil_composite2.cxx b/panda/src/mathutil/mathutil_composite2.cxx index f1d7c7aad0..39a3560039 100644 --- a/panda/src/mathutil/mathutil_composite2.cxx +++ b/panda/src/mathutil/mathutil_composite2.cxx @@ -1,8 +1,12 @@ #include "config_mathutil.cxx" +#include "perlinNoise.cxx" +#include "perlinNoise2.cxx" +#include "perlinNoise3.cxx" #include "plane.cxx" #include "rotate_to.cxx" #include "look_at.cxx" #include "linmath_events.cxx" +#include "mersenne.cxx" #include "fftCompressor.cxx" diff --git a/panda/src/mathutil/mersenne.cxx b/panda/src/mathutil/mersenne.cxx new file mode 100644 index 0000000000..0c65449999 --- /dev/null +++ b/panda/src/mathutil/mersenne.cxx @@ -0,0 +1,96 @@ +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.keio.ac.jp/matumoto/emt.html + email: matumoto@math.keio.ac.jp +*/ + +#include "mersenne.h" +#include + +/* initializes mt[N] with a seed */ +Mersenne:: +Mersenne(unsigned long seed) { + mt[0]= seed & 0xffffffffUL; + for (mti=1; mti> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + mt[mti] &= 0xffffffffUL; + /* for >32 bit machines */ + } +} + +/* generates a random number on [0,0x7fffffff]-interval */ +unsigned long Mersenne:: +get_uint31() { + unsigned long y; + static unsigned long mag01[2]={0x0UL, MATRIX_A}; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (mti >= N) { /* generate N words at one time */ + unsigned int kk; + + for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; + } + for (;kk> 1) ^ mag01[y & 0x1UL]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + + mti = 0; + } + + y = mt[mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y >> 1; +} diff --git a/panda/src/mathutil/mersenne.h b/panda/src/mathutil/mersenne.h new file mode 100644 index 0000000000..bceeeac17d --- /dev/null +++ b/panda/src/mathutil/mersenne.h @@ -0,0 +1,86 @@ +// Filename: mersenne.h +// Created by: darren (18Jul02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef MERSENNE_H +#define MERSENNE_H + +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.keio.ac.jp/matumoto/emt.html + email: matumoto@math.keio.ac.jp +*/ + +#include "pandabase.h" + +class EXPCL_PANDA Mersenne { +PUBLISHED: + Mersenne(unsigned long seed); + unsigned long get_uint31(); + +private: + enum { + // Period parameters + N = 624, + M = 397, + MATRIX_A = 0x9908b0dfUL, // constant vector a + UPPER_MASK = 0x80000000UL, // most significant w-r bits + LOWER_MASK = 0x7fffffffUL, // least significant r bits + }; + + unsigned long mt[N]; // the array for the state vector + unsigned int mti; // mti==N+1 means mt[N] is not initialized +}; + +#endif diff --git a/panda/src/mathutil/perlinNoise.I b/panda/src/mathutil/perlinNoise.I new file mode 100644 index 0000000000..31b54268fd --- /dev/null +++ b/panda/src/mathutil/perlinNoise.I @@ -0,0 +1,85 @@ +// Filename: perlinNoise.I +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::fade +// Access: Protected, Static +// Description: Returns a smooth interpolation spline from 0 .. 1 +// for t. +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise:: +fade(double t) { + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::lerp +// Access: Protected, Static +// Description: Returns the smoothly lerped value from a to b. +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise:: +lerp(double t, double a, double b) { + return a + t * (b - a); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::random_int +// Access: Protected +// Description: Returns a random integer in the range [0, range). +//////////////////////////////////////////////////////////////////// +INLINE int PerlinNoise:: +random_int(int range) { + return (int)floor(random_real((double)range)); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::random_real +// Access: Protected +// Description: Returns a random double in the range [0, range). +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise:: +random_real(double range) { + return (range * _mersenne.get_uint31()) / ((double)0xffffffff + 1.0f); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::random_real_unit +// Access: Protected +// Description: Returns a random double in the range [-0.5, 0.5). +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise:: +random_real_unit() { + return random_real(1.0f) - 0.5f; +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::get_next_seed +// Access: Protected, Static +// Description: Returns a random seed value for the next-in-sequence +// PerlinNoise object. +//////////////////////////////////////////////////////////////////// +INLINE unsigned long PerlinNoise:: +get_next_seed() { + if (!_got_first_seed) { + _next_seed = Mersenne((unsigned long)time(NULL)); + _got_first_seed = true; + } + return _next_seed.get_uint31(); +} + diff --git a/panda/src/mathutil/perlinNoise.cxx b/panda/src/mathutil/perlinNoise.cxx new file mode 100644 index 0000000000..6224dac21a --- /dev/null +++ b/panda/src/mathutil/perlinNoise.cxx @@ -0,0 +1,58 @@ +// Filename: perlinNoise.cxx +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "perlinNoise.h" + +Mersenne PerlinNoise::_next_seed(0); +bool PerlinNoise::_got_first_seed = false; + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise::Constructor +// Access: Protected +// Description: Randomizes the tables to make a unique noise +// function. +// +// If seed is nonzero, it is used to define the tables; +// if it is zero a random seed is generated. +//////////////////////////////////////////////////////////////////// +PerlinNoise:: +PerlinNoise(int table_size, unsigned long seed) : + _table_size(table_size), + _mersenne(seed != 0 ? seed : get_next_seed()) +{ + // The _index table is just a randomly shuffled index. + // table. + _index.reserve(_table_size * 2); + int i; + for (i = 0; i < _table_size; ++i) { + _index.push_back(i); + } + for (i = 0; i < _table_size; ++i) { + int j = random_int(_table_size); + nassertv(j >= 0 && j < _table_size); + int t = _index[i]; + _index[i] = _index[j]; + _index[j] = t; + } + + // We double up _index so we don't need to perform modulo + // arithmetic. + for (i = 0; i < _table_size; ++i) { + _index.push_back(_index[i]); + } +} diff --git a/panda/src/mathutil/perlinNoise.h b/panda/src/mathutil/perlinNoise.h new file mode 100644 index 0000000000..5234afe122 --- /dev/null +++ b/panda/src/mathutil/perlinNoise.h @@ -0,0 +1,60 @@ +// Filename: perlinNoise.h +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PERLINNOISE_H +#define PERLINNOISE_H + +#include "pandabase.h" +#include "pvector.h" +#include "luse.h" +#include "mersenne.h" + +//////////////////////////////////////////////////////////////////// +// Class : PerlinNoise +// Description : This is the base class for PerlinNoise2 and +// PerlinNoise3, different dimensions of Perlin noise +// implementation. The base class just collects the +// common functionality. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PerlinNoise { +protected: + PerlinNoise(int table_size, unsigned long seed); + + INLINE static double fade(double t); + INLINE static double lerp(double t, double a, double b); + + INLINE int random_int(int range); + INLINE double random_real(double range); + INLINE double random_real_unit(); + + INLINE static unsigned long get_next_seed(); + +protected: + int _table_size; + + Mersenne _mersenne; + static Mersenne _next_seed; + static bool _got_first_seed; + + typedef pvector Index; + Index _index; +}; + +#include "perlinNoise.I" + +#endif diff --git a/panda/src/mathutil/perlinNoise2.I b/panda/src/mathutil/perlinNoise2.I new file mode 100644 index 0000000000..6b1c5b9e53 --- /dev/null +++ b/panda/src/mathutil/perlinNoise2.I @@ -0,0 +1,53 @@ +// Filename: perlinNoise2.I +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise2::noise +// Access: Published +// Description: Returns the noise function of the three inputs. +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise2:: +noise(double x, double y) { + return noise(LVecBase2d(x, y)); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise2::noise +// Access: Published +// Description: Returns the noise function of the three inputs. +//////////////////////////////////////////////////////////////////// +INLINE float PerlinNoise2:: +noise(const LVecBase2f &value) { + return (float)noise(value[0], value[1]); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise2::grad +// Access: Private, Static +// Description: Returns the dot product of a random gradient vector +// (determined by the hash code) with the indicated +// offset vector. +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise2:: +grad(int hash, double x, double y) { + // Convert lo 3 bits of hash code into 8 gradient directions. + + int h = hash & 7; + return _grad_table[h].dot(LVector2d(x, y)); +} diff --git a/panda/src/mathutil/perlinNoise2.cxx b/panda/src/mathutil/perlinNoise2.cxx new file mode 100644 index 0000000000..d9ae6691e0 --- /dev/null +++ b/panda/src/mathutil/perlinNoise2.cxx @@ -0,0 +1,103 @@ +// Filename: perlinNoise2.cxx +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#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 +// Description: Randomizes the tables to make a unique noise +// function. +// +// If seed is nonzero, it is used to define the tables; +// if it is zero a random seed is generated. +//////////////////////////////////////////////////////////////////// +PerlinNoise2:: +PerlinNoise2(double sx, double sy, + int table_size, unsigned long seed) : + PerlinNoise(table_size, seed) +{ + // Come up with a random rotation to apply to the input coordinates. + // This will reduce the problem of the singularities on the axes, by + // sending the axes in some crazy direction. + double rot = random_real(360.0f); + _input_xform = LMatrix3d::rotate_mat(rot); + + // And come up with a random translation too, just so the + // singularity at (0, 0) is also unpredicatable. + _input_xform.set_row(2, LVecBase2d(random_real_unit(), + random_real_unit())); + + // Finally, apply the user's input scale. + _input_xform = LMatrix3d::scale_mat(1.0f / sx, 1.0f / sy) * _input_xform; +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise2::noise +// Access: Published +// Description: Returns the noise function of the three inputs. +//////////////////////////////////////////////////////////////////// +double PerlinNoise2:: +noise(const LVecBase2d &value) { + // Convert the vector to our local coordinate space. + LVecBase2d vec = _input_xform.xform_point(value); + + double x = vec._v.v._0; + 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); + + // Find relative x,y of point in square. + x -= cfloor(x); + y -= cfloor(y); + + // Compute fade curves for each of x,y. + double u = fade(x); + double v = fade(y); + + // Hash coordinates of the 4 square corners . . . + int A = _index[X] + Y; + int B = _index[X + 1] + Y; + + // . . . and add blended results from 8 corners of cube. + double result = + lerp(v, lerp(u, grad(_index[A], x, y), + grad(_index[B], x - 1, y)), + lerp(u, grad(_index[A + 1], x, y - 1), + grad(_index[B + 1], x - 1, y - 1))); + + return result; +} diff --git a/panda/src/mathutil/perlinNoise2.h b/panda/src/mathutil/perlinNoise2.h new file mode 100644 index 0000000000..4b89274710 --- /dev/null +++ b/panda/src/mathutil/perlinNoise2.h @@ -0,0 +1,54 @@ +// Filename: perlinNoise2.h +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PERLINNOISE2_H +#define PERLINNOISE2_H + +#include "pandabase.h" +#include "perlinNoise.h" + +//////////////////////////////////////////////////////////////////// +// Class : PerlinNoise2 +// Description : This class provides an implementation of Perlin noise +// for 2 variables. This code is loosely based on the +// reference implementation at +// http://mrl.nyu.edu/~perlin/noise/ . +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PerlinNoise2 : public PerlinNoise { +PUBLISHED: + PerlinNoise2(double sx, double sy, + int table_size = 256, + unsigned long seed = 0); + + INLINE double noise(double x, double y); + INLINE float noise(const LVecBase2f &value); + double noise(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" + +#endif + diff --git a/panda/src/mathutil/perlinNoise3.I b/panda/src/mathutil/perlinNoise3.I new file mode 100644 index 0000000000..364006c3d2 --- /dev/null +++ b/panda/src/mathutil/perlinNoise3.I @@ -0,0 +1,62 @@ +// Filename: perlinNoise3.I +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise3::noise +// Access: Published +// Description: Returns the noise function of the three inputs. +//////////////////////////////////////////////////////////////////// +INLINE double PerlinNoise3:: +noise(double x, double y, double z) { + return noise(LVecBase3d(x, y, z)); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise3::noise +// Access: Published +// Description: Returns the noise function of the three inputs. +//////////////////////////////////////////////////////////////////// +INLINE float PerlinNoise3:: +noise(const LVecBase3f &value) { + return (float)noise(value[0], value[1], value[2]); +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise3::grad +// Access: Private, Static +// Description: Returns the dot product of a random gradient vector +// (determined by the hash code) with the indicated +// offset vector. +//////////////////////////////////////////////////////////////////// +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)); + + /* + This is Perlin's reference code, but the table lookup above is + slightly faster (no jump instructions) and produces exactly the + same results. + 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); + */ +} diff --git a/panda/src/mathutil/perlinNoise3.cxx b/panda/src/mathutil/perlinNoise3.cxx new file mode 100644 index 0000000000..940757d24f --- /dev/null +++ b/panda/src/mathutil/perlinNoise3.cxx @@ -0,0 +1,127 @@ +// Filename: perlinNoise3.cxx +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#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 +// Description: Randomizes the tables to make a unique noise +// function. +// +// If seed is nonzero, it is used to define the tables; +// if it is zero a random seed is generated. +//////////////////////////////////////////////////////////////////// +PerlinNoise3:: +PerlinNoise3(double sx, double sy, double sz, + int table_size, unsigned long seed) : + PerlinNoise(table_size, seed) +{ + // Come up with a random rotation to apply to the input coordinates. + // This will reduce the problem of the singularities on the axes, by + // sending the axes in some crazy direction. + LRotationd rot(random_real_unit(), + random_real_unit(), + random_real_unit(), + random_real_unit()); + rot.normalize(); + rot.extract_to_matrix(_input_xform); + + // And come up with a random translation too, just so the + // singularity at (0, 0, 0) is also unpredicatable. + _input_xform.set_row(3, LVecBase3d(random_real_unit(), + random_real_unit(), + random_real_unit())); + + // Finally, apply the user's input scale. + _input_xform = LMatrix4d::scale_mat(1.0f / sx, 1.0f / sy, 1.0f / sz) * _input_xform; +} + +//////////////////////////////////////////////////////////////////// +// Function: PerlinNoise3::noise +// Access: Published +// Description: Returns the noise function of the three inputs. +//////////////////////////////////////////////////////////////////// +double PerlinNoise3:: +noise(const LVecBase3d &value) { + // Convert the vector to our local coordinate space. + LVecBase3d vec = _input_xform.xform_point(value); + + double x = vec._v.v._0; + double y = vec._v.v._1; + 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); + + // Find relative x,y,z of point in cube. + x -= cfloor(x); + y -= cfloor(y); + z -= cfloor(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 = _index[X] + Y; + int AA = _index[A] + Z; + int AB = _index[A + 1] + Z; + int B = _index[X + 1] + Y; + int BA = _index[B] + Z; + int BB = _index[B + 1] + Z; + + // . . . 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)), + lerp(u, grad(_index[AB], x, y - 1, z), + grad(_index[BB], x - 1, y - 1, z))), + lerp(v, lerp(u, grad(_index[AA + 1], x, y, z - 1), + grad(_index[BA + 1], x - 1, y, z - 1)), + lerp(u, grad(_index[AB + 1], x, y - 1, z - 1), + grad(_index[BB + 1], x - 1, y - 1, z - 1)))); + + return result; +} diff --git a/panda/src/mathutil/perlinNoise3.h b/panda/src/mathutil/perlinNoise3.h new file mode 100644 index 0000000000..1c65f563b4 --- /dev/null +++ b/panda/src/mathutil/perlinNoise3.h @@ -0,0 +1,54 @@ +// Filename: perlinNoise3.h +// Created by: drose (05Oct05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef PERLINNOISE3_H +#define PERLINNOISE3_H + +#include "pandabase.h" +#include "perlinNoise.h" + +//////////////////////////////////////////////////////////////////// +// Class : PerlinNoise3 +// Description : This class provides an implementation of Perlin noise +// for 3 variables. This code is loosely based on the +// reference implementation at +// http://mrl.nyu.edu/~perlin/noise/ . +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA PerlinNoise3 : public PerlinNoise { +PUBLISHED: + PerlinNoise3(double sx, double sy, double sz, + int table_size = 256, + unsigned long seed = 0); + + INLINE double noise(double x, double y, double z); + INLINE float noise(const LVecBase3f &value); + double noise(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" + +#endif +