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 /// @}