/*
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.cos;
import static org.jwildfire.base.mathlib.MathLib.sin;
import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;
/**
* @author Nicolaus Anderson
*/
public class SphereNjaFunc extends VariationFunc {
private static final long serialVersionUID = 1L;
private static final String PARAM_CIRCLE_A = "circle_a";
private static final String PARAM_CIRCLE_B = "circle_b";
private static final String PARAM_SHIFT_X = "shift_x";
private static final String PARAM_SHIFT_Y = "shift_y";
private static final String PARAM_SHIFT_Z = "shift_z";
private static final String PARAM_STRETCH = "stretch";
private static final String[] paramNames = { PARAM_CIRCLE_A, PARAM_CIRCLE_B, PARAM_SHIFT_X, PARAM_SHIFT_Y, PARAM_SHIFT_Z, PARAM_STRETCH };
private double circle_a = 1.0;
private double circle_b = 1.0;
private double shift_x = 0.0;
private double shift_y = 0.0;
private double shift_z = 0.0;
private double stretch = 1.0;
@Override
public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
/* Description:
The transform creates a sphere by converting the x and y values to a radius,
which becomes "t" for a parametric equation.
*/
// Initial coordinates
XYZPoint ini = new XYZPoint();
ini.x = pAffineTP.x;
ini.y = pAffineTP.y;
ini.z = pAffineTP.z;
ini.x -= shift_x;
ini.y -= shift_y;
//ini.z -= shift_z;
ini.invalidate();
/* Convert x and y of point to parametric space,
noting they are the radius outward in real space. */
double t = ini.getPrecalcSqrt() / stretch - M_PI / 2;
// circular curve, expanded by pAmount
double r = cos(t) * pAmount;// * ini.getPrecalcSqrt();
double z = sin(t) * pAmount;// * ini.getPrecalcSqrt();
// Convert parametric space (2D) back to real space (3D)
/* A new coordinate equals the new factor times a unit vector in the
direction of the coordinate of interest. */
pVarTP.x += r * (ini.x / ini.getPrecalcSqrt());
pVarTP.y += r * (ini.y / ini.getPrecalcSqrt());
pVarTP.z += z;
if (pContext.isPreserveZCoordinate()) {
// (this should cause positive z values to curl inside the sphere)
/* Treating z as a vector that is split into two components, one being
an x-component of parametric space which becomes a new radius for
real space, taking into account conversion through unit vectors */
pVarTP.x += r * ini.z * (ini.x / ini.getPrecalcSqrt());
pVarTP.y += r * ini.z * (ini.y / ini.getPrecalcSqrt());
/* The z-component is a normalized value from the parametric space y
(which is real space z), taking into account the amount that went into
the x component. */
pVarTP.z += ini.z * z / (r * r + z * z);
}
pVarTP.x += shift_x;
pVarTP.y += shift_y;
//pVarTP.z += shift_z;
}
@Override
public String[] getParameterNames() {
return paramNames;
}
@Override
public Object[] getParameterValues() {
return new Object[] { circle_a, circle_b, shift_x, shift_y, shift_z, stretch };
}
@Override
public void setParameter(String pName, double pValue) {
if (PARAM_CIRCLE_A.equalsIgnoreCase(pName))
circle_a = pValue;
else if (PARAM_CIRCLE_B.equalsIgnoreCase(pName))
circle_b = pValue;
else if (PARAM_SHIFT_X.equalsIgnoreCase(pName))
shift_x = pValue;
else if (PARAM_SHIFT_Y.equalsIgnoreCase(pName))
shift_y = pValue;
else if (PARAM_SHIFT_Z.equalsIgnoreCase(pName))
shift_z = pValue;
else if (PARAM_STRETCH.equalsIgnoreCase(pName))
stretch = pValue;
else
throw new IllegalArgumentException(pName);
}
@Override
public String getName() {
return "sphere_nja";
}
}