Panda3D
|
00001 // Filename: perlinNoise3.cxx 00002 // Created by: drose (05Oct05) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "perlinNoise3.h" 00016 #include "cmath.h" 00017 00018 //////////////////////////////////////////////////////////////////// 00019 // Function: PerlinNoise3::noise 00020 // Access: Published 00021 // Description: Returns the noise function of the three inputs. 00022 //////////////////////////////////////////////////////////////////// 00023 double PerlinNoise3:: 00024 noise(const LVecBase3d &value) const { 00025 // Convert the vector to our local coordinate space. 00026 LVecBase3d vec = _input_xform.xform_point(value); 00027 00028 double x = vec[0]; 00029 double y = vec[1]; 00030 double z = vec[2]; 00031 00032 // Find unit cube that contains point. 00033 double xf = cfloor(x); 00034 double yf = cfloor(y); 00035 double zf = cfloor(z); 00036 00037 int X = ((int)xf) & _table_size_mask; 00038 int Y = ((int)yf) & _table_size_mask; 00039 int Z = ((int)zf) & _table_size_mask; 00040 00041 // Find relative x,y,z of point in cube. 00042 x -= xf; 00043 y -= yf; 00044 z -= zf; 00045 00046 // Compute fade curves for each of x,y,z. 00047 double u = fade(x); 00048 double v = fade(y); 00049 double w = fade(z); 00050 00051 // Hash coordinates of the 8 cube corners. The 8 corners correspond 00052 // to AA, BA, AB, BB, AA + 1, BA + 1, AB + 1, and BB + 1. 00053 int A = _index[X] + Y; 00054 int AA = _index[A] + Z; 00055 int AB = _index[A + 1] + Z; 00056 int B = _index[X + 1] + Y; 00057 int BA = _index[B] + Z; 00058 int BB = _index[B + 1] + Z; 00059 00060 // and add blended results from 8 corners of cube. 00061 double result = 00062 lerp(w, lerp(v, lerp(u, grad(_index[AA], x, y, z), 00063 grad(_index[BA], x - 1, y, z)), 00064 lerp(u, grad(_index[AB], x, y - 1, z), 00065 grad(_index[BB], x - 1, y - 1, z))), 00066 lerp(v, lerp(u, grad(_index[AA + 1], x, y, z - 1), 00067 grad(_index[BA + 1], x - 1, y, z - 1)), 00068 lerp(u, grad(_index[AB + 1], x, y - 1, z - 1), 00069 grad(_index[BB + 1], x - 1, y - 1, z - 1)))); 00070 00071 return result; 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: PerlinNoise3::init_unscaled_xform 00076 // Access: Private 00077 // Description: Come up with a random rotation to apply to the input 00078 // coordinates. This will reduce the problem of the 00079 // singularities on the axes, by sending the axes in 00080 // some crazy direction. 00081 //////////////////////////////////////////////////////////////////// 00082 void PerlinNoise3:: 00083 init_unscaled_xform() { 00084 LRotationd rot(_randomizer.random_real_unit(), 00085 _randomizer.random_real_unit(), 00086 _randomizer.random_real_unit(), 00087 _randomizer.random_real_unit()); 00088 rot.normalize(); 00089 rot.extract_to_matrix(_unscaled_xform); 00090 00091 // And come up with a random translation too, just so the 00092 // singularity at (0, 0, 0) is also unpredicatable. 00093 _unscaled_xform.set_row(3, LVecBase3d(_randomizer.random_real_unit(), 00094 _randomizer.random_real_unit(), 00095 _randomizer.random_real_unit())); 00096 }