/* * Copyright (C) 2003, 2004 Jason Bevins (original libnoise code) * Copyright 2010 Thomas J. Hodge (java port of libnoise) * * This file is part of libnoiseforjava. * * libnoiseforjava is a Java port of the C++ library libnoise, which may be found at * http://libnoise.sourceforge.net/. libnoise was developed by Jason Bevins, who may be * contacted at jlbezigvins@gmzigail.com (for great email, take off every 'zig'). * Porting to Java was done by Thomas Hodge, who may be contacted at * libnoisezagforjava@gzagmail.com (remove every 'zag'). * * libnoiseforjava is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later version. * * libnoiseforjava is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * libnoiseforjava. If not, see . * */ package libnoiseforjava.module; import libnoiseforjava.Interp; import libnoiseforjava.exception.ExceptionInvalidParam; import libnoiseforjava.exception.ExceptionNoModule; public class Select extends ModuleBase { /// Noise module that outputs the value selected from one of two source /// modules chosen by the output value from a control module. /// /// Unlike most other noise modules, the index value assigned to a source /// module determines its role in the selection operation: /// - Source module 0 (upper left in the diagram) outputs a value. /// - Source module 1 (lower left in the diagram) outputs a value. /// - Source module 2 (bottom of the diagram) is known as the control /// module. The control module determines the value to select. If /// the output value from the control module is within a range of values /// known as the selection range, this noise module outputs the /// value from the source module with an index value of 1. Otherwise, /// this noise module outputs the value from the source module with an /// index value of 0. /// /// To specify the bounds of the selection range, call the setBounds() /// method. /// /// An application can pass the control module to the setControlModule() /// method instead of the setSourceModule() method. This may make the /// application code easier to read. /// /// By default, there is an abrupt transition between the output values /// from the two source modules at the selection-range boundary. To /// smooth the transition, pass a non-zero value to the setEdgeFalloff() /// method. Higher values result in a smoother transition. /// /// This noise module requires three source modules. /// Default edge-falloff value for the Select noise module. static final double DEFAULT_SELECT_EDGE_FALLOFF = 0.0; /// Default lower bound of the selection range for the /// Select noise module. static final double DEFAULT_SELECT_LOWER_BOUND = -1.0; /// Default upper bound of the selection range for the /// Select noise module. static final double DEFAULT_SELECT_UPPER_BOUND = 1.0; /// Edge-falloff value. double edgeFalloff; /// Lower bound of the selection range. double lowerBound; /// Upper bound of the selection range. double upperBound; public Select (ModuleBase sourceModuleOne, ModuleBase sourceModuleTwo, ModuleBase sourceModuleThree) throws ExceptionInvalidParam { super(3); setSourceModule(0, sourceModuleOne); setSourceModule(1, sourceModuleTwo); setSourceModule(2, sourceModuleThree); edgeFalloff = DEFAULT_SELECT_EDGE_FALLOFF; lowerBound = DEFAULT_SELECT_LOWER_BOUND; upperBound = DEFAULT_SELECT_UPPER_BOUND; } public double getValue (double x, double y, double z) { assert (sourceModules[0] != null); assert (sourceModules[1] != null); assert (sourceModules[2] != null); double controlValue = sourceModules[2].getValue (x, y, z); double alpha; if (edgeFalloff > 0.0) { if (controlValue < (lowerBound - edgeFalloff)) // The output value from the control module is below the selector // threshold; return the output value from the first source module. return sourceModules[0].getValue (x, y, z); else if (controlValue < (lowerBound + edgeFalloff)) { // The output value from the control module is near the lower end of the // selector threshold and within the smooth curve. Interpolate between // the output values from the first and second source modules. double lowerCurve = (lowerBound - edgeFalloff); double upperCurve = (lowerBound + edgeFalloff); alpha = Interp.SCurve3 ( (controlValue - lowerCurve) / (upperCurve - lowerCurve)); return Interp.linearInterp (sourceModules[0].getValue (x, y, z), sourceModules[2].getValue (x, y, z), alpha); } else if (controlValue < (upperBound - edgeFalloff)) // The output value from the control module is within the selector // threshold; return the output value from the second source module. return sourceModules[1].getValue (x, y, z); else if (controlValue < (upperBound + edgeFalloff)) { // The output value from the control module is near the upper end of the // selector threshold and within the smooth curve. Interpolate between // the output values from the first and second source modules. double lowerCurve = (upperBound - edgeFalloff); double upperCurve = (upperBound + edgeFalloff); alpha = Interp.SCurve3 ( (controlValue - lowerCurve) / (upperCurve - lowerCurve)); return Interp.linearInterp (sourceModules[1].getValue (x, y, z), sourceModules[0].getValue (x, y, z), alpha); } else // Output value from the control module is above the selector threshold; // return the output value from the first source module. return sourceModules[0].getValue (x, y, z); } else { if (controlValue < lowerBound || controlValue > upperBound) return sourceModules[0].getValue (x, y, z); else return sourceModules[1].getValue (x, y, z); } } /// Sets the lower and upper bounds of the selection range. /// /// @param lowerBound The lower bound. /// @param upperBound The upper bound. /// /// @pre The lower bound must be less than or equal to the upper /// bound. public void setBounds (double lowerBound, double upperBound) { assert (lowerBound < upperBound); this.lowerBound = lowerBound; this.upperBound = upperBound; // Make sure that the edge falloff curves do not overlap. setEdgeFalloff (edgeFalloff); } /// Sets the falloff value at the edge transition. /// /// @param edgeFalloff The falloff value at the edge transition. /// /// The falloff value is the width of the edge transition at either /// edge of the selection range. /// /// By default, there is an abrupt transition between the values from /// the two source modules at the boundaries of the selection range. /// /// For example, if the selection range is 0.5 to 0.8, and the edge /// falloff value is 0.1, then the getValue() method outputs: /// - the output value from the source module with an index value of 0 /// if the output value from the control module is less than 0.4 /// ( = 0.5 - 0.1). /// - a linear blend between the two output values from the two source /// modules if the output value from the control module is between /// 0.4 ( = 0.5 - 0.1) and 0.6 ( = 0.5 + 0.1). /// - the output value from the source module with an index value of 1 /// if the output value from the control module is between 0.6 /// ( = 0.5 + 0.1) and 0.7 ( = 0.8 - 0.1). /// - a linear blend between the output values from the two source /// modules if the output value from the control module is between /// 0.7 ( = 0.8 - 0.1 ) and 0.9 ( = 0.8 + 0.1). /// - the output value from the source module with an index value of 0 /// if the output value from the control module is greater than 0.9 /// ( = 0.8 + 0.1). public void setEdgeFalloff (double edgeFalloff) { // Make sure that the edge falloff curves do not overlap. double boundSize = upperBound - lowerBound; edgeFalloff = (edgeFalloff > boundSize / 2)? boundSize / 2: edgeFalloff; } /// Returns the control module. /// /// @returns A reference to the control module. /// /// @pre A control module has been added to this noise module via a /// call to setSourceModule() or setControlModule(). /// /// @throw ExceptionNoModule See the preconditions for more /// information. /// /// The control module determines the output value to select. If the /// output value from the control module is within a range of values /// known as the selection range, the getValue() method outputs /// the value from the source module with an index value of 1. /// Otherwise, this method outputs the value from the source module /// with an index value of 0. // not sure this does what it says it does. Recheck original source public ModuleBase getControlModule () throws ExceptionNoModule { if (sourceModules == null || sourceModules[2] == null) { throw new ExceptionNoModule ("Could not retrieve a source module from a noise module."); } return (sourceModules[2]); } /// Returns the falloff value at the edge transition. /// /// @returns The falloff value at the edge transition. /// /// The falloff value is the width of the edge transition at either /// edge of the selection range. /// /// By default, there is an abrupt transition between the output /// values from the two source modules at the selection-range /// boundary. public double getEdgeFalloff () { return edgeFalloff; } /// Returns the lower bound of the selection range. /// /// @returns The lower bound of the selection range. /// /// If the output value from the control module is within the /// selection range, the getValue() method outputs the value from the /// source module with an index value of 1. Otherwise, this method /// outputs the value from the source module with an index value of 0. public double getLowerBound () { return lowerBound; } /// Returns the upper bound of the selection range. /// /// @returns The upper bound of the selection range. /// /// If the output value from the control module is within the /// selection range, the getValue() method outputs the value from the /// source module with an index value of 1. Otherwise, this method /// outputs the value from the source module with an index value of 0. public double getUpperBound () { return upperBound; } /// Sets the control module. /// /// @param controlModule The control module. /// /// The control module determines the output value to select. If the /// output value from the control module is within a range of values /// known as the selection range, the getValue() method outputs /// the value from the source module with an index value of 1. /// Otherwise, this method outputs the value from the source module /// with an index value of 0. /// /// This method assigns the control module an index value of 2. /// Passing the control module to this method produces the same /// results as passing the control module to the setSourceModule() /// method while assigning that noise module an index value of 2. /// /// This control module must exist throughout the lifetime of this /// noise module unless another control module replaces that control /// module. public void setControlModule (ModuleBase controlModule) { assert (sourceModules != null); sourceModules[2] = controlModule; } }