1 // voronoi.h 2 // 3 // Copyright (C) 2003, 2004 Jason Bevins 4 // 5 // This library is free software; you can redistribute it and/or modify it 6 // under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation; either version 2.1 of the License, or (at 8 // your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, but WITHOUT 11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 13 // License (COPYING.txt) for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with this library; if not, write to the Free Software Foundation, 17 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 // 19 // The developer's email is jlbezigvins@gmzigail.com (for great email, take 20 // off every 'zig'.) 21 // 22 module noise.mod.voronoi; 23 24 private { 25 import noise.mod.modulebase; 26 import noise.mathconsts; 27 } 28 29 /// @addtogroup libnoise 30 /// @{ 31 32 /// @addtogroup modules 33 /// @{ 34 35 /// @addtogroup generatormodules 36 /// @{ 37 38 /// Default displacement to apply to each cell for the 39 /// module::Voronoi noise module. 40 const double DEFAULT_VORONOI_DISPLACEMENT = 1.0; 41 42 /// Default frequency of the seed points for the module::Voronoi 43 /// noise module. 44 const double DEFAULT_VORONOI_FREQUENCY = 1.0; 45 46 /// Default seed of the noise function for the module::Voronoi 47 /// noise module. 48 const int DEFAULT_VORONOI_SEED = 0; 49 50 /// Noise module that outputs Voronoi cells. 51 /// 52 /// @image html modulevoronoi.png 53 /// 54 /// In mathematics, a <i>Voronoi cell</i> is a region containing all the 55 /// points that are closer to a specific <i>seed point</i> than to any 56 /// other seed point. These cells mesh with one another, producing 57 /// polygon-like formations. 58 /// 59 /// By default, this noise module randomly places a seed point within 60 /// each unit cube. By modifying the <i>frequency</i> of the seed points, 61 /// an application can change the distance between seed points. The 62 /// higher the frequency, the closer together this noise module places 63 /// the seed points, which reduces the size of the cells. To specify the 64 /// frequency of the cells, call the SetFrequency() method. 65 /// 66 /// This noise module assigns each Voronoi cell with a random constant 67 /// value from a coherent-noise function. The <i>displacement value</i> 68 /// controls the range of random values to assign to each cell. The 69 /// range of random values is +/- the displacement value. Call the 70 /// SetDisplacement() method to specify the displacement value. 71 /// 72 /// To modify the random positions of the seed points, call the SetSeed() 73 /// method. 74 /// 75 /// This noise module can optionally add the distance from the nearest 76 /// seed to the output value. To enable this feature, call the 77 /// EnableDistance() method. This causes the points in the Voronoi cells 78 /// to increase in value the further away that point is from the nearest 79 /// seed point. 80 /// 81 /// Voronoi cells are often used to generate cracked-mud terrain 82 /// formations or crystal-like textures 83 /// 84 /// This noise module requires no source modules. 85 class Voronoi : Mod 86 { 87 88 public: 89 90 /// Constructor. 91 /// 92 /// The default displacement value is set to 93 /// module::DEFAULT_VORONOI_DISPLACEMENT. 94 /// 95 /// The default frequency is set to 96 /// module::DEFAULT_VORONOI_FREQUENCY. 97 /// 98 /// The default seed value is set to 99 /// module::DEFAULT_VORONOI_SEED. 100 this() 101 { 102 super(this.GetSourceModCount ()); 103 m_displacement = DEFAULT_VORONOI_DISPLACEMENT; 104 m_enableDistance = false; 105 m_frequency = DEFAULT_VORONOI_FREQUENCY; 106 m_seed = DEFAULT_VORONOI_SEED; 107 } 108 109 /// Enables or disables applying the distance from the nearest seed 110 /// point to the output value. 111 /// 112 /// @param enable Specifies whether to apply the distance to the 113 /// output value or not. 114 /// 115 /// Applying the distance from the nearest seed point to the output 116 /// value causes the points in the Voronoi cells to increase in value 117 /// the further away that point is from the nearest seed point. 118 /// Setting this value to @a true (and setting the displacement to a 119 /// near-zero value) causes this noise module to generate cracked mud 120 /// formations. 121 void EnableDistance (bool enable = true) 122 { 123 m_enableDistance = enable; 124 } 125 126 /// Returns the displacement value of the Voronoi cells. 127 /// 128 /// @returns The displacement value of the Voronoi cells. 129 /// 130 /// This noise module assigns each Voronoi cell with a random constant 131 /// value from a coherent-noise function. The <i>displacement 132 /// value</i> controls the range of random values to assign to each 133 /// cell. The range of random values is +/- the displacement value. 134 double GetDisplacement () const 135 { 136 return m_displacement; 137 } 138 139 /// Returns the frequency of the seed points. 140 /// 141 /// @returns The frequency of the seed points. 142 /// 143 /// The frequency determines the size of the Voronoi cells and the 144 /// distance between these cells. 145 double GetFrequency () const 146 { 147 return m_frequency; 148 } 149 150 override int GetSourceModCount () const 151 { 152 return 0; 153 } 154 155 /// Returns the seed value used by the Voronoi cells 156 /// 157 /// @returns The seed value. 158 /// 159 /// The positions of the seed values are calculated by a 160 /// coherent-noise function. By modifying the seed value, the output 161 /// of that function changes. 162 int GetSeed () const 163 { 164 return m_seed; 165 } 166 167 /// Determines if the distance from the nearest seed point is applied 168 /// to the output value. 169 /// 170 /// @returns 171 /// - @a true if the distance is applied to the output value. 172 /// - @a false if not. 173 /// 174 /// Applying the distance from the nearest seed point to the output 175 /// value causes the points in the Voronoi cells to increase in value 176 /// the further away that point is from the nearest seed point. 177 bool IsDistanceEnabled () const 178 { 179 return m_enableDistance; 180 } 181 182 override double GetValue (double x, double y, double z) const 183 { 184 // This method could be more efficient by caching the seed values. Fix 185 // later. 186 187 x *= m_frequency; 188 y *= m_frequency; 189 z *= m_frequency; 190 191 int xInt = (x > 0.0? cast(int)x: cast(int)x - 1); 192 int yInt = (y > 0.0? cast(int)y: cast(int)y - 1); 193 int zInt = (z > 0.0? cast(int)z: cast(int)z - 1); 194 195 double minDist = 2147483647.0; 196 double xCandidate = 0; 197 double yCandidate = 0; 198 double zCandidate = 0; 199 200 // Inside each unit cube, there is a seed point at a random position. Go 201 // through each of the nearby cubes until we find a cube with a seed point 202 // that is closest to the specified position. 203 for (int zCur = zInt - 2; zCur <= zInt + 2; zCur++) { 204 for (int yCur = yInt - 2; yCur <= yInt + 2; yCur++) { 205 for (int xCur = xInt - 2; xCur <= xInt + 2; xCur++) { 206 207 // Calculate the position and distance to the seed point inside of 208 // this unit cube. 209 double xPos = xCur + ValueNoise3D (xCur, yCur, zCur, m_seed ); 210 double yPos = yCur + ValueNoise3D (xCur, yCur, zCur, m_seed + 1); 211 double zPos = zCur + ValueNoise3D (xCur, yCur, zCur, m_seed + 2); 212 double xDist = xPos - x; 213 double yDist = yPos - y; 214 double zDist = zPos - z; 215 double dist = xDist * xDist + yDist * yDist + zDist * zDist; 216 217 if (dist < minDist) { 218 // This seed point is closer to any others found so far, so record 219 // this seed point. 220 minDist = dist; 221 xCandidate = xPos; 222 yCandidate = yPos; 223 zCandidate = zPos; 224 } 225 } 226 } 227 } 228 229 double value; 230 if (m_enableDistance) { 231 // Determine the distance to the nearest seed point. 232 double xDist = xCandidate - x; 233 double yDist = yCandidate - y; 234 double zDist = zCandidate - z; 235 value = (sqrt (xDist * xDist + yDist * yDist + zDist * zDist) 236 ) * SQRT_3 - 1.0; 237 } else { 238 value = 0.0; 239 } 240 241 // Return the calculated distance with the displacement value applied. 242 return value + (m_displacement * cast(double)ValueNoise3D ( 243 cast(int)(floor (xCandidate)), 244 cast(int)(floor (yCandidate)), 245 cast(int)(floor (zCandidate)))); 246 } 247 248 /// Sets the displacement value of the Voronoi cells. 249 /// 250 /// @param displacement The displacement value of the Voronoi cells. 251 /// 252 /// This noise module assigns each Voronoi cell with a random constant 253 /// value from a coherent-noise function. The <i>displacement 254 /// value</i> controls the range of random values to assign to each 255 /// cell. The range of random values is +/- the displacement value. 256 void SetDisplacement (double displacement) 257 { 258 m_displacement = displacement; 259 } 260 261 /// Sets the frequency of the seed points. 262 /// 263 /// @param frequency The frequency of the seed points. 264 /// 265 /// The frequency determines the size of the Voronoi cells and the 266 /// distance between these cells. 267 void SetFrequency (double frequency) 268 { 269 m_frequency = frequency; 270 } 271 272 /// Sets the seed value used by the Voronoi cells 273 /// 274 /// @param seed The seed value. 275 /// 276 /// The positions of the seed values are calculated by a 277 /// coherent-noise function. By modifying the seed value, the output 278 /// of that function changes. 279 void SetSeed (int seed) 280 { 281 m_seed = seed; 282 } 283 284 protected: 285 286 /// Scale of the random displacement to apply to each Voronoi cell. 287 double m_displacement; 288 289 /// Determines if the distance from the nearest seed point is applied to 290 /// the output value. 291 bool m_enableDistance; 292 293 /// Frequency of the seed points. 294 double m_frequency; 295 296 /// Seed value used by the coherent-noise function to determine the 297 /// positions of the seed points. 298 int m_seed; 299 300 }; 301 302 /// @} 303 304 /// @} 305 306 /// @}