Package org.jwildfire.create.eden.swing

Source Code of org.jwildfire.create.eden.swing.EDENController$Worker

/*
  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.eden.swing;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

import org.jwildfire.base.Prefs;
import org.jwildfire.base.Tools;
import org.jwildfire.base.mathlib.MathLib;
import org.jwildfire.create.eden.io.SunflowWriter;
import org.jwildfire.create.eden.primitive.Point;
import org.jwildfire.create.eden.primitive.Torus;
import org.jwildfire.create.eden.scene.Scene;
import org.jwildfire.create.tina.swing.SunflowSceneFileChooser;
import org.jwildfire.swing.ErrorHandler;
import org.jwildfire.swing.MainController;
import org.sunflow.SunflowAPI;
import org.sunflow.system.ImagePanel;
import org.sunflow.system.Timer;
import org.sunflow.system.UI;
import org.sunflow.system.UI.Module;
import org.sunflow.system.UI.PrintLevel;
import org.sunflow.system.UserInterface;

public class EDENController implements UserInterface {
  private enum SceneType {
    JAVA, SC
  };

  private enum Status {
    IDLE, RENDERING
  };

  private enum Sampler {
    BUCKET, IPR
  }

  private String currentFile;
  private SunflowAPI api;
  private final Prefs prefs;
  private final MainController mainController;
  private final ErrorHandler errorHandler;
  private final JTextArea editorTextArea;
  private final JTextArea consoleTextArea;
  private final ImagePanel imagePanel;
  private final JButton renderButton;
  private final JButton iprButton;
  private final JButton loadSceneButton;
  private final JButton cancelRenderButton;
  private final JButton buildSceneButton;
  private final JButton saveSceneButton;
  private final JButton clearConsoleButton;
  private final JButton newSceneButton;

  private SceneType sceneType = null;
  private Status status = Status.IDLE;

  public EDENController(MainController pMainController, ErrorHandler pErrorHandler, Prefs pPrefs, JTextArea pEditorTextArea, JTextArea pConsoleTextArea, ImagePanel pImagePanel,
      JButton pRenderButton, JButton pIprButton, JButton pLoadSceneButton, JButton pCancelRenderButton, JButton pBuildSceneButton, JButton pSaveSceneButton,
      JButton pClearConsoleButton, JButton pNewSceneButton) {
    mainController = pMainController;
    errorHandler = pErrorHandler;
    prefs = pPrefs;
    editorTextArea = pEditorTextArea;
    consoleTextArea = pConsoleTextArea;
    renderButton = pRenderButton;
    iprButton = pIprButton;
    loadSceneButton = pLoadSceneButton;
    cancelRenderButton = pCancelRenderButton;
    buildSceneButton = pBuildSceneButton;
    saveSceneButton = pSaveSceneButton;
    clearConsoleButton = pClearConsoleButton;
    newSceneButton = pNewSceneButton;
    imagePanel = pImagePanel;
    UI.set(this);
  }

  public void newEmptyScene() {
    currentFile = null;
    api = null;
    sceneType = SceneType.SC;
    currentFile = "new" + genNewFileId() + ".sc";
    editorTextArea.setText("");
    enableControls();
  }

  public void newScene() {
    currentFile = null;
    api = null;
    sceneType = SceneType.SC;
    currentFile = "new" + genNewFileId() + ".sc";
    // TODO
    String template = edenCreateSunflowScene();
    editorTextArea.setText(template);
    enableControls();
  }

  private String genNewFileId() {
    return new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date());
  }

  private JFileChooser getSceneJFileChooser() {
    JFileChooser fileChooser = new SunflowSceneFileChooser(Prefs.getPrefs());
    fileChooser.setAcceptAllFileFilterUsed(false);
    return fileChooser;
  }

  public void loadScene() {
    try {
      JFileChooser chooser = getSceneJFileChooser();
      if (prefs.getInputSunflowScenePath() != null) {
        chooser.setCurrentDirectory(new File(prefs.getInputSunflowScenePath()));
      }
      if (chooser.showOpenDialog(editorTextArea) == JFileChooser.APPROVE_OPTION) {
        api = null;
        File file = chooser.getSelectedFile();
        String filename = file.getAbsolutePath();
        if (filename.endsWith(".java")) {
          sceneType = SceneType.JAVA;
        }
        else {
          sceneType = SceneType.SC;
        }
        editorTextArea.setText(Tools.readUTF8Textfile(filename));
        prefs.setLastInputSunflowSceneFile(file);
        currentFile = filename;
        enableControls();
      }
    }
    catch (Throwable ex) {
      errorHandler.handleError(ex);
    }
  }

  public void buildScene() {
    try {
      clearConsole();
      Timer t = new Timer();
      t.start();
      switch (sceneType) {
        case JAVA:
          api = SunflowAPI.compile(editorTextArea.getText());
          break;
        case SC: {
          File tmpFile = File.createTempFile("jwf", ".sc");
          try {
            String filename = tmpFile.getAbsolutePath();
            Tools.writeUTF8Textfile(filename, editorTextArea.getText());
            String template = "import org.sunflow.core.*;\nimport org.sunflow.core.accel.*;\nimport org.sunflow.core.camera.*;\nimport org.sunflow.core.primitive.*;\nimport org.sunflow.core.shader.*;\nimport org.sunflow.image.Color;\nimport org.sunflow.math.*;\n\npublic void build() {\n  include(\"" + filename.replace("\\", "\\\\") + "\");\n}\n";
            api = SunflowAPI.compile(template);
          }
          finally {
            tmpFile.deleteOnExit();
          }
        }
          break;
      }
      if (currentFile != null) {
        String dir = new File(currentFile).getAbsoluteFile().getParent();
        api.searchpath("texture", dir);
        api.searchpath("include", dir);
      }
      api.build();
      t.end();
      UI.printInfo(Module.GUI, "Build time: %s", t.toString());
      enableControls();
    }
    catch (Throwable ex) {
      api = null;
      errorHandler.handleError(ex);
    }
  }

  void clearConsole() {
    consoleTextArea.setText("");
  }

  @Override
  public void print(Module m, PrintLevel level, String s) {
    if (level == PrintLevel.ERROR)
      JOptionPane.showMessageDialog(editorTextArea, s, String.format("Error - %s", m.name()), JOptionPane.ERROR_MESSAGE);
    println(UI.formatOutput(m, level, s));
  }

  private void println(final String s) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        consoleTextArea.append(s + "\n");
      }
    });
  }

  @Override
  public void taskStart(String arg0, int arg1, int arg2) {
    // TODO Auto-generated method stub

  }

  @Override
  public void taskStop() {
    // TODO Auto-generated method stub

  }

  @Override
  public void taskUpdate(int arg0) {
    // TODO Auto-generated method stub

  }

  public void renderScene() {
    doRender(Sampler.BUCKET);
  }

  private boolean renderCancelled;

  public void doRender(final Sampler pSampler) {
    if (status == Status.RENDERING) {
      return;
    }

    buildScene();
    renderCancelled = false;
    new Thread() {
      @Override
      public void run() {
        status = Status.RENDERING;
        try {
          enableControls();
          clearConsole();
          api.parameter("sampler", pSampler == Sampler.BUCKET ? "bucket" : "ipr");
          api.parameter("accel", "kdtree");
          api.options(SunflowAPI.DEFAULT_OPTIONS);
          api.render(SunflowAPI.DEFAULT_OPTIONS, imagePanel);
        }
        finally {
          if (!renderCancelled) {
            File file;
            try {
              file = File.createTempFile("JWF", "png");
            }
            catch (IOException e) {
              e.printStackTrace();
              throw new RuntimeException(e);
            }
            try {
              imagePanel.save(file.getAbsolutePath());
              try {
                mainController.loadImage(file.getAbsolutePath(), false);
              }
              catch (Exception e) {
                e.printStackTrace();
              }
            }
            finally {
              file.delete();
            }
          }
          status = Status.IDLE;
          enableControls();
        }
      }
    }.start();
  }

  private void enableControls() {
    boolean hasScene = editorTextArea.getText().length() > 0;
    boolean idle = status == Status.IDLE;
    renderButton.setEnabled(idle && hasScene);
    iprButton.setEnabled(renderButton.isEnabled());
    loadSceneButton.setEnabled(idle);
    cancelRenderButton.setEnabled(!idle);
    buildSceneButton.setEnabled(renderButton.isEnabled());
    saveSceneButton.setEnabled(renderButton.isEnabled());
    newSceneButton.setEnabled(loadSceneButton.isEnabled());
    clearConsoleButton.setEnabled(idle);
  }

  public void cancelRendering() {
    UI.taskCancel();
    renderCancelled = true;
  }

  public void iprScene() {
    doRender(Sampler.IPR);
  }

  public void saveScene() {
    try {
      JFileChooser chooser = getSceneJFileChooser();
      chooser.setCurrentDirectory(new File(prefs.getOutputSunflowScenePath()));
      if (currentFile != null) {
        chooser.setSelectedFile(new File(currentFile));
      }
      if (chooser.showSaveDialog(editorTextArea) == JFileChooser.APPROVE_OPTION) {
        File file = chooser.getSelectedFile();
        String filename = file.getAbsolutePath();
        switch (sceneType) {
          case JAVA:
            if (!filename.endsWith(".java")) {
              filename += ".java";
            }
            break;
          case SC:
            if (!filename.endsWith(".sc")) {
              filename += ".sc";
            }
            break;
          default:
            throw new IllegalStateException();
        }
        Tools.writeUTF8Textfile(filename, editorTextArea.getText());
        prefs.setLastOutputSunflowSceneFile(file);
      }
    }
    catch (Throwable ex) {
      errorHandler.handleError(ex);
    }
  }

  public static class Worker {
    private final Scene scene;
    private final Point deltaSize = new Point(0.02, 0.02, 0.02);
    private final Point deltaRotate = new Point(6, 0, 18);

    private final Point position = new Point(-150.0, 50.0, 0.0);
    private final Point direction = new Point(16.0, 0, 0);
    private final Point rotate = new Point(0.0, 0.0, 0.0);
    private final Point size = new Point(3.0, 3.0, 3.0);

    public Worker(Scene pScene, double pX, double pY, double pZ) {
      scene = pScene;
      //      position.setValue(pX, pY, pZ);
    }

    public void performStep() {
      position.setX(position.getX() + direction.getX());
      position.setY(position.getY() + direction.getY());
      position.setZ(position.getZ() + direction.getZ());
      //      System.out.println("POS " + position.getX() + " " + position.getY() + " " + position.getZ());
      direction.rotate(deltaRotate.getX(), deltaRotate.getY(), deltaRotate.getZ());
      rotate.setX(rotate.getX() + deltaRotate.getX());
      rotate.setY(rotate.getY() + deltaRotate.getY());
      rotate.setZ(rotate.getZ() + deltaRotate.getZ());

      //      System.out.println("  ROT " + rotate.getX() + " " + rotate.getY() + " " + rotate.getZ());

      size.setX(size.getX() + deltaSize.getX());
      size.setY(size.getY() + deltaSize.getY());
      size.setZ(size.getZ() + deltaSize.getZ());
      //      System.out.println("  SIZE " + size.getX() + " " + size.getY() + " " + size.getZ());

      Torus box = new Torus();
      box.getPosition().assign(position);
      box.getSize().assign(size);
      box.getRotate().assign(rotate);
      scene.addObject(box);

      deltaRotate.setZ(deltaRotate.getZ() - 0.1 * (0.5 + Math.random()));
    }
  }

  private String edenCreateSunflowScene() {
    Scene scene = new Scene();
    // A
    //    for (int i = 0; i < 3300; i++) {
    //      Sphere sphere = new Sphere();
    //      sphere.setCentre((-50.0 + Math.random() * 94.0) * 2.5, 1.0 + Math.random() * 128.0, (-3.0 + Math.random() * 920.0));
    //      sphere.setRadius(3.6 + Math.random() * 11.4);
    //      scene.addObject(sphere);
    //    }
    // B
    //    for (int i = 0; i < 6666; i++) {
    //      double shape = Math.random();
    //      if (shape < 0.25) {
    //        Sphere sphere = new Sphere();
    //        sphere.getPosition().setValue((-50.0 + Math.random() * 94.0) * 2, 1.0 + Math.random() * 128.0, (-3.0 + Math.random() * 92.0));
    //        sphere.getSize().setValue((8 + Math.random() * 11.4) * 10);
    //        scene.addObject(sphere);
    //      }
    //      else if (shape < 0.5) {
    //        Box box = new Box();
    //        box.getPosition().setValue((-50.0 + Math.random() * 94.0) * 2, 1.0 + Math.random() * 128.0, (-3.0 + Math.random() * 92.0));
    //        box.getSize().setValue((8 + Math.random() * 11.4) * 10);
    //        box.getRotate().setValue(Math.random() * 90.0, Math.random() * 90.0, Math.random() * 90.0);
    //        scene.addObject(box);
    //      }
    //      else if (shape < 0.75) {
    //        Torus torus = new Torus();
    //        torus.getPosition().setValue((-50.0 + Math.random() * 94.0) * 2, 1.0 + Math.random() * 128.0, (-3.0 + Math.random() * 92.0));
    //        torus.getSize().setValue((8 + Math.random() * 11.4) * 10);
    //        torus.getRotate().setValue(Math.random() * 90.0, Math.random() * 90.0, Math.random() * 90.0);
    //        scene.addObject(torus);
    //      }
    //      else {
    //        Cylinder cylinder = new Cylinder();
    //        cylinder.getPosition().setValue((-50.0 + Math.random() * 94.0) * 2, 1.0 + Math.random() * 128.0, (-3.0 + Math.random() * 92.0));
    //        cylinder.getSize().setValue((8 + Math.random() * 11.4) * 10);
    //        cylinder.getRotate().setValue(Math.random() * 90.0, Math.random() * 90.0, Math.random() * 90.0);
    //        scene.addObject(cylinder);
    //      }
    // C
    //    Worker worker1 = new Worker(scene, 0, 0, 0);
    //    for (int i = 0; i < 100; i++) {
    //      worker1.performStep();
    //    }
    // D
    fillDLAScene(scene);
    return new SunflowWriter().createSunflowScene(scene);
  }

  private void fillDLAScene(Scene pScene) {
    int width = 100;
    int height = 100;
    int maxIter = 20000;
    int seed = 123;
    double gridSize = 4.0;
    double maxSize = 10.0;
    double minSize = 1.0;
    double xOffset = 0;
    double yOffset = 0.0;
    double zOffset = 33.0;

    short q[][] = new short[width][height];
    iterateDLA(q, width, height, maxIter, seed);
    double maxR = Math.sqrt(width * width + height * height) * 0.5;
    for (int i = 0; i < width; i++) {
      for (int j = 0; j < height; j++) {
        if (q[i][j] != 0) {
          double dx = i - (width - 1) * 0.5;
          double dy = j - (height - 1) * 0.5;
          double r = Math.sqrt(dx * dx + dy * dy) / maxR + MathLib.EPSILON;
          double size = minSize + (maxSize - minSize) * r;
          Torus sphere = new Torus();
          sphere.getPosition().setValue(dx * gridSize + xOffset, dy * gridSize + yOffset, zOffset);
          sphere.getSize().setValue(size);
          sphere.getRotate().setValue(90 + Math.random() * 12.0 - 6.0, Math.random() * 12.0 - 6.0, Math.random() * 12.0 - 6.0);
          pScene.addObject(sphere);
        }
      }
    }

  }

  private void iterateDLA(short pQ[][], int pWidth, int pHeight, int pMaxIter, int pSeed) {
    int cx = pWidth / 2;
    int cy = pHeight / 2;
    double pi2 = 2.0 * Math.PI;
    int w2 = pWidth - 2;
    int h2 = pHeight - 2;
    Tools.srand123(pSeed);
    /* create the cluster */
    pQ[cy][cx] = 1;
    double r1 = 3.0;
    double r2 = 3.0 * r1;
    for (int i = 0; i < pMaxIter; i++) {
      double phi = pi2 * Tools.drand();
      double ri = r1 * Math.cos(phi);
      double rj = r1 * Math.sin(phi);
      int ci = cy + (int) (ri + 0.5);
      int cj = cx + (int) (rj + 0.5);
      short qt = 0;
      while (qt == 0) {
        double rr = Tools.drand();
        rr += rr;
        rr += rr;
        int rd = (int) rr;
        switch (rd) {
          case 0:
            ci++;
            break;
          case 1:
            cj--;
            break;
          case 2:
            ci--;
            break;
          default:
            cj++;
        }
        if ((ci < 1) || (ci > h2) || (cj < 1) || (cj > w2)) {
          qt = 1;
          i--;
        }
        else {
          int sum = pQ[ci - 1][cj] + pQ[ci + 1][cj] + pQ[ci][cj - 1] + pQ[ci][cj + 1];
          if (sum != 0) {
            pQ[ci][cj] = qt = 1;
            double r3 = (double) (ci - cy);
            double r4 = (double) (cj - cx);
            r3 *= r3;
            r4 *= r4;
            r3 += r4;
            r3 = Math.sqrt(r3);
            if (r3 > r1) {
              r1 = r3;
              r2 = 2.1 * r1;
            }
          }
          else {
            double r3 = (double) (ci - cy);
            double r4 = (double) (cj - cx);
            r3 *= r3;
            r4 *= r4;
            r3 += r4;
            r3 = Math.sqrt(r3);
            if (r3 > r2) {
              qt = 1;
              i--;
            }
          }
        }
      }
    }
  }
}
TOP

Related Classes of org.jwildfire.create.eden.swing.EDENController$Worker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.