/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2014 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.iflames; import static org.jwildfire.base.mathlib.MathLib.EPSILON; import static org.jwildfire.base.mathlib.MathLib.fabs; import java.util.List; import org.jwildfire.base.Prefs; import org.jwildfire.base.mathlib.MathLib; import org.jwildfire.create.tina.base.Flame; import org.jwildfire.create.tina.base.Layer; import org.jwildfire.create.tina.base.XForm; import org.jwildfire.create.tina.base.XYZPoint; import org.jwildfire.create.tina.dance.model.AnimationModelService; import org.jwildfire.create.tina.dance.model.FlamePropertyPath; import org.jwildfire.create.tina.io.FlameReader; import org.jwildfire.create.tina.io.FlameWriter; import org.jwildfire.create.tina.variation.FlameTransformationContext; import org.jwildfire.create.tina.variation.SubFlameWFFunc; import org.jwildfire.create.tina.variation.VariationFunc; public class IFlamesIterator { private final XYZPoint affine, var, ifsPoint; private final VariationFunc fnc; private final XForm xform; private final FlameTransformationContext flameTransformationContext; private final FlameParams params; private final double rotateMatrix[][] = new double[3][3]; public final static IFlamesIterator BLANK = new IFlamesIterator(); public IFlamesIterator(FlameTransformationContext pFlameTransformationContext, FlameParams pFlameParams, List<String> pParamNames, List<Double> pParamValues) { flameTransformationContext = pFlameTransformationContext; params = pFlameParams; affine = new XYZPoint(); var = new XYZPoint(); ifsPoint = new XYZPoint(); xform = new XForm(); fnc = new SubFlameWFFunc(); String flameXML = params.getFlameXML(); if (pParamNames != null && pParamNames.size() > 0) { try { Flame flame = new FlameReader(Prefs.getPrefs()).readFlamesfromXML(flameXML).get(0); for (int i = 0; i < pParamNames.size(); i++) { FlamePropertyPath path = new FlamePropertyPath(flame, pParamNames.get(i)); AnimationModelService.setFlameProperty(flame, path, pParamValues.get(i)); } flameXML = new FlameWriter().getFlameXML(flame); } catch (Exception ex) { ex.printStackTrace(); } } fnc.setRessource(SubFlameWFFunc.RESSOURCE_FLAME, flameXML.getBytes()); fnc.init(pFlameTransformationContext, new Layer(), xform, 1.0); } private IFlamesIterator() { affine = var = ifsPoint = null; fnc = null; xform = null; flameTransformationContext = null; params = null; } public void iterate(XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP) { fnc.transform(flameTransformationContext, pXForm, pAffineTP, pVarTP, 1.0); } public void iterate(XYZPoint pSrc, XYZPoint pDest, double pSize, double pAngleAlpha, double pAngleBeta, double pAngleGamma) { affine.clear(); var.clear(); double dr = pSize; double centreX = params.getCentreX(); double centreY = params.getCentreY(); fnc.transform(flameTransformationContext, xform, affine, var, 1.0); if (fabs(pAngleBeta) < EPSILON && fabs(pAngleGamma) < EPSILON) { double dx = var.x - centreX; double dy = var.y - centreY; double sina = MathLib.sin(pAngleAlpha); double cosa = MathLib.cos(pAngleAlpha); double rx = dx * cosa - dy * sina; double ry = dx * sina + dy * cosa; ifsPoint.x = rx * dr + centreX; ifsPoint.y = ry * dr + centreY; ifsPoint.z = var.z; } else { double sina = MathLib.sin(pAngleAlpha); double cosa = MathLib.cos(pAngleAlpha); double sinb = MathLib.sin(pAngleBeta); double cosb = MathLib.cos(pAngleBeta); double sing = MathLib.sin(pAngleGamma); double cosg = MathLib.cos(pAngleGamma); rotateMatrix[0][0] = cosb * cosa - sina * sinb * cosg; rotateMatrix[1][0] = -sinb * cosa - cosb * cosg * sina; rotateMatrix[2][0] = sina * sing; rotateMatrix[0][1] = cosb * sina + cosa * sinb * cosg; rotateMatrix[1][1] = -sinb * sina + cosb * cosg * cosa; rotateMatrix[2][1] = -cosa * sing; rotateMatrix[0][2] = sinb * sing; rotateMatrix[1][2] = cosb * sing; rotateMatrix[2][2] = cosg; double centreZ = params.getCentreZ(); double dx = (var.x - centreX) * dr; double dy = (var.y - centreY) * dr; double dz = (var.z - centreZ) * dr; ifsPoint.x = rotateMatrix[0][0] * dx + rotateMatrix[1][0] * dy + rotateMatrix[2][0] * dz + centreX; ifsPoint.y = rotateMatrix[0][1] * dx + rotateMatrix[1][1] * dy + rotateMatrix[2][1] * dz + centreY; ifsPoint.z = rotateMatrix[0][2] * dx + rotateMatrix[1][2] * dy + rotateMatrix[2][2] * dz + centreZ; } pDest.x = ifsPoint.x + pSrc.x; pDest.y = ifsPoint.y + pSrc.y; pDest.z = ifsPoint.z + pSrc.z; pDest.redColor = var.redColor; pDest.greenColor = var.greenColor; pDest.blueColor = var.blueColor; pDest.rgbColor = var.rgbColor; pDest.color = var.color; } }