protected void parseXFormAttributes(Flame pFlame, XForm pXForm, String pXML) {
    XMLAttributes atts = Tools.parseAttributes(pXML);
    String hs;
    if ((hs = atts.get(ATTR_NAME)) != null) {
      pXForm.setName(hs);
    }
    if ((hs = atts.get(ATTR_WEIGHT)) != null) {
      pXForm.setWeight(Double.parseDouble(hs));
    }
    if ((hs = atts.get(ATTR_COLOR)) != null) {
      pXForm.setColor(Double.parseDouble(hs));
    }
    // legacy
    if ((hs = atts.get(ATTR_ANTIALIAS_AMOUNT)) != null) {
      double value = Double.parseDouble(hs);
      if (value > 0) pFlame.setAntialiasAmount(value);
    }
    // legacy
    if ((hs = atts.get(ATTR_ANTIALIAS_RADIUS)) != null) {
      double value = Double.parseDouble(hs);
      if (value > 0) pFlame.setAntialiasRadius(value);
    }
    if ((hs = atts.get(ATTR_OPACITY)) != null) {
      double opacity = Double.parseDouble(hs);
      pXForm.setOpacity(opacity);
      if (Math.abs(opacity) <= MathLib.EPSILON) {
        pXForm.setDrawMode(DrawMode.HIDDEN);
      } else if (Math.abs(opacity - 1.0) > MathLib.EPSILON) {
        pXForm.setDrawMode(DrawMode.OPAQUE);
      } else {
        pXForm.setDrawMode(DrawMode.NORMAL);
      }
    }
    if ((hs = atts.get(ATTR_SYMMETRY)) != null) {
      pXForm.setColorSymmetry(Double.parseDouble(hs));
    }
    if ((hs = atts.get(ATTR_COEFS)) != null) {
      String s[] = hs.split(" ");
      pXForm.setCoeff00(Double.parseDouble(s[0]));
      pXForm.setCoeff01(Double.parseDouble(s[1]));
      pXForm.setCoeff10(Double.parseDouble(s[2]));
      pXForm.setCoeff11(Double.parseDouble(s[3]));
      pXForm.setCoeff20(Double.parseDouble(s[4]));
      pXForm.setCoeff21(Double.parseDouble(s[5]));
    }
    if ((hs = atts.get(ATTR_POST)) != null) {
      String s[] = hs.split(" ");
      pXForm.setPostCoeff00(Double.parseDouble(s[0]));
      pXForm.setPostCoeff01(Double.parseDouble(s[1]));
      pXForm.setPostCoeff10(Double.parseDouble(s[2]));
      pXForm.setPostCoeff11(Double.parseDouble(s[3]));
      pXForm.setPostCoeff20(Double.parseDouble(s[4]));
      pXForm.setPostCoeff21(Double.parseDouble(s[5]));
    }
    if ((hs = atts.get(ATTR_CHAOS)) != null) {
      String s[] = hs.split(" ");
      for (int i = 0; i < s.length; i++) {
        pXForm.getModifiedWeights()[i] = Double.parseDouble(s[i]);
      }
    }
    // variations
    {
      List<String> variationNameList = VariationFuncList.getNameList();
      Map<String, String> aliasMap = VariationFuncList.getAliasMap();

      for (XMLAttribute attr : atts.getAttributes()) {
        String rawName = attr.getName();
        String name = removeIndexFromAttr(rawName);
        String varName = name;
        boolean hasVariation = variationNameList.indexOf(varName) >= 0;
        if (!hasVariation) {
          String aliasName = aliasMap.get(name);
          if (aliasName != null) {
            varName = aliasName;
            hasVariation = variationNameList.indexOf(varName) >= 0;
          }
        }
        if (hasVariation) {
          VariationFunc varFunc = VariationFuncList.getVariationFuncInstance(varName);
          Variation variation = pXForm.addVariation(Double.parseDouble(atts.get(name)), varFunc);
          // params
          {
            String paramNames[] = variation.getFunc().getParameterNames();
            String paramAltNames[] = variation.getFunc().getParameterAlternativeNames();
            if (paramNames != null) {
              if (paramAltNames != null && paramAltNames.length != paramNames.length) {
                paramAltNames = null;
              }
              for (int i = 0; i < paramNames.length; i++) {
                String pName = paramNames[i];
                String pHs;
                if ((pHs = atts.get(rawName + "_" + pName)) != null) {
                  variation.getFunc().setParameter(pName, Double.parseDouble(pHs));
                }
                // altNames can only be come from flames which were not created by JWF, so no need
                // to handle index here
                else if (paramAltNames != null && ((pHs = atts.get(paramAltNames[i])) != null)) {
                  variation.getFunc().setParameter(pName, Double.parseDouble(pHs));
                }
              }
            }
          }
          // ressources
          {
            String ressNames[] = variation.getFunc().getRessourceNames();
            if (ressNames != null) {
              for (String pName : ressNames) {
                String pHs;
                if ((pHs = atts.get(name + "_" + pName)) != null) {
                  variation.getFunc().setRessource(pName, Tools.hexStringToByteArray(pHs));
                }
              }
            }
          }
          //
        }
      }
    }
  }
Esempio n. 2
0
  private static XForm morphXForms(
      Prefs pPrefs, XForm pXForm1, XForm pXForm2, double pFScl, int pFrame, int pFrames) {
    pXForm1 = pXForm1.makeCopy();
    pXForm2 = pXForm2.makeCopy();
    prepareMorphXForm(pXForm1);
    prepareMorphXForm(pXForm2);
    XForm res = new XForm();
    res.setWeight(morphValue(pXForm1.getWeight(), pXForm2.getWeight(), pFScl));
    res.setColor(morphValue(pXForm1.getColor(), pXForm2.getColor(), pFScl));
    res.setColorSymmetry(morphValue(pXForm1.getColorSymmetry(), pXForm2.getColorSymmetry(), pFScl));
    res.setMaterial(morphValue(pXForm1.getMaterial(), pXForm2.getMaterial(), pFScl));
    res.setMaterialSpeed(morphValue(pXForm1.getMaterialSpeed(), pXForm2.getMaterialSpeed(), pFScl));

    res.setXYCoeff00(morphValue(pXForm1.getXYCoeff00(), pXForm2.getXYCoeff00(), pFScl));
    res.setXYCoeff01(morphValue(pXForm1.getXYCoeff01(), pXForm2.getXYCoeff01(), pFScl));
    res.setXYCoeff10(morphValue(pXForm1.getXYCoeff10(), pXForm2.getXYCoeff10(), pFScl));
    res.setXYCoeff11(morphValue(pXForm1.getXYCoeff11(), pXForm2.getXYCoeff11(), pFScl));
    res.setXYCoeff20(morphValue(pXForm1.getXYCoeff20(), pXForm2.getXYCoeff20(), pFScl));
    res.setXYCoeff21(morphValue(pXForm1.getXYCoeff21(), pXForm2.getXYCoeff21(), pFScl));

    res.setYZCoeff00(morphValue(pXForm1.getYZCoeff00(), pXForm2.getYZCoeff00(), pFScl));
    res.setYZCoeff01(morphValue(pXForm1.getYZCoeff01(), pXForm2.getYZCoeff01(), pFScl));
    res.setYZCoeff10(morphValue(pXForm1.getYZCoeff10(), pXForm2.getYZCoeff10(), pFScl));
    res.setYZCoeff11(morphValue(pXForm1.getYZCoeff11(), pXForm2.getYZCoeff11(), pFScl));
    res.setYZCoeff20(morphValue(pXForm1.getYZCoeff20(), pXForm2.getYZCoeff20(), pFScl));
    res.setYZCoeff21(morphValue(pXForm1.getYZCoeff21(), pXForm2.getYZCoeff21(), pFScl));

    res.setZXCoeff00(morphValue(pXForm1.getZXCoeff00(), pXForm2.getZXCoeff00(), pFScl));
    res.setZXCoeff01(morphValue(pXForm1.getZXCoeff01(), pXForm2.getZXCoeff01(), pFScl));
    res.setZXCoeff10(morphValue(pXForm1.getZXCoeff10(), pXForm2.getZXCoeff10(), pFScl));
    res.setZXCoeff11(morphValue(pXForm1.getZXCoeff11(), pXForm2.getZXCoeff11(), pFScl));
    res.setZXCoeff20(morphValue(pXForm1.getZXCoeff20(), pXForm2.getZXCoeff20(), pFScl));
    res.setZXCoeff21(morphValue(pXForm1.getZXCoeff21(), pXForm2.getZXCoeff21(), pFScl));

    res.setOpacity(morphValue(pXForm1.getOpacity(), pXForm2.getOpacity(), pFScl));

    res.setXYPostCoeff00(morphValue(pXForm1.getXYPostCoeff00(), pXForm2.getXYPostCoeff00(), pFScl));
    res.setXYPostCoeff01(morphValue(pXForm1.getXYPostCoeff01(), pXForm2.getXYPostCoeff01(), pFScl));
    res.setXYPostCoeff10(morphValue(pXForm1.getXYPostCoeff10(), pXForm2.getXYPostCoeff10(), pFScl));
    res.setXYPostCoeff11(morphValue(pXForm1.getXYPostCoeff11(), pXForm2.getXYPostCoeff11(), pFScl));
    res.setXYPostCoeff20(morphValue(pXForm1.getXYPostCoeff20(), pXForm2.getXYPostCoeff20(), pFScl));
    res.setXYPostCoeff21(morphValue(pXForm1.getXYPostCoeff21(), pXForm2.getXYPostCoeff21(), pFScl));

    res.setYZPostCoeff00(morphValue(pXForm1.getYZPostCoeff00(), pXForm2.getYZPostCoeff00(), pFScl));
    res.setYZPostCoeff01(morphValue(pXForm1.getYZPostCoeff01(), pXForm2.getYZPostCoeff01(), pFScl));
    res.setYZPostCoeff10(morphValue(pXForm1.getYZPostCoeff10(), pXForm2.getYZPostCoeff10(), pFScl));
    res.setYZPostCoeff11(morphValue(pXForm1.getYZPostCoeff11(), pXForm2.getYZPostCoeff11(), pFScl));
    res.setYZPostCoeff20(morphValue(pXForm1.getYZPostCoeff20(), pXForm2.getYZPostCoeff20(), pFScl));
    res.setYZPostCoeff21(morphValue(pXForm1.getYZPostCoeff21(), pXForm2.getYZPostCoeff21(), pFScl));

    res.setZXPostCoeff00(morphValue(pXForm1.getZXPostCoeff00(), pXForm2.getZXPostCoeff00(), pFScl));
    res.setZXPostCoeff01(morphValue(pXForm1.getZXPostCoeff01(), pXForm2.getZXPostCoeff01(), pFScl));
    res.setZXPostCoeff10(morphValue(pXForm1.getZXPostCoeff10(), pXForm2.getZXPostCoeff10(), pFScl));
    res.setZXPostCoeff11(morphValue(pXForm1.getZXPostCoeff11(), pXForm2.getZXPostCoeff11(), pFScl));
    res.setZXPostCoeff20(morphValue(pXForm1.getZXPostCoeff20(), pXForm2.getZXPostCoeff20(), pFScl));
    res.setZXPostCoeff21(morphValue(pXForm1.getZXPostCoeff21(), pXForm2.getZXPostCoeff21(), pFScl));

    res.setOpacity(morphValue(pXForm1.getOpacity(), pXForm2.getOpacity(), pFScl));
    res.setDrawMode(pFScl >= 0.5 ? pXForm2.getDrawMode() : pXForm1.getDrawMode());
    for (int i = 0; i < pXForm1.getModifiedWeights().length; i++) {
      res.getModifiedWeights()[i] =
          morphValue(pXForm1.getModifiedWeights()[i], pXForm2.getModifiedWeights()[i], pFScl);
    }
    res.clearVariations();
    List<Variation> vars1 = new ArrayList<Variation>();
    List<Variation> vars2 = new ArrayList<Variation>();

    HashMap<String, String> processed = new HashMap<String, String>();
    for (int i = 0; i < pXForm1.getVariationCount(); i++) {
      Variation var1 = pXForm1.getVariation(i);
      String fncName = var1.getFunc().getName();
      processed.put(fncName, fncName);
      vars1.add(var1);
      // search the same func in xForm2
      Variation var2 = null;
      for (int j = 0; j < pXForm2.getVariationCount(); j++) {
        var2 = pXForm2.getVariation(j);
        if (var2.getFunc().getName().equals(fncName)) {
          break;
        } else {
          var2 = null;
        }
      }
      if (var2 != null) {
        vars2.add(var2);
      } else {
        vars2.add(
            new Variation(
                0.0, VariationFuncList.getVariationFuncInstance(var1.getFunc().getName(), true)));
      }
    }
    for (int i = 0; i < pXForm2.getVariationCount(); i++) {
      Variation var2 = pXForm2.getVariation(i);
      String fncName = var2.getFunc().getName();
      if (processed.get(fncName) == null) {
        vars2.add(var2);
        vars1.add(
            new Variation(
                0.0, VariationFuncList.getVariationFuncInstance(var2.getFunc().getName(), true)));
      }
    }
    if (vars1.size() != vars2.size()) {
      throw new IllegalStateException();
    }
    for (int i = 0; i < vars1.size(); i++) {
      Variation var1 = vars1.get(i);
      Variation var2 = vars2.get(i);
      if (!var1.getFunc().getName().equals(var2.getFunc().getName())) {
        throw new IllegalStateException();
      }
      //      System.out.println(i + ": " + var1.getFunc().getName() + " " + var1.getAmount() + " "
      // + var2.getAmount());
      double amount = morphValue(var1.getAmount(), var2.getAmount(), pFScl);
      Variation var = res.addVariation(amount, var1.getFunc());
      //  params
      if (var.getFunc().getParameterNames() != null
          && var.getFunc().getParameterNames().length > 0) {
        Object val[] = var.getFunc().getParameterValues();
        Object val1[] = var1.getFunc().getParameterValues();
        Object val2[] = var2.getFunc().getParameterValues();
        for (int j = 0; j < var.getFunc().getParameterNames().length; j++) {
          String name = var.getFunc().getParameterNames()[j];
          if (val[j] instanceof Integer) {
            int mVal = morphValue((Integer) val1[j], (Integer) val2[j], pFScl);
            if (mVal == 0 && name.equals("power")) {
              mVal = 1;
            }
            //    int mVal = pFScl >= 0.5 ? (Integer) val2[j] : (Integer) val1[j];
            //          System.out.println("  " + name + " " + mVal + " (" + val1[j] + " " + val2[j]
            // + ")");
            var.getFunc().setParameter(name, mVal);
          } else if (val[j] instanceof Double) {
            double mVal = morphValue((Double) val1[j], (Double) val2[j], pFScl);
            //          System.out.println("  " + name + " " + mVal + " (" + val1[j] + " " + val2[j]
            // + ")");
            var.getFunc().setParameter(name, mVal);
          } else {
            throw new IllegalStateException();
          }
        }
      }
      // ressources
      if (var.getFunc().getRessourceNames() != null
          && var.getFunc().getRessourceNames().length > 0) {
        Object ress1[] = var1.getFunc().getRessourceValues();
        Object ress2[] = var2.getFunc().getRessourceValues();
        for (int j = 0; j < var.getFunc().getRessourceNames().length; j++) {
          String name = var.getFunc().getRessourceNames()[j];
          if (name.equalsIgnoreCase(SubFlameWFFunc.RESSOURCE_FLAME)
              && var.getFunc().getName().indexOf("subflame_wf") >= 0) {
            String flame1XML = new String((byte[]) ress1[j]);
            String flame2XML = new String((byte[]) ress2[j]);
            try {
              Flame flame1 = new FlameReader(pPrefs).readFlamesfromXML(flame1XML).get(0);
              Flame flame2 = new FlameReader(pPrefs).readFlamesfromXML(flame2XML).get(0);
              Flame morphedFlame =
                  morphFlames(pPrefs, FlameMorphType.MORPH, flame1, flame2, pFrame, pFrames);
              String morphedFlameXML = new FlameWriter().getFlameXML(morphedFlame);
              var.getFunc()
                  .setRessource(SubFlameWFFunc.RESSOURCE_FLAME, morphedFlameXML.getBytes());
            } catch (Exception ex) {
              ex.printStackTrace();
            }
          }
        }
      }
    }
    return res;
  }
Esempio n. 3
0
  private static Flame morphFlames_morph(
      Prefs pPrefs, Flame pFlame1, Flame pFlame2, int pFrame, int pFrames) {
    if (pFrame < 1 || pFrames < 2) return pFlame1;
    double fScl = (double) (pFrame - 1) / (pFrames - 1);
    if (fScl <= MathLib.EPSILON) {
      return pFlame1;
    } else if (fScl >= 1.0 - MathLib.EPSILON) {
      return pFlame2;
    }
    Flame res = pFlame1.makeCopy();
    res.getLayers().clear();
    int layerSize1 = pFlame1.getLayers().size();
    int layerSize2 = pFlame2.getLayers().size();
    int maxLayerSize = layerSize1 > layerSize2 ? layerSize1 : layerSize2;
    for (int lIdx = 0; lIdx < maxLayerSize; lIdx++) {
      Layer layer = new Layer();
      res.getLayers().add(layer);
      // Morph layers
      if (lIdx < layerSize1 && lIdx < layerSize2) {
        Layer layer1 = pFlame1.getLayers().get(lIdx);
        Layer layer2 = pFlame2.getLayers().get(lIdx);
        layer.assign(layer1);
        layer.getXForms().clear();
        layer.getFinalXForms().clear();
        layer.setWeight(morphValue(layer1.getWeight(), layer2.getWeight(), fScl));
        // morph XForms
        {
          int size1 = layer1.getXForms().size();
          int size2 = layer2.getXForms().size();
          int maxSize = size1 > size2 ? size1 : size2;
          for (int i = 0; i < maxSize; i++) {
            XForm xForm1 = i < size1 ? layer1.getXForms().get(i) : null;
            if (xForm1 == null) {
              xForm1 = new XForm();
              xForm1.addVariation(
                  0.0, VariationFuncList.getVariationFuncInstance("linear3D", true));
              xForm1.setWeight(0.0);
            }

            XForm xForm2 = i < size2 ? layer2.getXForms().get(i) : null;
            if (xForm2 == null) {
              xForm2 = new XForm();
              xForm2.addVariation(
                  0.0, VariationFuncList.getVariationFuncInstance("linear3D", true));
              xForm2.setWeight(0.0);
            }

            XForm morphedXForm = morphXForms(pPrefs, xForm1, xForm2, fScl, pFrame, pFrames);
            layer.getXForms().add(morphedXForm);
          }
        }
        // morph final XForms
        {
          int size1 = layer1.getFinalXForms().size();
          int size2 = layer2.getFinalXForms().size();
          int maxSize = size1 > size2 ? size1 : size2;
          for (int i = 0; i < maxSize; i++) {
            XForm xForm1 = i < size1 ? layer1.getFinalXForms().get(i) : null;
            if (xForm1 == null) {
              xForm1 = new XForm();
              xForm1.addVariation(
                  0.0, VariationFuncList.getVariationFuncInstance("linear3D", true));
              xForm1.setWeight(0.0);
            }

            XForm xForm2 = i < size2 ? layer2.getFinalXForms().get(i) : null;
            if (xForm2 == null) {
              xForm2 = new XForm();
              xForm2.addVariation(
                  0.0, VariationFuncList.getVariationFuncInstance("linear3D", true));
              xForm2.setWeight(0.0);
            }

            XForm morphedXForm = morphXForms(pPrefs, xForm1, xForm2, fScl, pFrame, pFrames);
            layer.getFinalXForms().add(morphedXForm);
          }
        }
        // morph colors
        RGBPalette palette1 = layer1.getPalette();
        RGBPalette palette2 = layer2.getPalette();
        for (int i = 0; i < RGBPalette.PALETTE_SIZE; i++) {
          RGBColor color1 = palette1.getColor(i);
          RGBColor color2 = palette2.getColor(i);
          int red = Tools.roundColor(color1.getRed() + (color2.getRed() - color1.getRed()) * fScl);
          int green =
              Tools.roundColor(color1.getGreen() + (color2.getGreen() - color1.getGreen()) * fScl);
          int blue =
              Tools.roundColor(color1.getBlue() + (color2.getBlue() - color1.getBlue()) * fScl);
          layer.getPalette().setColor(i, red, green, blue);
        }
      }
      // fade out layer1 to black
      else if (lIdx < layerSize1) {
        Layer layer1 = pFlame1.getLayers().get(lIdx);
        layer.assign(layer1);
        layer.setWeight(morphValue(layer1.getWeight(), 0.0, fScl));
      }
      // fade in layer2 from black
      else if (lIdx < layerSize2) {
        Layer layer2 = pFlame2.getLayers().get(lIdx);
        layer.assign(layer2);
        layer.setWeight(morphValue(0.0, layer2.getWeight(), fScl));
      }
    }
    // morph camera settings etc.
    morphFlameValues(pFlame1, pFlame2, fScl, res);
    return res;
  }
  @Override
  public Flame prepareFlame(RandomFlameGeneratorState pState) {
    Flame flame = new Flame();
    Layer layer = flame.getFirstLayer();
    flame.setCamRoll(0);
    flame.setCamPitch(90.0 - Math.random() * 180.0);
    flame.setCamYaw(30.0 - Math.random() * 60.0);
    flame.setCamPerspective(Math.random() * 0.2);
    flame.setWidth(601);
    flame.setHeight(338);
    flame.setPixelsPerUnit(92.48366013);
    flame.setCamZoom(0.3 + Math.random() * 0.5);

    randomizeSolidRenderingSettings(flame);

    layer.getFinalXForms().clear();
    layer.getXForms().clear();

    // create transform 1
    {
      XForm xForm = new XForm();
      layer.getXForms().add(xForm);
      xForm.setWeight(0.5);
      xForm.setColor(Math.random());
      xForm.setColorSymmetry(1.0 - 2 * Math.random());
      xForm.setMaterial(0);
      xForm.setMaterialSpeed(0);

      xForm.setCoeff00(1); // a
      xForm.setCoeff10(0); // b
      xForm.setCoeff20(0); // e
      xForm.setCoeff01(0); // c
      xForm.setCoeff11(1); // d
      xForm.setCoeff21(0); // f

      xForm.setPostCoeff00(1);
      xForm.setPostCoeff10(0);
      xForm.setPostCoeff01(0);
      xForm.setPostCoeff11(1);
      xForm.setPostCoeff20(0);
      xForm.setPostCoeff21(0);

      if (Math.random() > 0.125) {
        xForm.setDrawMode(DrawMode.HIDDEN);
      }

      // variation 1
      xForm.addVariation(0.2 + Math.random(), getRandom3DShape());
      // set default edit plane
      flame.setEditPlane(
          Math.random() > 0.666 ? EditPlane.XY : Math.random() < 0.5 ? EditPlane.YZ : EditPlane.ZX);
      XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, false);
      XFormTransformService.rotate(xForm, 360.0 * Math.random(), false);
      XFormTransformService.localTranslate(
          xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), false);

      if (Math.random() > 0.5) {
        XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, true);
        XFormTransformService.rotate(xForm, 360.0 * Math.random(), true);
        XFormTransformService.localTranslate(
            xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), true);
      }
    }

    // create transform 2
    {
      XForm xForm = new XForm();
      layer.getXForms().add(xForm);
      xForm.setWeight(0.5);
      xForm.setColor(0);
      xForm.setColorSymmetry(0);
      xForm.setMaterial(0);
      xForm.setMaterialSpeed(0);

      xForm.setXYCoeff00(0.54625622); // a
      xForm.setXYCoeff10(0.26758811); // b
      xForm.setXYCoeff20(0); // e
      xForm.setXYCoeff01(-0.26758811); // c
      xForm.setXYCoeff11(0.54625622); // d
      xForm.setXYCoeff21(0); // f

      xForm.setXYPostCoeff00(1);
      xForm.setXYPostCoeff10(0);
      xForm.setXYPostCoeff01(0);
      xForm.setXYPostCoeff11(1);
      xForm.setXYPostCoeff20(0);
      xForm.setXYPostCoeff21(0);

      xForm.setYZCoeff00(0.46864442);
      xForm.setYZCoeff10(-0.17017929);
      xForm.setYZCoeff20(1.21536218);
      xForm.setYZCoeff01(0.17017929);
      xForm.setYZCoeff11(0.46864442);
      xForm.setYZCoeff21(-0.02558657);

      xForm.setYZPostCoeff00(1);
      xForm.setYZPostCoeff10(0);
      xForm.setYZPostCoeff01(0);
      xForm.setYZPostCoeff11(1);
      xForm.setYZPostCoeff20(0);
      xForm.setYZPostCoeff21(0);

      xForm.setZXCoeff00(0.81078767);
      xForm.setZXCoeff10(0.12035676);
      xForm.setZXCoeff20(0.21748586);
      xForm.setZXCoeff01(-0.12035676);
      xForm.setZXCoeff11(0.81078767);
      xForm.setZXCoeff21(-0.05117314);

      xForm.setZXPostCoeff00(1);
      xForm.setZXPostCoeff10(0);
      xForm.setZXPostCoeff01(0);
      xForm.setZXPostCoeff11(1);
      xForm.setZXPostCoeff20(0);
      xForm.setZXPostCoeff21(0);

      // variation 1
      xForm.addVariation(1, VariationFuncList.getVariationFuncInstance("linear3D", true));
      // set default edit plane
      flame.setEditPlane(EditPlane.XY);
      XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, false);
      XFormTransformService.rotate(xForm, 360.0 * Math.random(), false);
      XFormTransformService.localTranslate(
          xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), false);
      if (Math.random() > 0.666) {
        XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, true);
        XFormTransformService.rotate(xForm, 360.0 * Math.random(), true);
        XFormTransformService.localTranslate(
            xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), true);
      }
    }
    // create transform 3
    if (Math.random() > 0.666) {
      XForm xForm = new XForm();
      layer.getXForms().add(xForm);
      xForm.setWeight(0.5);
      xForm.setColor(0);
      xForm.setColorSymmetry(0);
      xForm.setMaterial(0);
      xForm.setMaterialSpeed(0);

      xForm.setXYCoeff00(0.54625622); // a
      xForm.setXYCoeff10(0.26758811); // b
      xForm.setXYCoeff20(0); // e
      xForm.setXYCoeff01(-0.26758811); // c
      xForm.setXYCoeff11(0.54625622); // d
      xForm.setXYCoeff21(0); // f

      xForm.setXYPostCoeff00(1);
      xForm.setXYPostCoeff10(0);
      xForm.setXYPostCoeff01(0);
      xForm.setXYPostCoeff11(1);
      xForm.setXYPostCoeff20(0);
      xForm.setXYPostCoeff21(0);

      xForm.setYZCoeff00(0.46864442);
      xForm.setYZCoeff10(-0.17017929);
      xForm.setYZCoeff20(1.21536218);
      xForm.setYZCoeff01(0.17017929);
      xForm.setYZCoeff11(0.46864442);
      xForm.setYZCoeff21(-0.02558657);

      xForm.setYZPostCoeff00(1);
      xForm.setYZPostCoeff10(0);
      xForm.setYZPostCoeff01(0);
      xForm.setYZPostCoeff11(1);
      xForm.setYZPostCoeff20(0);
      xForm.setYZPostCoeff21(0);

      xForm.setZXCoeff00(0.59207155);
      xForm.setZXCoeff10(-0.56684538);
      xForm.setZXCoeff20(1.31770847);
      xForm.setZXCoeff01(0.56684538);
      xForm.setZXCoeff11(0.59207155);
      xForm.setZXCoeff21(-0.84435688);

      xForm.setZXPostCoeff00(1);
      xForm.setZXPostCoeff10(0);
      xForm.setZXPostCoeff01(0);
      xForm.setZXPostCoeff11(1);
      xForm.setZXPostCoeff20(0);
      xForm.setZXPostCoeff21(0);

      // variation 1
      xForm.addVariation(1, VariationFuncList.getVariationFuncInstance("linear3D", true));
      // set default edit plane
      flame.setEditPlane(EditPlane.XY);
      XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, false);
      XFormTransformService.rotate(xForm, 360.0 * Math.random(), false);
      XFormTransformService.localTranslate(
          xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), false);
      if (Math.random() > 0.5) {
        XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, true);
        XFormTransformService.rotate(xForm, 360.0 * Math.random(), true);
        XFormTransformService.localTranslate(
            xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), true);
      }
    }

    // create final transform 1
    if (Math.random() > 0.42) {
      XForm xForm = new XForm();
      layer.getFinalXForms().add(xForm);
      xForm.setWeight(0);
      xForm.setColor(0);
      xForm.setColorSymmetry(0);
      xForm.setMaterial(0);
      xForm.setMaterialSpeed(0);

      xForm.setCoeff00(1); // a
      xForm.setCoeff10(0); // b
      xForm.setCoeff20(0); // e
      xForm.setCoeff01(0); // c
      xForm.setCoeff11(1); // d
      xForm.setCoeff21(0); // f

      xForm.setPostCoeff00(1);
      xForm.setPostCoeff10(0);
      xForm.setPostCoeff01(0);
      xForm.setPostCoeff11(1);
      xForm.setPostCoeff20(0);
      xForm.setPostCoeff21(0);

      // variation 1
      xForm.addVariation(0.75 + Math.random() * 0.25, getRandomVariation());
      // variation 2
      if (Math.random() > 0.5) {
        xForm.addVariation(
            0.25 + Math.random() * 0.25,
            VariationFuncList.getVariationFuncInstance("linear3D", true));
      }
      // set default edit plane
      flame.setEditPlane(EditPlane.XY);
      if (Math.random() > 0.5) {
        XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, false);
        XFormTransformService.rotate(xForm, 360.0 * Math.random(), false);
        XFormTransformService.localTranslate(
            xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), false);
      }
      if (Math.random() > 0.5) {
        XFormTransformService.scale(xForm, 1.25 - Math.random() * 0.5, true, true, true);
        XFormTransformService.rotate(xForm, 360.0 * Math.random(), true);
        XFormTransformService.localTranslate(
            xForm, 1.0 - 2.0 * Math.random(), 1.0 - 2.0 * Math.random(), true);
      }
    }

    return flame;
  }