All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.flowpowered.noise.module.combiner.Select Maven / Gradle / Ivy

/*
 * This file is part of Flow Noise, licensed under the MIT License (MIT).
 *
 * Copyright (c) 2013 Flow Powered 
 * Original libnoise in C++ by Jason Bevins 
 * jlibnoise Java port by Garrett Fleenor 
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.flowpowered.noise.module.combiner;

import com.flowpowered.noise.Utils;
import com.flowpowered.noise.exception.NoModuleException;
import com.flowpowered.noise.module.Module;

public class Select extends Module {
    // Default edge-falloff value for the noise::module::Select noise module.
    public static final double DEFAULT_SELECT_EDGE_FALLOFF = 0.0;
    // Default lower bound of the selection range for the
    // noise::module::Select noise module.
    public static final double DEFAULT_SELECT_LOWER_BOUND = -1.0;
    // Default upper bound of the selection range for the
    // noise::module::Select noise module.
    public static final double DEFAULT_SELECT_UPPER_BOUND = 1.0;
    // Edge-falloff value.
    private double edgeFalloff = DEFAULT_SELECT_EDGE_FALLOFF;
    // Lower bound of the selection range.
    private double lowerBound = DEFAULT_SELECT_LOWER_BOUND;
    // Upper bound of the selection range.
    private double upperBound = DEFAULT_SELECT_UPPER_BOUND;

    public Select() {
        super(3);
    }

    public Module getControlModule() {
        if (sourceModule == null || sourceModule[2] == null) {
            throw new NoModuleException();
        }
        return sourceModule[2];
    }

    public void setControlModule(Module m) {
        if (m == null) {
            throw new IllegalArgumentException("the module cannot be null");
        }
        sourceModule[2] = m;
    }

    public double getEdgeFalloff() {
        return edgeFalloff;
    }

    public void setEdgeFalloff(double edgeFalloff) {
        // Make sure that the edge falloff curves do not overlap.
        double boundSize = upperBound - lowerBound;
        this.edgeFalloff = (edgeFalloff > boundSize / 2) ? boundSize / 2 : edgeFalloff;
    }

    public double getLowerBound() {
        return lowerBound;
    }

    public double getUpperBound() {
        return upperBound;
    }

    public void setBounds(double upper, double lower) {
        if (lower > upper) {
            throw new IllegalArgumentException("lower must be less than upper");
        }
        this.lowerBound = lower;
        this.upperBound = upper;

        setEdgeFalloff(edgeFalloff);
    }

    @Override
    public int getSourceModuleCount() {
        return 3;
    }

    @Override
    public double getValue(double x, double y, double z) {
        if (sourceModule[0] == null) {
            throw new NoModuleException();
        }
        if (sourceModule[1] == null) {
            throw new NoModuleException();
        }
        if (sourceModule[2] == null) {
            throw new NoModuleException();
        }

        double controlValue = sourceModule[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 sourceModule[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 = Utils.sCurve3((controlValue - lowerCurve) / (upperCurve - lowerCurve));
                return Utils.linearInterp(sourceModule[0].getValue(x, y, z), sourceModule[1].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 sourceModule[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 = Utils.sCurve3((controlValue - lowerCurve) / (upperCurve - lowerCurve));
                return Utils.linearInterp(sourceModule[1].getValue(x, y, z), sourceModule[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 sourceModule[0].getValue(x, y, z);
            }
        } else {
            if (controlValue < lowerBound || controlValue > upperBound) {
                return sourceModule[0].getValue(x, y, z);
            } else {
                return sourceModule[1].getValue(x, y, z);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy