1 // select.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.select; 23 24 private { 25 import noise.mod.modulebase; 26 import noise.interp; 27 debug import std.stdio; 28 } 29 30 /// @addtogroup libnoise 31 /// @{ 32 33 /// @addtogroup modules 34 /// @{ 35 36 /// @addtogroup selectormodules 37 /// @{ 38 39 /// Default edge-falloff value for the module::Select noise module. 40 const double DEFAULT_SELECT_EDGE_FALLOFF = 0.0; 41 42 /// Default lower bound of the selection range for the 43 /// module::Select noise module. 44 const double DEFAULT_SELECT_LOWER_BOUND = -1.0; 45 46 /// Default upper bound of the selection range for the 47 /// module::Select noise module. 48 const double DEFAULT_SELECT_UPPER_BOUND = 1.0; 49 50 /// Noise module that outputs the value selected from one of two source 51 /// modules chosen by the output value from a control module. 52 /// 53 /// @image html moduleselect.png 54 /// 55 /// Unlike most other noise modules, the index value assigned to a source 56 /// module determines its role in the selection operation: 57 /// - Source module 0 (upper left in the diagram) outputs a value. 58 /// - Source module 1 (lower left in the diagram) outputs a value. 59 /// - Source module 2 (bottom of the diagram) is known as the <i>control 60 /// module</i>. The control module determines the value to select. If 61 /// the output value from the control module is within a range of values 62 /// known as the <i>selection range</i>, this noise module outputs the 63 /// value from the source module with an index value of 1. Otherwise, 64 /// this noise module outputs the value from the source module with an 65 /// index value of 0. 66 /// 67 /// To specify the bounds of the selection range, call the SetBounds() 68 /// method. 69 /// 70 /// An application can pass the control module to the SetControlMod() 71 /// method instead of the SetSourceMod() method. This may make the 72 /// application code easier to read. 73 /// 74 /// By default, there is an abrupt transition between the output values 75 /// from the two source modules at the selection-range boundary. To 76 /// smooth the transition, pass a non-zero value to the SetEdgeFalloff() 77 /// method. Higher values result in a smoother transition. 78 /// 79 /// This noise module requires three source modules. 80 class Select : Mod 81 { 82 83 public: 84 85 /// Constructor. 86 /// 87 /// The default falloff value at the edge transition is set to 88 /// module::DEFAULT_SELECT_EDGE_FALLOFF. 89 /// 90 /// The default lower bound of the selection range is set to 91 /// module::DEFAULT_SELECT_LOWER_BOUND. 92 /// 93 /// The default upper bound of the selection range is set to 94 /// module::DEFAULT_SELECT_UPPER_BOUND. 95 this() 96 { 97 super(this.GetSourceModCount ()); 98 m_edgeFalloff = DEFAULT_SELECT_EDGE_FALLOFF; 99 m_lowerBound = DEFAULT_SELECT_LOWER_BOUND; 100 m_upperBound = DEFAULT_SELECT_UPPER_BOUND; 101 } 102 103 this(const double edgeFalloff, const double lowerBound, const double upperBound) 104 { 105 super(this.GetSourceModCount ()); 106 m_edgeFalloff = edgeFalloff; 107 m_lowerBound = lowerBound; 108 m_upperBound = upperBound; 109 } 110 111 /// Returns the control module. 112 /// 113 /// @returns A reference to the control module. 114 /// 115 /// @pre A control module has been added to this noise module via a 116 /// call to SetSourceMod() or SetControlMod(). 117 /// 118 /// @throw new ExceptionNoMod See the preconditions for more 119 /// information. 120 /// 121 /// The control module determines the output value to select. If the 122 /// output value from the control module is within a range of values 123 /// known as the <i>selection range</i>, the GetValue() method outputs 124 /// the value from the source module with an index value of 1. 125 /// Otherwise, this method outputs the value from the source module 126 /// with an index value of 0. 127 ref const(Mod) GetControlMod () const 128 { 129 if (m_pSourceMod == null || m_pSourceMod[2] == null) { 130 throw new ExceptionNoMod (); 131 } 132 return *(m_pSourceMod[2]); 133 } 134 135 /// Returns the falloff value at the edge transition. 136 /// 137 /// @returns The falloff value at the edge transition. 138 /// 139 /// The falloff value is the width of the edge transition at either 140 /// edge of the selection range. 141 /// 142 /// By default, there is an abrupt transition between the output 143 /// values from the two source modules at the selection-range 144 /// boundary. 145 double GetEdgeFalloff () const 146 { 147 return m_edgeFalloff; 148 } 149 150 /// Returns the lower bound of the selection range. 151 /// 152 /// @returns The lower bound of the selection range. 153 /// 154 /// If the output value from the control module is within the 155 /// selection range, the GetValue() method outputs the value from the 156 /// source module with an index value of 1. Otherwise, this method 157 /// outputs the value from the source module with an index value of 0. 158 double GetLowerBound () const 159 { 160 return m_lowerBound; 161 } 162 163 override int GetSourceModCount () const 164 { 165 return 3; 166 } 167 168 /// Returns the upper bound of the selection range. 169 /// 170 /// @returns The upper bound of the selection range. 171 /// 172 /// If the output value from the control module is within the 173 /// selection range, the GetValue() method outputs the value from the 174 /// source module with an index value of 1. Otherwise, this method 175 /// outputs the value from the source module with an index value of 0. 176 double GetUpperBound () const 177 { 178 return m_upperBound; 179 } 180 181 override double GetValue (double x, double y, double z) const 182 { 183 assert (m_pSourceMod[0] !is null); 184 assert (m_pSourceMod[1] !is null); 185 assert (m_pSourceMod[2] !is null); 186 187 double controlValue = m_pSourceMod[2].GetValue (x, y, z); 188 double alpha; 189 if (m_edgeFalloff > 0.0) { 190 if (controlValue < (m_lowerBound - m_edgeFalloff)) { 191 // The output value from the control module is below the selector 192 // threshold; return the output value from the first source module. 193 return m_pSourceMod[0].GetValue (x, y, z); 194 195 } else if (controlValue < (m_lowerBound + m_edgeFalloff)) { 196 // The output value from the control module is near the lower end of the 197 // selector threshold and within the smooth curve. Interpolate between 198 // the output values from the first and second source modules. 199 double lowerCurve = (m_lowerBound - m_edgeFalloff); 200 double upperCurve = (m_lowerBound + m_edgeFalloff); 201 alpha = SCurve3 ( 202 (controlValue - lowerCurve) / (upperCurve - lowerCurve)); 203 return LinearInterp (m_pSourceMod[0].GetValue (x, y, z), 204 m_pSourceMod[1].GetValue (x, y, z), 205 alpha); 206 207 } else if (controlValue < (m_upperBound - m_edgeFalloff)) { 208 // The output value from the control module is within the selector 209 // threshold; return the output value from the second source module. 210 return m_pSourceMod[1].GetValue (x, y, z); 211 212 } else if (controlValue < (m_upperBound + m_edgeFalloff)) { 213 // The output value from the control module is near the upper end of the 214 // selector threshold and within the smooth curve. Interpolate between 215 // the output values from the first and second source modules. 216 double lowerCurve = (m_upperBound - m_edgeFalloff); 217 double upperCurve = (m_upperBound + m_edgeFalloff); 218 alpha = SCurve3 ( 219 (controlValue - lowerCurve) / (upperCurve - lowerCurve)); 220 return LinearInterp (m_pSourceMod[1].GetValue (x, y, z), 221 m_pSourceMod[0].GetValue (x, y, z), 222 alpha); 223 224 } else { 225 // Output value from the control module is above the selector threshold; 226 // return the output value from the first source module. 227 return m_pSourceMod[0].GetValue (x, y, z); 228 } 229 } else { 230 if (controlValue < m_lowerBound || controlValue > m_upperBound) { 231 return m_pSourceMod[0].GetValue (x, y, z); 232 } else { 233 return m_pSourceMod[1].GetValue (x, y, z); 234 } 235 } 236 } 237 238 /// Sets the lower and upper bounds of the selection range. 239 /// 240 /// @param lowerBound The lower bound. 241 /// @param upperBound The upper bound. 242 /// 243 /// @pre The lower bound must be less than or equal to the upper 244 /// bound. 245 /// 246 /// @throw new ExceptionInvalidParam An invalid parameter was 247 /// specified; see the preconditions for more information. 248 /// 249 /// If the output value from the control module is within the 250 /// selection range, the GetValue() method outputs the value from the 251 /// source module with an index value of 1. Otherwise, this method 252 /// outputs the value from the source module with an index value of 0. 253 void SetBounds (double lowerBound, double upperBound) 254 { 255 assert (lowerBound < upperBound); 256 257 m_lowerBound = lowerBound; 258 m_upperBound = upperBound; 259 260 // Make sure that the edge falloff curves do not overlap. 261 SetEdgeFalloff (m_edgeFalloff); 262 } 263 264 /// Sets the control module. 265 /// 266 /// @param controlMod The control module. 267 /// 268 /// The control module determines the output value to select. If the 269 /// output value from the control module is within a range of values 270 /// known as the <i>selection range</i>, the GetValue() method outputs 271 /// the value from the source module with an index value of 1. 272 /// Otherwise, this method outputs the value from the source module 273 /// with an index value of 0. 274 /// 275 /// This method assigns the control module an index value of 2. 276 /// Passing the control module to this method produces the same 277 /// results as passing the control module to the SetSourceMod() 278 /// method while assigning that noise module an index value of 2. 279 /// 280 /// This control module must exist throughout the lifetime of this 281 /// noise module unless another control module replaces that control 282 /// module. 283 void SetControlMod (const(Mod)* controlMod) 284 { 285 assert (m_pSourceMod !is null); 286 m_pSourceMod[2] = controlMod; 287 } 288 289 /// Sets the falloff value at the edge transition. 290 /// 291 /// @param edgeFalloff The falloff value at the edge transition. 292 /// 293 /// The falloff value is the width of the edge transition at either 294 /// edge of the selection range. 295 /// 296 /// By default, there is an abrupt transition between the values from 297 /// the two source modules at the boundaries of the selection range. 298 /// 299 /// For example, if the selection range is 0.5 to 0.8, and the edge 300 /// falloff value is 0.1, then the GetValue() method outputs: 301 /// - the output value from the source module with an index value of 0 302 /// if the output value from the control module is less than 0.4 303 /// ( = 0.5 - 0.1). 304 /// - a linear blend between the two output values from the two source 305 /// modules if the output value from the control module is between 306 /// 0.4 ( = 0.5 - 0.1) and 0.6 ( = 0.5 + 0.1). 307 /// - the output value from the source module with an index value of 1 308 /// if the output value from the control module is between 0.6 309 /// ( = 0.5 + 0.1) and 0.7 ( = 0.8 - 0.1). 310 /// - a linear blend between the output values from the two source 311 /// modules if the output value from the control module is between 312 /// 0.7 ( = 0.8 - 0.1 ) and 0.9 ( = 0.8 + 0.1). 313 /// - the output value from the source module with an index value of 0 314 /// if the output value from the control module is greater than 0.9 315 /// ( = 0.8 + 0.1). 316 void SetEdgeFalloff (double edgeFalloff) 317 { 318 // Make sure that the edge falloff curves do not overlap. 319 double boundSize = m_upperBound - m_lowerBound; 320 m_edgeFalloff = (edgeFalloff > boundSize / 2)? boundSize / 2: edgeFalloff; 321 } 322 323 protected: 324 325 /// Edge-falloff value. 326 double m_edgeFalloff; 327 328 /// Lower bound of the selection range. 329 double m_lowerBound; 330 331 /// Upper bound of the selection range. 332 double m_upperBound; 333 334 }; 335 336 /// @} 337 338 /// @} 339 340 /// @}