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

The “vo” package

1. Package description

The “vo” package implements the 3D visualized objects. It contains the following classes:

  • EnvObjectFactory
  • EvacuationEnvObjectVO
  • EvacuationEventVO
  • EvacuationHumanAgentVO
  • EventFactory
  • Skybox

2. Implementing package

To implement the “EnvObjectFactory” class:

  • Create a new class inside the “edu.utdallas.mavs.evacuation.visualization.vis3D.vo” package and name it “EnvObjectFactory”.
  • Copy the code given below that describes the full implementation of a “EnvObjectFactory” class.
package edu.utdallas.mavs.evacuation.visualization.vis3D.vo;

import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;

import edu.utdallas.mavs.divas.core.config.VisConfig;
import edu.utdallas.mavs.divas.core.sim.common.state.EnvObjectState;
import edu.utdallas.mavs.divas.visualization.vis3D.Visualizer3DApplication;
import edu.utdallas.mavs.evacuation.simulation.config.EvacuationVisConfig;
import edu.utdallas.mavs.evacuation.simulation.config.SkyboxEnum;

/**
 * This class describes a factory for visualized environment objects.
 */
public class EnvObjectFactory
{
    /**
     * This is a factory method for visualized environment objects.
     * 
     * @param state
     *        an environment object state to be factored into a visualized event
     * @return a spatial associated with the newly created visualized environment object
     */
    public static Spatial createEnvObjectVO(EnvObjectState state)
    {
        Spatial envObjModel;
        SkyboxEnum skybox = VisConfig.getInstance().getCustomProperty(EvacuationVisConfig.SKYBOX);
        if(skybox.equals(SkyboxEnum.Night_Stars) || VisConfig.getInstance().getCustomProperty(EvacuationVisConfig.SKYBOX).equals(SkyboxEnum.Night_Red))
        {
            envObjModel = Visualizer3DApplication.getInstance().getAssetManager().loadModel(state.getModelName().replace(".j3o", "_night.j3o"));
        }
        else
        {
            envObjModel = Visualizer3DApplication.getInstance().getAssetManager().loadModel(state.getModelName());
        }
        return envObjModel;
    }

    /**
     * @param modelName The model to get local scale for
     * @param x Scale X
     * @param y Scale Y
     * @param z Scale Z
     * @return The required local scale for the model
     */
    public static Vector3f getLocalScale(String modelName, float x, float y, float z)
    {
        if(modelName.equals("objects/Tree.mesh.j3o"))
        {
            return new Vector3f(x * 4, y * 4, z * 4);
        }

        return new Vector3f(x, y, z);
    }

}

To implement the “EvacuationEnvObjectVO” class:

  • Create a new class inside the “edu.utdallas.mavs.evacuation.visualization.vis3D.vo” package and name it “EvacuationEnvObjectVO”.
  • Copy the code given below that describes the full implementation of a “EvacuationEnvObjectVO” class.
package edu.utdallas.mavs.evacuation.visualization.vis3D.vo;

import java.util.ArrayList;
import java.util.List;

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

import com.jme3.bounding.BoundingBox;
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;

import edu.utdallas.mavs.divas.core.sim.common.state.EnvObjectState;
import edu.utdallas.mavs.divas.visualization.vis3D.Visualizer3DApplication;
import edu.utdallas.mavs.divas.visualization.vis3D.utils.VisToolbox;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.EnvObjectVO;
import edu.utdallas.mavs.evacuation.simulation.sim.common.state.DoorObjectState;

/**
 * This class describes a visualized environment object
 */
public class EvacuationEnvObjectVO extends EnvObjectVO
{
    private final static Logger   logger                  = LoggerFactory.getLogger(EvacuationEnvObjectVO.class);

    /**
     * A list conttains the list of environemnet object models names
     */
    protected static List<String> modifiedBoundingBoxList = new ArrayList<>();

    // protected Geometry skeleton;
    //
    // protected boolean skeletonMade = false;

    /**
     * @param state
     *        the VO's environment object state
     * @param cycle
     *        the cycle of the simulation associated with the environment object state
     */
    public EvacuationEnvObjectVO(EnvObjectState state, long cycle)
    {
        super(state, cycle);
    }

    /**
     * Constructs an empty interpolated VO
     * To be called only for cloning purposes. Not to be called if the VO is to be actually created in the visualization.
     * 
     * @param state
     *        the VO's environment object state
     */
    public EvacuationEnvObjectVO(EnvObjectState state)
    {
        super(state);
    }

    @Override
    public void updateState()
    {
        /*
         * update position and rotation (handled by InterpolatedVO.updateState(vector, quaternion) to enable smooth
         * motion)
         */
        if(state.getType().equals("door") && state instanceof DoorObjectState && ((DoorObjectState) state).isOpen())
        {
            updateState(state.getPosition().add(new Vector3f(0, state.getScale().y - .5f, 0)), state.getRotation(), new Vector3f(state.getScale().x, .5f, state.getScale().z));
        }
        else if(state.getType().equals("door") && state instanceof DoorObjectState && !((DoorObjectState) state).isOpen())
        {
            updateState(state.getPosition().add(new Vector3f(0, 0, 0)), state.getRotation(), new Vector3f(state.getScale()));
        }
        else if(state.getType().equals("door")) // assume open
        {
            updateState(state.getPosition().add(new Vector3f(0, 7.5f, 0)), state.getRotation(), new Vector3f(state.getScale().x, .5f, state.getScale().z));
        }
        else
        {
            updateState(state.getPosition(), state.getRotation(), state.getScale());
        }

    }


    /**
     * Attaches this model geometric form
     */
    @Override
    protected void attachModel()
    {
        setLocalTranslation(state.getPosition());

        if(state.getType().equals("floor"))
        {
            isLocked = true;
        }

        // Attach 3D Models
        if(state.getType().equals("3DModel"))
        {
            attachEnvObjectModel();
        }
        else
        {
            attachGeometry();
        }
    }

    /**
     * Attaches a 3D model representing this VO
     */
    protected void attachEnvObjectModel()
    {
        envObjModel = EnvObjectFactory.createEnvObjectVO(state);

        float stateX = 1;
        float stateY = 1;
        float stateZ = 1;

        float modelX = ((BoundingBox) envObjModel.getWorldBound()).getXExtent();
        float modelY = ((BoundingBox) envObjModel.getWorldBound()).getYExtent();
        float modelZ = ((BoundingBox) envObjModel.getWorldBound()).getZExtent();

        float x = stateX / modelX;
        float y = stateY / modelY;
        float z = stateZ / modelZ;

        Vector3f localScale = EnvObjectFactory.getLocalScale(state.getModelName(), x, y, z);
        // If the model is attached before there is no need to update the bounding box because the update is cached
        if(!modifiedBoundingBoxList.contains(state.getModelName()))
        {
            BoundingBox bb = (BoundingBox) envObjModel.getWorldBound();
            modifiedBoundingBoxList.add(state.getModelName());
            bb.setYExtent(bb.getYExtent() * 2);

            envObjModel.setModelBound(bb);
            envObjModel.setLocalScale(localScale);
        }
        // If the model is cached then you should multiply the Y scale by 2, otherwise the Y access will be the half
        else
        {
            envObjModel.setLocalScale(localScale.getX(), localScale.getY() * 2, localScale.getZ());
        }

        if(Visualizer3DApplication.getInstance().getVisRootNode() != null)
        {
            attachChild(envObjModel);
        }

    }

    /**
     * Attaches a textured geometry representing this VO
     */
    protected void attachGeometry()
    {
        Box box = new Box(new Vector3f(0, 0, 0), 1, 1, 1);
        Geometry geometry = new Geometry("Box", box);
        Material material = new Material(getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
        try
        {
            Texture texture = getAssetManager().loadTexture(TEXTURES_DIR + state.getMaterial() + ".jpg");

            if(state.getType().equals("wall"))
            {
                texture.setWrap(WrapMode.Repeat);

                if(state.getScale().getZ() > 5)
                {
                    box.scaleTextureCoordinates(new Vector2f(state.getScale().getZ() / 2, 2.5f));
                }
                else
                {
                    box.scaleTextureCoordinates(new Vector2f(state.getScale().getX() / 2, 2.5f));
                }
            }

            material.setTexture("DiffuseMap", texture);
        }
        catch(Exception e)
        {
            if(state.getType().equals("door"))
            {
                Texture tex1 = getAssetManager().loadTexture(TEXTURES_DIR + "plasterwall.jpg");
                material.setTexture("DiffuseMap", tex1);
                AmbientLight doorLight = VisToolbox.createAmbientLight(ColorRGBA.White.mult(2f));
                addLight(doorLight);
            }
            else
            {
                material = new Material(getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
                material.setColor("Color", ColorRGBA.randomColor());
            }
        }
        geometry.setMaterial(material);
        attachChild(geometry);
    }

    @Override
    protected EnvObjectVO createClone(EnvObjectState clone)
    {
        return new EvacuationEnvObjectVO(clone);
    }
}

To implement the “EvacuationEventVO” class:

  • Create a new class inside the “edu.utdallas.mavs.evacuation.visualization.vis3D.vo” package and name it “EvacuationEventVO”.
  • Copy the code given below that describes the full implementation of a “EvacuationEventVO” class.
package edu.utdallas.mavs.evacuation.visualization.vis3D.vo;

import com.jme3.scene.Spatial;

import edu.utdallas.mavs.divas.core.sim.common.event.EnvEvent;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.EventVO;

/**
 * This class represents a visualized event
 */
public class EvacuationEventVO extends EventVO
{
    /**
     * Cosntructs a new event VO
     * 
     * @param event the event state associated with this VO
     * @param cycle the simulation cycle number associated with this event
     */
    public EvacuationEventVO(EnvEvent event, long cycle)
    {
        super(event, cycle);
    }

    @Override
    protected Spatial createEventVO(EnvEvent event)
    {        
        return EventFactory.createEventVO(event);
    }
}

To implement the “EvacuationHumanAgentVO” class:

  • Create a new class inside the “edu.utdallas.mavs.evacuation.visualization.vis3D.vo” package and name it “EvacuationHumanAgentVO”.
  • Copy the code given below that describes the full implementation of a “EvacuationHumanAgentVO” class.
package edu.utdallas.mavs.evacuation.visualization.vis3D.vo;

import java.util.ArrayList;
import java.util.List;

import com.jme3.animation.AnimControl;
import com.jme3.animation.LoopMode;
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Sphere;

import edu.utdallas.mavs.divas.visualization.vis3D.Visualizer3DApplication;
import edu.utdallas.mavs.divas.visualization.vis3D.utils.VisToolbox;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.AgentVO;
import edu.utdallas.mavs.evacuation.simulation.sim.common.state.EHumanAgentState;
import edu.utdallas.mavs.evacuation.simulation.sim.common.state.Posture;

/**
 * This class describes a visualized agent
 */
public class EvacuationHumanAgentVO extends AgentVO<EHumanAgentState>
{
    /**
     * A ratio constant to correct the mismatch between the 3D models and the simulation entity
     */
    private static final float MODEL_RATIO = 0.55f;

    /**
     * The previous posture of this VO
     */
    protected Posture          prevPosture = null;

    /**
     * The agent path of this VO
     */
    protected List<Geometry>   myPath      = new ArrayList<Geometry>();

    private boolean            agentPath   = false;

    private List<Vector3f>     lastPath    = null;

    ColorRGBA                  agentMarkColor;

    private Geometry           idSphere    = null;

    protected Node             myRootChild;

    /**
     * Creates a new agent VO
     * 
     * @param state
     *        the agent state to be associated with this VO
     * @param cycle
     *        the simulation cycle number associated with the agent state
     */
    public EvacuationHumanAgentVO(EHumanAgentState state, long cycle)
    {
        super(state, cycle);
        createIdSphere();
        myRootChild = new Node();
        AmbientLight agentLight = VisToolbox.createAmbientLight(ColorRGBA.White);
        addLight(agentLight);
    }

    @Override
    protected float getModelRatio()
    {
        return MODEL_RATIO;
    }

    protected void createIdSphere()
    {
        agentMarkColor = ColorRGBA.randomColor();
        agentMarkColor.a = .5f;
        Sphere sphere = new Sphere(30, 30, 1);
        idSphere = new Geometry("AgentPathF", sphere);
        Material mat = new Material(Visualizer3DApplication.getInstance().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
        mat.setColor("Color", agentMarkColor);
        idSphere.setMaterial(mat);

        idSphere.setQueueBucket(Bucket.Translucent);

        idSphere.setLocalTranslation(Vector3f.UNIT_Y.mult(7));
    }

    @Override
    protected void setupAgentModel()
    {
        String agentPath = new String();

        boolean lqModels = Visualizer3DApplication.getVisConfig().lowQualityModels;
        boolean animated = Visualizer3DApplication.getVisConfig().animatedModels;

        if(animated)
        {
            agentPath = AGENTS_MODELS_DIR + state.getModelName() + ((lqModels) ? "_lq" : "") + ".j3o";
        }
        else
        {
            agentPath = AGENTS_MODELS_DIR + "simple_model" + ".j3o";
        }

        agentModel = getAssetManager().loadModel(agentPath);
    }

    /**
     * Updates this VO's visible properties (e.g., posture, vision cone)
     */
    @Override
    protected void updateVisibleProperties()
    {

        updateAgentPath();

        if(Visualizer3DApplication.getVisConfig().animatedModels)
        {
            if(prevPosture != state.getPosture())
            {
                for(Posture posture : Posture.values())
                {
                    if(state.getPosture() == posture)
                    {
                        channel.setAnim(state.getPosture().toString().toLowerCase());
                        channel.setLoopMode(isLooping(posture));
                    }
                }
            }
        }

        prevPosture = state.getPosture();

        if(prevFov != state.getFOV() || prevVisibleDistance != state.getVisibleDistance())
        {
            if(visionConeEnabled)
            {
                detachVisionCone();
                attachVisionCone();
            }
        }

        prevFov = state.getFOV();
        prevVisibleDistance = state.getVisibleDistance();

    }

    private LoopMode isLooping(Posture posture)
    {
        if(posture == Posture.Death_backward || posture == Posture.Death_forward || posture == Posture.sit_g_start)
        {
            return LoopMode.DontLoop;
        }
        return LoopMode.Loop;
    }

    private void updateAgentPath()
    {
        if(pathHasChanged(lastPath, state.getAgentPath()))
        {

            if(pathIsContinue(lastPath, state.getAgentPath()))
            {
                if(myPath != null && myPath.get(0) != null)
                {
                    myRootChild.detachChild(myPath.remove(0));
                }
            }
            else
            {
                detachAgentPath();
                myPath = VisToolbox.createAgentPath(state.getPosition(), state.getAgentPath(), agentMarkColor);
                attachAgentPath();
            }
        }

        lastPath = state.getAgentPath();
    }

    private boolean pathIsContinue(List<Vector3f> oldPath, List<Vector3f> newPath)
    {
        if(oldPath == null)
        {
            return false;
        }

        if(oldPath.size() == (newPath.size() + 1))
        {
            for(int i = 0; i < newPath.size(); i++)
            {
                if(!newPath.get(i).equals(oldPath.get(i + 1)))
                {
                    return false;
                }
            }
        }
        else
        {
            return false;
        }
        return true;
    }

    /**
     * Attaches the path
     */
    private void checkAgentPath()
    {
        // if(agentPath)
        // {
        // myRootChild.updateGeometricState();
        // }
        if(Visualizer3DApplication.getInstance().getApp().isDebugMode() && !agentPath)
        {
            // attachAgentPath();
            Visualizer3DApplication.getInstance().getVisRootNode().attachChild(myRootChild);
            agentPath = true;
            attachChild(idSphere);
        }
        else if(!Visualizer3DApplication.getInstance().getApp().isDebugMode() && agentPath)
        {
            // detachAgentPath();
            Visualizer3DApplication.getInstance().getVisRootNode().detachChild(myRootChild);
            agentPath = false;
            detachChild(idSphere);
        }
    }

    protected void attachAgentPath()
    {
        if(myPath != null)
        {
            // agentPath = true;
            for(Geometry c : myPath)
            {
                myRootChild.attachChild(c);
            }
        }
        // if(idSphere != null)
        // {
        // attachChild(idSphere);
        // }

    }

    protected void detachAgentPath()
    {
        if(myPath != null)
        {
            // agentPath = false;
            for(Geometry g : myPath)
            {
                myRootChild.detachChild(g);
            }
        }
        // if(idSphere != null)
        // {
        // detachChild(idSphere);
        // }

    }

    @Override
    protected void setupAnimation()
    {
        if(Visualizer3DApplication.getVisConfig().animatedModels)
        {
            control = agentModel.getControl(AnimControl.class);
            channel = control.createChannel();
            channel.setAnim((Posture.Walk).toString().toLowerCase());
        }
    }

    private boolean pathHasChanged(List<Vector3f> lastPath2, List<Vector3f> agentPath2)
    {
        if(lastPath2 == null)
        {
            return true;
        }
        if(lastPath2.size() != agentPath2.size())
        {
            return true;
        }
        for(int i = 0; i < lastPath2.size(); i++)
        {

            Vector3f last = lastPath2.get(i);
            Vector3f current = agentPath2.get(i);
            if(last != null && current != null)
            {
                if(!last.equals(current))
                {
                    return true;
                }
            }
            else if(last == null && current != null)
            {
                return true;
            }
            else if(last != null && current == null)
            {
                return true;
            }
        }
        return false;

    }

    @Override
    protected void detachSpatial()
    {
        detachAgentPath();
        Visualizer3DApplication.getInstance().getVisRootNode().detachChild(myRootChild);
        super.detachSpatial();
    }

    @Override
    protected void updateSelfObjects()
    {
        checkAgentPath();
    }
}

To implement the “EventFactory” class:

  • Create a new class inside the “edu.utdallas.mavs.evacuation.visualization.vis3D.vo” package and name it “EventFactory”.
  • Copy the code given below that describes the full implementation of a “EventFactory” class.
package edu.utdallas.mavs.evacuation.visualization.vis3D.vo;

import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Dome;
import com.jme3.scene.shape.Sphere;

import edu.utdallas.mavs.divas.core.sim.common.event.BombEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.DrumsEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.DynamiteEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.EnvEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.FireworkEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.GrillingFoodEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.SirenEvent;
import edu.utdallas.mavs.divas.core.sim.common.event.SpotlightEvent;
import edu.utdallas.mavs.divas.visualization.vis3D.Visualizer3DApplication;
import edu.utdallas.mavs.divas.visualization.vis3D.utils.VisToolbox;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Drum;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Dynamite;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Explosion;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Fireworks;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.Grill;
import edu.utdallas.mavs.divas.visualization.vis3D.vo.effect.ShockWave;

/**
 * This class describes a factory for visualized events.
 */
public class EventFactory
{
    /**
     * This is a factory method for visualized events.
     * 
     * @param event
     *        an event to be factored into a visualized event
     * @return a spatial associated with the newly created visualized event
     */
    public static Spatial createEventVO(EnvEvent event)
    {
        Spatial vo = null;
        if(event instanceof FireworkEvent)
        {
            vo = createFireworksVO(event);
        }
        else if(event instanceof BombEvent)
        {
            vo = cretateExplosionVO(event);
        }
        else if(event instanceof GrillingFoodEvent)
        {
            vo = createGrillVO(event);
        }
        else if(event instanceof DrumsEvent)
        {
            vo = createDrumsVO(event);
        }
        else if(event instanceof SpotlightEvent)
        {
            vo = createSpotlight(event);
        }
        else if(event instanceof SirenEvent)
        {
            vo = createSiren(event);
        }
        else if(event instanceof DynamiteEvent)
        {
            vo = createDynamite(event);
        }
        return vo;
    }


    private static Spatial createSpotlight(EnvEvent event)
    {
        Node n = new Node();
        n.setLocalTranslation(event.getOrigin().add(0, 1.1f, 0));
        String path = "objects/" + "light7.mesh" + ".j3o";

        Spatial model = Visualizer3DApplication.getInstance().getAssetManager().loadModel(path);

        model.setLocalScale(.005f);

        n.attachChild(model);

        Sphere box1 = new Sphere(50, 50, .4f);
        Geometry vo = new Geometry("Box", box1);
        vo.setLocalTranslation(0, 6.2f, .8f);
        Material mat1 = new Material(Visualizer3DApplication.getInstance().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.White);
        mat1.setColor("GlowColor", ColorRGBA.White);
        vo.setMaterial(mat1);
        AmbientLight agentLight = VisToolbox.createAmbientLight(ColorRGBA.White);
        vo.addLight(agentLight);
        n.attachChild(vo);

        Dome cone = new Dome(Vector3f.ZERO, 2, 30, 1f, false);
        Geometry geometry = new Geometry("VisionCone", cone);

        Material mat = new Material(Visualizer3DApplication.getInstance().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        // mat.setColor("Color", new ColorRGBA(1.0f, 0.2f, 0, alpha));
        ColorRGBA visionColor = ColorRGBA.White;
        mat.setColor("Color", new ColorRGBA(visionColor.r, visionColor.g, visionColor.b, .1f));
        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
        mat.getAdditionalRenderState().setDepthWrite(false);

        geometry.setMaterial(mat);

        geometry.setQueueBucket(Bucket.Translucent);
        geometry.setLocalScale(new Vector3f(25, 50, 25));
        geometry.rotate(new Quaternion().fromAngleAxis(-FastMath.PI / 2, Vector3f.UNIT_X));
        geometry.setLocalTranslation(0, 6.2f, 50);
        n.attachChild(geometry);

        cone = new Dome(Vector3f.ZERO, 2, 30, 1f, true);
        geometry = new Geometry("VisionCone", cone);

        mat = new Material(Visualizer3DApplication.getInstance().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        // mat.setColor("Color", new ColorRGBA(1.0f, 0.2f, 0, alpha));
        visionColor = ColorRGBA.White;
        mat.setColor("Color", new ColorRGBA(visionColor.r, visionColor.g, visionColor.b, .1f));
        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
        mat.getAdditionalRenderState().setDepthWrite(false);

        geometry.setMaterial(mat);

        geometry.setQueueBucket(Bucket.Translucent);
        geometry.setLocalScale(new Vector3f(25, 50, 25));
        geometry.rotate(new Quaternion().fromAngleAxis(-FastMath.PI / 2, Vector3f.UNIT_X));
        geometry.setLocalTranslation(0, 6.2f, 50);
        n.attachChild(geometry);

        return n;
    }

    private static Spatial createDrumsVO(EnvEvent event)
    {
        Drum vo = new Drum((DrumsEvent) event);
        return vo;
    }

    private static Spatial createGrillVO(EnvEvent event)
    {
        Grill vo = new Grill((GrillingFoodEvent) event);
        return vo;
    }

    private static Spatial cretateExplosionVO(EnvEvent event)
    {
        Explosion vo = new Explosion((BombEvent) event);
        event.setIntensity(10f);
        return vo;
    }

    private static Spatial createDynamite(EnvEvent event)
    {
        Dynamite vo = new Dynamite((DynamiteEvent) event);
        event.setIntensity(17f);
        return vo;
    }

    private static Spatial createSiren(EnvEvent event)
    {
        ShockWave vo = new ShockWave((SirenEvent) event);
        return vo;
    }

    private static Spatial createFireworksVO(EnvEvent event)
    {
        Fireworks vo = new Fireworks(event);
        event.setIntensity(25f);
        return vo;
    }
}

To implement the “Skybox” class:

  • Create a new class inside the “edu.utdallas.mavs.evacuation.visualization.vis3D.vo” package and name it “Skybox”.
  • Copy the code given below that describes the full implementation of a “Skybox” class.
package edu.utdallas.mavs.evacuation.visualization.vis3D.vo;

import java.util.concurrent.Callable;

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

import com.jme3.app.Application;
import com.jme3.asset.AssetManager;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.texture.Texture;
import com.jme3.util.SkyFactory;

import edu.utdallas.mavs.divas.core.config.VisConfig;
import edu.utdallas.mavs.divas.visualization.vis3D.BaseApplication;
import edu.utdallas.mavs.divas.visualization.vis3D.Visualizer3DApplication;
import edu.utdallas.mavs.evacuation.simulation.config.EvacuationVisConfig;
import edu.utdallas.mavs.evacuation.simulation.config.SkyboxEnum;

/**
 * This class describes the skybox of the 3D visualization.
 */
public class Skybox
{
    private final static Logger logger = LoggerFactory.getLogger(Skybox.class);

    private static Spatial      sky;

    private Skybox()
    {}

    /**
     * Unloads the skybox in the visualization
     */
    public static void unloadSky()
    {
        try
        {
            Visualizer3DApplication.getInstance().getApp().enqueue(new Callable<Object>()
            {

                @Override
                public Object call() throws Exception
                {
                    dettachSky();
                    return null;
                }
            });
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    private static void dettachSky()
    {
        Visualizer3DApplication.getInstance().getApp().getRootNode().detachChild(sky);
    }

    /**
     * Loads the skybox in the visualization
     */
    public static void loadSky()
    {

        try
        {
            Visualizer3DApplication.getInstance().getApp().enqueue(new Callable<Object>()
            {

                @Override
                public Object call() throws Exception
                {
                    updateSky();
                    return null;
                }
            });
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    private static void updateSky()
    {
        Application app = Visualizer3DApplication.getInstance().getApp();
        AssetManager assetManager = app.getAssetManager();

        SkyboxEnum skyboxName = VisConfig.getInstance().getCustomProperty(EvacuationVisConfig.SKYBOX);
        String skyboxPath = String.format("skybox/%s/", skyboxName.toString());

        try
        {
            if(skyboxName.equals(SkyboxEnum.Sunny) || skyboxName.equals(SkyboxEnum.Sunny_Nature) || skyboxName.equals(SkyboxEnum.Cloudy) || skyboxName.equals(SkyboxEnum.Dusk) || skyboxName.equals(SkyboxEnum.Night_Red)
                    || skyboxName.equals(SkyboxEnum.Night_Stars) || skyboxName.equals(SkyboxEnum.Rise) || skyboxName.equals(SkyboxEnum.Sunny_Sea) || skyboxName.equals(SkyboxEnum.Sunset))
            {
                Texture west = assetManager.loadTexture(String.format("%sW.jpg", skyboxPath));
                Texture east = assetManager.loadTexture(String.format("%sE.jpg", skyboxPath));
                Texture north = assetManager.loadTexture(String.format("%sN.jpg", skyboxPath));
                Texture south = assetManager.loadTexture(String.format("%sS.jpg", skyboxPath));
                Texture up = assetManager.loadTexture(String.format("%sU.jpg", skyboxPath));
                Texture down = assetManager.loadTexture(String.format("%sD.jpg", skyboxPath));

                sky = SkyFactory.createSky(assetManager, west, east, north, south, up, down, Vector3f.UNIT_XYZ);
            }
            else
            {
                Texture west = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_west.jpg");
                Texture east = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_east.jpg");
                Texture north = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_north.jpg");
                Texture south = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_south.jpg");
                Texture up = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_up.jpg");
                Texture down = assetManager.loadTexture("Textures/Sky/Lagoon/lagoon_down.jpg");

                sky = SkyFactory.createSky(assetManager, west, east, north, south, up, down, Vector3f.UNIT_XYZ);
            }

            if(sky != null)
            {
                sky.setQueueBucket(Bucket.Sky);

                Node node = ((BaseApplication<?,?>) app).getRootNode();
                node.attachChild(sky);
            }

        }
        catch(Exception e)
        {
            logger.error("Error occured when loading the skybox.");
        }
    }
}