+1 (972) 883-2091
ECSS 4.220, 800 W Campbell Rd, Richardson, TX 75083–0688, US

The “appstate” package

This package contains the implementation of classes that describe the application states of the evacuation 3D visualizer. The “appstate” package consists of the following classes:

  • “EvacuationEnvironmentAppState”
  • “EvacuationSimulatingAppState”

1. Implementing the “EvacuationEnvironmentAppState” class

The “EvacuationEnvironmentAppState” class describes the evacuation environment application state. Everything that is not simulated, for example, terrain, sky, water, light, etc., is attached to this application state. In addition, the application state class implements the mechanism that allows the lights of the 3D visualization to be turned on and off. There are two lights in the simulation, one direction light, representing the Sun, and another ambient light, representing the natural ambient light. Also, this class implements the ability for showing or hiding the visualized objects attached to its state. To implement this class:

  1. Inside the package “edu.utdallas.mavs.evacuation.visualization.vis3D.appstate”, create a class named “EvacuationEnvironmentAppState” that extends the class “EnvironmentAppState” defined in the package “edu.utdallas.mavs.divas.visualization.vis3D.appstate”.
  2. The class “EvacuationEnvironmentAppState” provides concrete implementations of the following abstract methods defined originally in the jMonkey “AbstractAppState” class:
    1. unloadLights: This method unload the lights from the 3D visualizer.
    2. loadLights: There are two lights in the simulation, one direction light that represents the Sun, and another ambient light that rep
    3. stateDetached: This method detaches the sky box, lights, water, and terrain effects from the visualization scene.
    4. initialize: This method initializes the visualization scene by loading the sky box, lights, water, and terrain effects. In addition,resents the natural ambient light.

The following code provides the full implementation of the class EvacuationEnvironmentAppState:

package edu.utdallas.mavs.evacuation.visualization.vis3D.appstate;

import com.jme3.app.Application;
import com.jme3.app.state.AppStateManager;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;

import edu.utdallas.mavs.divas.core.config.VisConfig;
import edu.utdallas.mavs.divas.visualization.vis3D.appstate.EnvironmentAppState;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Terrain;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Water;
import edu.utdallas.mavs.evacuation.simulation.config.EvacuationVisConfig;
import edu.utdallas.mavs.evacuation.visualization.vis3D.vo.Skybox;

/**
 * This class describes the evacuation environment application state.
 * <p>
 * Everything that is not simulated, for example, terrain, sky, water, light, etc., is attached to this application state. This application state allows the lights of the 3D visualization to be turned on and off, having the effect of showing or
 * hiding the visualized objects attached to this application state.
 * <p>
 * There are two lights in the simulation, one direction light, representing the Sun, and another ambient light, representing the natural ambient light.
 */
public class EvacuationEnvironmentAppState extends EnvironmentAppState
{
    private DirectionalLight sun;
    private AmbientLight     al;

    boolean                  waterLoaded   = false;
    boolean                  terrainLoaded = false;

    @Override
    public void update(float tpf)
    {}

    @Override
    public void stateDetached(AppStateManager stateManager)
    {
        super.stateDetached(stateManager);
        Skybox.unloadSky();
        if(waterLoaded)
        {
            waterLoaded = false;
            Water.unloadWater(app);
        }
        unloadLights();
        if(terrainLoaded)
        {
            terrainLoaded = false;
            Terrain.unloadTerrain();
        }
    }

    @Override
    public void initialize(AppStateManager stateManager, Application app)
    {
        super.initialize(stateManager, app);
        app.getCamera().setFrustumFar(20000);
        Skybox.loadSky();
        if(VisConfig.getInstance().getCustomProperty(EvacuationVisConfig.WATER))
        {
            waterLoaded = true;
            Water.loadWater(app);
        }
        loadLights();
        if(VisConfig.getInstance().getCustomProperty(EvacuationVisConfig.TERRAIN))
        {
            terrainLoaded = true;
            Terrain.loadTerrain();
        }
        app.getCamera().setLocation(new Vector3f(30, 30, 30));
        app.getCamera().lookAt(new Vector3f(-150, 15, -150), Vector3f.UNIT_Y);
    }

    @Override
    public void unloadLights()
    {
        app.getRootNode().removeLight(sun);
        app.getRootNode().removeLight(al);
    }

    @Override
    public void loadLights()
    {
        sun = new DirectionalLight();
        sun.setDirection(new Vector3f(-0.577f, -0.577f, -0.577f));
        app.getRootNode().addLight(sun);

        al = new AmbientLight();
        // al.setColor(ColorRGBA.White.mult(2.5f));
        al.setColor(new ColorRGBA(1, 1, 1, 0));
        app.getRootNode().addLight(al);
    }
}

2. Implementing the “EvacuationSimulatingAppState” class

This class represents the main application state of the traffic 3D visualizer. It allows users to interact with the simulation by selecting visualized objects (VOs) and triggering events in the simulation. It also allows users to add agents to simulation. To implement this class:
Inside the package “edu.utdallas.mavs.evacuation.visualization.vis3D.appstate”, create a class named “EvacuationSimulatingAppState” that extends the class “SimulatingAppState” defined in the package “edu.utdallas.mavs.divas.visualization.vis3D.appstate”.

The following code provides the full implementation of the classEvacuationSimulatingAppState:

package edu.utdallas.mavs.evacuation.visualization.vis3D.appstate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jme3.math.Vector3f;

import edu.utdallas.mavs.divas.visualization.vis3D.Visualizer3DApplication;
import edu.utdallas.mavs.divas.visualization.vis3D.appstate.SimulatingAppState;
import edu.utdallas.mavs.divas.visualization.vis3D.common.CursorType;
import edu.utdallas.mavs.divas.visualization.vis3D.common.InputMode;
import edu.utdallas.mavs.divas.visualization.vis3D.dialog.NiftyScreen;
import edu.utdallas.mavs.evacuation.visualization.vis3D.EvacuationApplication;
import edu.utdallas.mavs.evacuation.visualization.vis3D.common.EvacuationCursorType;
import edu.utdallas.mavs.evacuation.visualization.vis3D.common.EvacuationInputMode;
import edu.utdallas.mavs.evacuation.visualization.vis3D.dialog.voModification.agentModification.AgentPropertyDialog;

/**
 * This class represents the main application state of the evacuation 3D visualizer.
 * <p>
 * It allows users to interact with the visualized simulation, by selecting visualized objects (VOs) and triggering events to the simulation. It also allows users to add agents to simulation.
 */
public class EvacuationSimulatingAppState extends SimulatingAppState<EvacuationApplication>
{
    private final static Logger logger = LoggerFactory.getLogger(EvacuationSimulatingAppState.class);

    @Override
    protected void triggerEvent(Vector3f position)
    {
        if(mode.equals(EvacuationInputMode.ADD_EXPLOSION))
        {
            logger.debug("Adding explosion @ location: " + position);
            Visualizer3DApplication.getInstance().getSimCommander().createExplosion(position, 0.00000003f, true);
        }
        else if(mode.equals(EvacuationInputMode.ADD_EXPLOSION_NO_SMOKE))
        {
            logger.debug("Adding explosion no smoke @ location: " + position);
            Visualizer3DApplication.getInstance().getSimCommander().createExplosion(position, 0.00000003f, false);
        }
        else if(mode.equals(EvacuationInputMode.ADD_SPOTLIGHT))
        {
            logger.debug("Adding spotlight @ location: " + position);
            Visualizer3DApplication.getInstance().getSimCommander().createSpotlight(position);
        }
        else if(mode.equals(EvacuationInputMode.ADD_DRUMS))
        {
            logger.debug("Adding drums @ location: " + position);
            Visualizer3DApplication.getInstance().getSimCommander().createDrums(position);
        }
        else if(mode.equals(EvacuationInputMode.ADD_GRILL))
        {
            logger.debug("Adding grill @ location: " + position);
            Visualizer3DApplication.getInstance().getSimCommander().createGrill(position);
        }
        else if(mode.equals(EvacuationInputMode.ADD_FIREWORKS))
        {
            logger.debug("Adding firework @ location: " + position);
            Visualizer3DApplication.getInstance().getSimCommander().createFireworks(position, 1, false);
        }
        else
        {
            logger.debug("No handler for triggering event implemented for {}", mode);
        }
    }

    @Override
    public void setCursor(InputMode inputMode)
    {
        // change cursors in here (and anything else required when changing modes)
        if(inputMode.equals(EvacuationInputMode.ADD_EXPLOSION))
        {
            app.setCursor(EvacuationCursorType.SMOKE_BOMB);
        }
        else if(inputMode.equals(EvacuationInputMode.ADD_EXPLOSION_NO_SMOKE))
        {
            app.setCursor(EvacuationCursorType.BOMB);
        }
        else if(inputMode.equals(EvacuationInputMode.ADD_SPOTLIGHT))
        {
            app.setCursor(EvacuationCursorType.SPOTLIGHT);
        }
        else if(inputMode.equals(EvacuationInputMode.ADD_DRUMS))
        {
            app.setCursor(EvacuationCursorType.DRUMS);
        }
        else if(inputMode.equals(EvacuationInputMode.ADD_GRILL))
        {
            app.setCursor(EvacuationCursorType.GRILL);
        }
        else if(inputMode.equals(EvacuationInputMode.ADD_FIREWORKS))
        {
            app.setCursor(EvacuationCursorType.FIREWORKS);
        }
        else if(inputMode.equals(EvacuationInputMode.ADD_TREASURE))
        {
            app.setCursor(EvacuationCursorType.TREASURE);
        }
        else if(inputMode.equals(InputMode.ADD_AGENT))
        {
            app.setCursor(CursorType.AGENT);
        }
        else if(inputMode.equals(InputMode.ADD_OBJECT))
        {
            app.setCursor(CursorType.OBJECT);
        }
        else if(inputMode.equals(InputMode.SELECTION))
        {
            app.setCursor(CursorType.ARROW);
        }
    }

    @Override
    protected InputMode getMappedEventInputMode(String inputMode)
    {
        InputMode mappedInputMode = null;

        if(inputMode.equals("ADD_EXPLOSION"))
        {
            mappedInputMode = EvacuationInputMode.ADD_EXPLOSION;
        }
        else if(inputMode.equals("ADD_EXPLOSION_NO_SMOKE"))
        {
            mappedInputMode = EvacuationInputMode.ADD_EXPLOSION_NO_SMOKE;
        }
        else if(inputMode.equals("ADD_FIREWORKS"))
        {
            mappedInputMode = EvacuationInputMode.ADD_FIREWORKS;
        }
        else if(inputMode.equals("ADD_TREASURE"))
        {
            mappedInputMode = EvacuationInputMode.ADD_TREASURE;
        }
        else if(inputMode.equals("ADD_DRUMS"))
        {
            mappedInputMode = EvacuationInputMode.ADD_DRUMS;
        }
        else if(inputMode.equals("ADD_GRILL"))
        {
            mappedInputMode = EvacuationInputMode.ADD_GRILL;
        }
        else if(inputMode.equals("ADD_SPOTLIGHT"))
        {
            mappedInputMode = EvacuationInputMode.ADD_SPOTLIGHT;
        }
        else
        {
            mappedInputMode = EvacuationInputMode.ADD_EXPLOSION;
        }

        return mappedInputMode;
    }

    @Override
    protected void setupContextObservers()
    {
        super.setupContextObservers();
        
        contextObservers.add(new AgentPropertyDialog(NiftyScreen.windowLayerElement));
    }
}