/* 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.sin; import static org.jwildfire.base.mathlib.MathLib.trunc; import org.jwildfire.create.tina.base.Layer; import org.jwildfire.create.tina.base.XForm; import org.jwildfire.create.tina.base.XYZPoint; public class Hexaplay3DFunc extends VariationFunc { private static final long serialVersionUID = 1L; private double _seg60x[] = new double[6]; private double _seg60y[] = new double[6]; private double _seg120x[] = new double[3]; private double _seg120y[] = new double[3]; private int _rswtch; // A value for choosing between 6 or 3 segments to a plane private int _fcycle; // markers to count cycles... private int _bcycle; private static final String PARAM_MAJP = "majp"; private static final String PARAM_SCALE = "scale"; private static final String PARAM_ZLIFT = "zlift"; private static final String[] paramNames = { PARAM_MAJP, PARAM_SCALE, PARAM_ZLIFT }; private double majp = 1.0; // establishes 1 or 2 planes, and if 2, the distance between them private double scale = 0.25; // scales the effect of X and Y private double zlift = 0.25; // scales the effect of Z axis within the snowflake @Override public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) { /* hexaplay3D by Larry Berlin, http://aporev.deviantart.com/art/3D-Plugins-Collection-One-138514007?q=gallery%3Aaporev%2F8229210&qo=15 */ if (this._fcycle > 5) { this._fcycle = 0; this._rswtch = (int) trunc(pContext.random() * 3.0); // Chooses new 6 or 3 nodes } if (this._bcycle > 2) { this._bcycle = 0; this._rswtch = (int) trunc(pContext.random() * 3.0); // Chooses new 6 or 3 nodes } double lrmaj = pAmount; // Sets hexagon length radius - major plane double boost = 0; // Boost is the separation distance between the two planes int posNeg = 1; int loc60; int loc120; double scale = this.scale * 0.5; if (pContext.random() < 0.5) { posNeg = -1; } // Determine whether one or two major planes int majplane = 1; double abmajp = fabs(this.majp); if (abmajp <= 1.0) { majplane = 1; // Want either 1 or 2 } else { majplane = 2; boost = (abmajp - 1.0) * 0.5; // distance above and below XY plane } // Creating Z factors relative to the planes if (majplane == 2) { pVarTP.z += pAffineTP.z * 0.5 * this.zlift + (posNeg * boost); } else { pVarTP.z += pAffineTP.z * 0.5 * this.zlift; } // Work out the segments and hexagonal nodes if (this._rswtch <= 1) { // Occasion to build using 60 degree segments //loc60 = trunc(pContext.random()*6.0); // random nodes selection loc60 = this._fcycle; // sequential nodes selection pVarTP.x = ((pVarTP.x + pAffineTP.x) * scale) + (lrmaj * _seg60x[loc60]); pVarTP.y = ((pVarTP.y + pAffineTP.y) * scale) + (lrmaj * _seg60y[loc60]); this._fcycle += 1; } else {// Occasion to build on 120 degree segments //loc120 = trunc(pContext.random()*3.0); // random nodes selection loc120 = this._bcycle; // sequential nodes selection pVarTP.x = ((pVarTP.x + pAffineTP.x) * scale) + (lrmaj * _seg120x[loc120]); pVarTP.y = ((pVarTP.y + pAffineTP.y) * scale) + (lrmaj * _seg120y[loc120]); this._bcycle += 1; } } @Override public String[] getParameterNames() { return paramNames; } @Override public Object[] getParameterValues() { return new Object[] { majp, scale, zlift }; } @Override public void setParameter(String pName, double pValue) { if (PARAM_MAJP.equalsIgnoreCase(pName)) majp = pValue; else if (PARAM_SCALE.equalsIgnoreCase(pName)) scale = pValue; else if (PARAM_ZLIFT.equalsIgnoreCase(pName)) zlift = pValue; else throw new IllegalArgumentException(pName); } @Override public String getName() { return "hexaplay3D"; } @Override public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) { /* Set up two major angle systems */ _rswtch = (int) trunc(pContext.random() * 3.0); // Chooses 6 or 3 nodes double hlift = sin(M_PI / 3.0); _fcycle = 0; _bcycle = 0; _seg60x[0] = 1.0; _seg60x[1] = 0.5; _seg60x[2] = -0.5; _seg60x[3] = -1.0; _seg60x[4] = -0.5; _seg60x[5] = 0.5; _seg60y[0] = 0.0; _seg60y[1] = hlift; _seg60y[2] = hlift; _seg60y[3] = 0.0; _seg60y[4] = -hlift; _seg60y[5] = -hlift; _seg120x[0] = 1.0; _seg120x[1] = -0.5; _seg120x[2] = -0.5; _seg120y[0] = 0.0; _seg120y[1] = hlift; _seg120y[2] = -hlift; } }