Browse Source

add Perlin noise

David Rose 20 years ago
parent
commit
9358dbf532

+ 21 - 5
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

+ 0 - 23
panda/src/mathutil/mathHelpers.I

@@ -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
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-#include <math.h>
-
-INLINE_MATHUTIL float distance(const LPoint3f &pos0, const LPoint3f &pos1) {
-  LVector3f v = pos0 - pos1;
-  return length(v);
-}

+ 0 - 37
panda/src/mathutil/mathHelpers.h

@@ -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
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#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

+ 4 - 0
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"
 

+ 96 - 0
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: [email protected]
+*/
+
+#include "mersenne.h"
+#include <stdio.h>
+
+/* initializes mt[N] with a seed */
+Mersenne::
+Mersenne(unsigned long seed) {
+  mt[0]= seed & 0xffffffffUL;
+  for (mti=1; mti<N; mti++) {
+    mt[mti] = 
+      (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 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<N-M;kk++) {
+      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+      mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+    }
+    for (;kk<N-1;kk++) {
+      y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+      mt[kk] = mt[kk+(M-N)] ^ (y >> 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;
+}

+ 86 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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: [email protected]
+*/
+
+#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

+ 85 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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();
+}
+

+ 58 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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]);
+  }
+}

+ 60 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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<int> Index;
+  Index _index;
+};
+
+#include "perlinNoise.I"
+
+#endif

+ 53 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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));
+}

+ 103 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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;
+}

+ 54 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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
+

+ 62 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     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);
+  */
+}

+ 127 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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;
+}

+ 54 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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
+