/*
Hypercycle simulation. Copyright by J�rg H�hne.
For suggestions or questions email me at hoehne@thinktel.de
*/
package hyperCycle;
import javax.swing.JFrame;
import sim.display.Controller;
import sim.display.GUIState;
import sim.display3d.Display3D;
import sim.engine.SimState;
import sim.portrayal3d.grid.ValueGrid2DPortrayal3D;
import sim.portrayal3d.grid.quad.MeshPortrayal;
import sim.portrayal3d.grid.quad.QuadPortrayal;
import sim.portrayal3d.grid.quad.TilePortrayal;
import sim.util.gui.SimpleColorMap;
/**
* This class visualize the hyper cycle simulation in 3D. This class was
* retrieved by modifying the heatbugs example from the MASON framework so don't
* blame me for errors (and I also do not earn the merits).
* <p>
* The state of a cell is color coded and also by the height. Three display
* modes are supported:
* <ul>
* <li>TILE: Colored and tiles in different heights. Same colored tiles have the
* same height.</li>
* <li>MESH: A meshed colored grid. Same colors have the same height.</li>
* <li>NOZ: Color coding only, no different heights.</li>
* </ul>
*
* @author hoehne
*/
public class HyperCycle3DWithUI extends GUIState {
public JFrame displayFrame;
public static final int TILE = 0;
public static final int MESH = 1;
public static final int NOZ = 2;
int cellMode = MESH;
ValueGrid2DPortrayal3D cellPortrayal = new ValueGrid2DPortrayal3D();
QuadPortrayal quadP = null;
public Display3D display;
public HyperCycle3DWithUI() {
this(new HyperCycleSimulation(System.currentTimeMillis(),
new HyperCycleParameters()), MESH);
}
public HyperCycle3DWithUI(SimState state, final int cellMode) {
super(state);
this.cellMode = cellMode;
}
public static String getName() {
return "Hyper Cycle Simulation 3D";
}
public void start() {
super.start();
setupPortrayals();
}
public void load(SimState state) {
super.load(state);
// we now have new grids. Set up the portrayals to reflect that
setupPortrayals();
}
/**
* This method has also its roots at the heatbugs example. It sets up the
* visuals.
*/
public void setupPortrayals() {
display.destroySceneGraph();
HyperCycleSimulation hcsState = (HyperCycleSimulation) state;
HyperCycleParameters p = hcsState.getParameters();
// set the color map
SimpleColorMap cm = new SimpleColorMap(p.colorTable);
// the heat can be tiles, meshes, or tiles with no change in height
// (NOZ).
// Specify which one here.
switch (cellMode) {
case TILE:
quadP = new TilePortrayal(cm, 2.0f);
break;
case MESH:
quadP = new MeshPortrayal(cm, 1.1f);
break;
case NOZ:
quadP = new TilePortrayal(cm); // no height changes
break;
}
cellPortrayal.setPortrayalForAll(quadP);
// With this line we can tell the bug portrayal to use two triangles
// rather than a rect to draw each cell. See the documentation for
// ValueGrid2DPortrayal3D for
// why this would be useful and when it is not.
cellPortrayal.setUsingTriangles(true);
cellPortrayal.setField(((HyperCycleSimulation) state).gridBuffer);
// reschedule the displayer
display.reset();
// rebuild the scene graph
display.createSceneGraph();
}
/**
* The overwritten init method. Mainly taken from the heatbugs example.
*/
public void init(Controller c) {
super.init(c);
// Make the Display3D. We'll have it display stuff later.
display = new Display3D(600, 600, this, 1);
// attach the portrayals to the displayer, from bottom to top
display.attach(cellPortrayal, "HyperCycle Cells");
cellPortrayal.valueName = "HyperCycle Cells";
HyperCycleSimulation hcsState = (HyperCycleSimulation) state;
HyperCycleParameters p = hcsState.getParameters();
// center the bug graph. Right now it's located at the (0,0) position.
// For
// example, if it's a 5x5 graph, and the origin is at (0,0), we want to
// move it
// to (2,2). So we want it to be at ( (5-1)/2 = 2, (5-1/2) = 2 ).
// Similarly,
// if it's a 6x6 graph we want the origin to be at (2.5, 2.5), dead
// center between
// the (2,2) and (3,3) grid positions. To center
// the origin there, we need to move the graph in the opposite
// direction.
// so the general equation for each dimension: (numGridPoints - 1) /
// -2.0.
display.translate((p.getWidth() - 1) / -2.0,
(p.getHeight() - 1) / -2.0, 0);
// now let's scale it so it fits inside a 1x1x1 cube centered at the
// origin. We don't
// have to, but it'll look nicer.
display.scale(1.0 / Math.max(p.getWidth(), p.getHeight()));
displayFrame = display.createFrame();
c.registerFrame(displayFrame); // register the frame so it appears in
// the "Display" list
displayFrame.setVisible(true);
}
/**
* The overwritten quit method.
*/
public void quit() {
super.quit();
if (displayFrame != null)
displayFrame.dispose();
displayFrame = null;
display = null;
}
}