package org.jwildfire.create.tina.variation; import org.jwildfire.base.Tools; import org.jwildfire.create.tina.base.Layer; import org.jwildfire.create.tina.base.XForm; import org.jwildfire.create.tina.base.XYZPoint; import static org.jwildfire.base.mathlib.MathLib.*; public class Hourglass3DFunc extends VariationFunc { private static final long serialVersionUID = 1L; private static final String PARAM_KX = "kx"; private static final String PARAM_KY = "ky"; private static final String PARAM_KZ = "kz"; private static final String PARAM_MAXHEIGHT = "maxheight"; private static final String PARAM_USELIMIT = "uselimit"; private static final String PARAM_ZERO_EDGES = "zero_edges"; private static final String[] paramNames = {PARAM_KX, PARAM_KY, PARAM_KX, PARAM_MAXHEIGHT, PARAM_USELIMIT, PARAM_ZERO_EDGES}; private double kx = 1.0; private double ky = 1.0; private double kz = 1.0; private double maxheight = 3.0; private int limit = 1; private int zero = 0; private double vkx, vky, vkz, h, hb; @Override public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) { vkx = pAmount * kx; vky = pAmount * ky; vkz = pAmount * kz; h = sqrt(1 + sqr(maxheight / ky)); hb = sqrt(sqr(h) - 1); } @Override public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) { double sn, cn, sh, ch; sn = sin(pAffineTP.x); cn = cos(pAffineTP.x); sh = sinh(pAffineTP.y); ch = cosh(pAffineTP.y); if (limit == 0) { // Function pVarTP.x += vkx * ch * sn; pVarTP.y += vky * sh; pVarTP.z += vkz * ch * cn; } else if (zero == 0) { // CutBorder if (ch < h) { // cut the surface pVarTP.x += vkx * ch * sn; pVarTP.y += vky * sh; pVarTP.z += vkz * ch * cn; } else { // place the point on it's boarder pVarTP.x += vkx * h * sn; pVarTP.y += vky * sign(sh) * hb; pVarTP.z += vkz * h * cn; } } else { // Cut if (ch < h) { // cut the surface pVarTP.x += vkx * ch * sn; pVarTP.y += vky * sh; pVarTP.z += vkz * ch * cn; } } } @Override public String[] getParameterNames() { return paramNames; } @Override public Object[] getParameterValues() { return new Object[]{kx, ky, kz, maxheight, limit, zero}; } @Override public void setParameter(String pName, double pValue) { if (PARAM_KX.equalsIgnoreCase(pName)) kx = (pValue < 1E-5) ? 1E-5 : pValue; else if (PARAM_KY.equalsIgnoreCase(pName)) ky = (pValue < 1E-5) ? 1E-5 : pValue; else if (PARAM_KZ.equalsIgnoreCase(pName)) kz = (pValue < 1E-5) ? 1E-5 : pValue; else if (PARAM_MAXHEIGHT.equalsIgnoreCase(pName)) maxheight = (pValue < 0.1) ? 0.1 : pValue; else if (PARAM_USELIMIT.equalsIgnoreCase(pName)) limit = limitIntVal(Tools.FTOI(pValue), 0, 1); else if (PARAM_ZERO_EDGES.equalsIgnoreCase(pName)) zero = limitIntVal(Tools.FTOI(pValue), 0, 1); else throw new IllegalArgumentException(pName); } public String getName() { return "hourglass3D"; } public VariationFuncType[] getVariationTypes() { // return new VariationFuncType[]{VariationFuncType.VARTYPE_3D, VariationFuncType.VARTYPE_SUPPORTS_GPU}; return new VariationFuncType[]{VariationFuncType.VARTYPE_3D}; } }