package org.jwildfire.create.tina.variation;
import static org.jwildfire.base.mathlib.MathLib.cos;
import static org.jwildfire.base.mathlib.MathLib.fabs;
import static org.jwildfire.base.mathlib.MathLib.sin;
import static org.jwildfire.base.mathlib.MathLib.sqrt;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;
/*
* Original author dark-beam
* (see JWildfire forum post: http://jwildfire.org/forum/viewtopic.php?f=18&t=1444&p=3032)
* suggested/requested as full variation by Don Town
* transcribed, extended, and turned into full variation by CozyG
*
* WARNING: assumes centered on (0,0,0), can disapear if move too far off in pre-transforms etc.
*/
public class FlowerDbFunc extends VariationFunc {
private static final long serialVersionUID = 1L;
private static final String PARAM_PETALS = "petals";
private static final String PARAM_PETAL_SPLIT = "petal_split";
private static final String PARAM_PETAL_SPREAD = "petal_spread";
private static final String PARAM_STEM_THICKNESS = "stem_thickness";
private static final String PARAM_STEM_LENGTH = "stem_length";
private static final String PARAM_PETAL_FOLD_STRENGTH = "petal_fold_strength";
private static final String PARAM_PETAL_FOLD_RADIUS = "petal_fold_radius";
private static final String[] paramNames = { PARAM_PETALS, PARAM_PETAL_SPLIT, PARAM_PETAL_SPREAD, PARAM_STEM_THICKNESS, PARAM_STEM_LENGTH, PARAM_PETAL_FOLD_STRENGTH, PARAM_PETAL_FOLD_RADIUS };
// non-integer petals is possible, changes relative size of petals
private double petals = 6;
// non-integer petal_splits are possible, changes relative size of petals
private double petal_split = 0;
private double petal_spread = 1;
private double stem_thickness = 1;
// default stem_length of 0 is considered special case,
// if stem_length = 0, then stem length doesn't truncate, so extends "infinitely" while fading away
private double stem_length = 0;
// how strong (added angle) the fold is, positive value fold up, negative values fold down
private double petal_fold_strength = 0;
// how far out along the petals the fold happens
private double petal_fold_radius = 1;
public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
double r = pAmount * sqrt(pAffineTP.getPrecalcSumsq());
double t = pAffineTP.getPrecalcAtanYX();
r = r * (fabs((petal_spread + sin(petals * t)) * cos(petal_split * petals * t)));
pVarTP.x += sin(t) * r;
pVarTP.y += cos(t) * r;
pVarTP.z -= stem_thickness * ((2.0 / r) - 1.0);
double rnew = sqrt((pVarTP.x * pVarTP.x) + (pVarTP.y * pVarTP.y));
if (rnew > petal_fold_radius) {
pVarTP.z += (rnew - petal_fold_radius) * petal_fold_strength;
}
if ((stem_length != 0) && (pVarTP.z <= (-1 * stem_length))) {
pVarTP.z = (-1 * stem_length);
}
}
@Override
public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) {
}
@Override
public String[] getParameterNames() {
return paramNames;
}
@Override
public Object[] getParameterValues() {
return new Object[] { petals, petal_split, petal_spread, stem_thickness, stem_length, petal_fold_strength, petal_fold_radius };
}
@Override
public void setParameter(String pName, double pValue) {
if (PARAM_PETALS.equalsIgnoreCase(pName))
petals = pValue;
else if (PARAM_PETAL_SPLIT.equalsIgnoreCase(pName))
petal_split = pValue;
else if (PARAM_PETAL_SPREAD.equalsIgnoreCase(pName))
petal_spread = pValue;
else if (PARAM_STEM_THICKNESS.equalsIgnoreCase(pName))
stem_thickness = pValue;
else if (PARAM_STEM_LENGTH.equalsIgnoreCase(pName))
stem_length = pValue;
else if (PARAM_PETAL_FOLD_STRENGTH.equalsIgnoreCase(pName))
petal_fold_strength = pValue;
else if (PARAM_PETAL_FOLD_RADIUS.equalsIgnoreCase(pName))
petal_fold_radius = pValue;
else
throw new IllegalArgumentException(pName);
}
@Override
public String getName() {
return "flower_db";
}
}