/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2011 Andreas Maschke
This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This software 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this software;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.variation;
import static org.jwildfire.base.mathlib.MathLib.M_PI;
import static org.jwildfire.base.mathlib.MathLib.fabs;
import static org.jwildfire.base.mathlib.MathLib.fmod;
import static org.jwildfire.base.mathlib.MathLib.sin;
import static org.jwildfire.base.mathlib.MathLib.cos;
import static org.jwildfire.base.mathlib.MathLib.tan;
import static org.jwildfire.base.mathlib.MathLib.sqr;
import static org.jwildfire.base.mathlib.MathLib.sqrt;
import org.jwildfire.base.Tools;
import static org.jwildfire.base.mathlib.MathLib.log;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;
public class DCGnarlyFunc extends VariationFunc {
private static final long serialVersionUID = 1L;
private static final String PARAM_MODE = "mode";
private static final String PARAM_SCALEX = "scalex";
private static final String PARAM_SCALEY = "scaley";
private static final String PARAM_FREQX1 = "freqx1";
private static final String PARAM_FREQY1 = "freqy1";
private static final String PARAM_FREQX2 = "freqx2";
private static final String PARAM_FREQY2 = "freqy2";
private static final String PARAM_FREQX3 = "freqx3";
private static final String PARAM_FREQY3 = "freqy3";
private static final String PARAM_DC = "dc";
private static final String PARAM_COLOR1 = "color1";
private static final String PARAM_COLOR2 = "color2";
private static final String PARAM_FMAG = "fmag";
private static final String PARAM_DISTORT = "distort";
private static final String PARAM_BLUR = "blur";
private static final String PARAM_SCALEZ = "scale_z";
private static final String PARAM_OFFSETZ = "offset_z";
private static final String PARAM_RESETZ = "reset_z";
private static final String[] paramNames = { PARAM_MODE, PARAM_SCALEX, PARAM_SCALEY, PARAM_FREQX1, PARAM_FREQY1,
PARAM_FREQX2, PARAM_FREQY2, PARAM_FREQX3, PARAM_FREQY3, PARAM_DC, PARAM_COLOR1, PARAM_COLOR2,
PARAM_FMAG, PARAM_DISTORT, PARAM_BLUR, PARAM_SCALEZ, PARAM_OFFSETZ, PARAM_RESETZ };
private int mode = 1;
private double scalex = 0.05;
private double scaley = 0.05;
private double freqx1 = 3.5;
private double freqy1 = 3.5;
private double freqx2 = 2;
private double freqy2 = 2;
private double freqx3 = 5;
private double freqy3 = 5;
private int dc = 1;
private double color1 = 5;
private double color2 = 5;
private double fmag = 1;
private double distort = 0.0;
private double blur = 5.0;
private double scale_z = 0.0;
private double offset_z = 0.0;
private int reset_z = 0;
private final double gauss_rnd[] = new double[6];
private int gauss_N;
@Override
public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
// dc_gnarly by Brad Stefanov and Rick Sidwell
// inspired by techniques and formulas by Tatyana Zabanova, Georg Kiehne, Clifford Pickover, and Mark Townsend
double x0 = pAffineTP.x;
double y0 = pAffineTP.y;
if (blur > 0) {
double r = pContext.random() * 2 * M_PI;
double sina = sin(r);
double cosa = cos(r);
r = blur * (gauss_rnd[0] + gauss_rnd[1] + gauss_rnd[2] + gauss_rnd[3] + gauss_rnd[4] + gauss_rnd[5] - 3);
gauss_rnd[gauss_N] = pContext.random();
gauss_N = (gauss_N + 1) & 5;
x0 += r * cosa;
y0 += r * sina;
}
else if (blur < 0) {
x0 += pContext.random() * blur * 2 - blur;
y0 += pContext.random() * blur * 2 - blur;
}
double x1, y1;
switch (mode) {
case 1:
x1 = cos(freqx1 * y0 + sin(freqx2 * (y0 + sin(freqx3 * y0)))) * scalex;
y1 = cos(freqy1 * x0 + sin(freqy2 * (x0 + sin(freqy3 * x0)))) * scaley;
break;
case 2:
x1 = sin(freqx1 * y0 + sin(freqx2 * (y0 + cos(freqx3 * y0)))) * scalex;
y1 = sin(freqy1 * x0 + sin(freqy2 * (x0 + cos(freqy3 * x0)))) * scaley;
break;
case 3:
x1 = cos(freqx1 * y0 + sin(freqx2 * (x0 + sin(freqx3 * y0)))) * scalex;
y1 = cos(freqy1 * x0 + sin(freqy2 * (y0 + sin(freqy3 * x0)))) * scaley;
break;
case 4:
x1 = sin(freqx1 * y0 + sin(sqrt(fabs(freqx2 * (y0 + cos(freqx3 * y0)))))) * scalex;
y1 = sin(freqy1 * x0 + sin(sqrt(fabs(freqy2 * (x0 + cos(freqy3 * x0)))))) * scaley;
break;
case 5:
x1 = cos(freqx1 * y0 + asinh(freqx2 * (y0 + sin(freqx3 * y0)))) * scalex;
y1 = cos(freqy1 * x0 + asinh(freqy2 * (x0 + sin(freqy3 * x0)))) * scaley;
break;
case 6:
x1 = cos(freqx1 * y0 + tan(freqx2 * (y0 + sin(freqx3 * y0)))) * scalex;
y1 = cos(freqy1 * x0 + tan(freqy2 * (x0 + sin(freqy3 * x0)))) * scaley;
break;
case 7:
x1 = sin(freqx1 * y0 + sin(sqr(freqx2 * (y0 + cos(freqx3 * y0))))) * scalex;
y1 = sin(freqy1 * x0 + sin(sqr(freqy2 * (x0 + cos(freqy3 * x0))))) * scaley;
break;
case 8:
x1 = sin(freqx1 * y0 + sin(sqr(freqx2 * (x0 + cos(freqx3 * y0))))) * scalex;
y1 = sin(freqy1 * x0 + sin(sqr(freqy2 * (y0 + cos(freqy3 * x0))))) * scaley;
break;
default:
x1 = sin(freqx1 * y0) * scalex;
y1 = sin(freqy1 * x0) * scaley;
break;
}
double s1 = log(sqrt(sqr(x1) + sqr(y1))) * distort;
pVarTP.x += pAmount * (x0 + x1) / 2;
pVarTP.y += pAmount * (y0 + y1) / 2;
if (dc != 0) {
pVarTP.color = fmod(fabs(cos(x0 + x1 * color1 + s1) + sin(y0 + y1 * color2 + s1)), fmag);
}
double dz = pVarTP.color * scale_z + offset_z;
if (reset_z > 0) {
pVarTP.z = dz;
}
else {
pVarTP.z += dz;
}
}
@Override
public String[] getParameterNames() {
return paramNames;
}
@Override
public Object[] getParameterValues() {
return new Object[] { mode, scalex, scaley, freqx1, freqy1, freqx2, freqy2, freqx3, freqy3,
dc, color1, color2, fmag, distort, blur, scale_z, offset_z, reset_z };
}
@Override
public void setParameter(String pName, double pValue) {
if (PARAM_MODE.equalsIgnoreCase(pName))
mode = Tools.limitValue(Tools.FTOI(pValue), 0, 8);
else if (PARAM_SCALEX.equalsIgnoreCase(pName))
scalex = pValue;
else if (PARAM_SCALEY.equalsIgnoreCase(pName))
scaley = pValue;
else if (PARAM_FREQX1.equalsIgnoreCase(pName))
freqx1 = pValue;
else if (PARAM_FREQY1.equalsIgnoreCase(pName))
freqy1 = pValue;
else if (PARAM_FREQX2.equalsIgnoreCase(pName))
freqx2 = pValue;
else if (PARAM_FREQY2.equalsIgnoreCase(pName))
freqy2 = pValue;
else if (PARAM_FREQX3.equalsIgnoreCase(pName))
freqx3 = pValue;
else if (PARAM_FREQY3.equalsIgnoreCase(pName))
freqy3 = pValue;
else if (PARAM_DC.equalsIgnoreCase(pName))
dc = Tools.limitValue(Tools.FTOI(pValue), 0, 1);
else if (PARAM_COLOR1.equalsIgnoreCase(pName))
color1 = pValue;
else if (PARAM_COLOR2.equalsIgnoreCase(pName))
color2 = pValue;
else if (PARAM_FMAG.equalsIgnoreCase(pName))
fmag = Tools.limitValue(pValue, 0.05, 1);
else if (PARAM_DISTORT.equalsIgnoreCase(pName))
distort = pValue;
else if (PARAM_BLUR.equalsIgnoreCase(pName))
blur = pValue;
else if (PARAM_SCALEZ.equalsIgnoreCase(pName))
scale_z = pValue;
else if (PARAM_OFFSETZ.equalsIgnoreCase(pName))
offset_z = pValue;
else if (PARAM_RESETZ.equalsIgnoreCase(pName))
reset_z = Tools.limitValue(Tools.FTOI(pValue), 0, 1);
else
throw new IllegalArgumentException(pName);
}
@Override
public String getName() {
return "dc_gnarly";
}
@Override
public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) {
gauss_rnd[0] = pContext.random();
gauss_rnd[1] = pContext.random();
gauss_rnd[2] = pContext.random();
gauss_rnd[3] = pContext.random();
gauss_rnd[4] = pContext.random();
gauss_rnd[5] = pContext.random();
gauss_N = 0;
}
public static double asinh(double x) {
return log(x + sqrt(x * x + 1.0));
}
}
Comments