Create an additional camera and view port to support these additional graphics
In JMonkeyEngine its possible to have more than one viewport and layer them on top of each other to provide the described effect. Each viewport is internally 3d, but the view ports themselves layer over the top of each other.
Code example
Main class to get things set up
public class Example extends SimpleApplication {
public static void main(String[] args){
Example app = new Example();
app.start(); // start the game
}
@Override
public void simpleInitApp() {
//this represents the "real world" in this example
Box b = new Box(1, 1, 1);
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager,"Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);
rootNode.attachChild(geom);
this.stateManager.attach(new UnderGui());
}
}
An UnderGui layer, that has a 3d scene between the gui layer and the main 3d scene
/**
* The under gui is for things like the held tool. Things that are kind of 3d but also want to be "over" everything
* else
*/
public class UnderGui extends AbstractAppState {
private Node root;
public UnderGui() {
}
@Override
public void initialize(AppStateManager stateManager, Application app )
{
root = new Node( "Under gui viewport Root" );
Camera originalCam = app.getCamera();
Camera cam = new Camera(originalCam.getWidth(), originalCam.getHeight());
//the default camera is an orthoganal camera, use the main cam to copy sensible camera properties
cam.setParallelProjection(originalCam.isParallelProjection());
cam.setFrustum(originalCam.getFrustumNear(), originalCam.getFrustumFar(), originalCam.getFrustumLeft(), originalCam.getFrustumRight(),originalCam.getFrustumTop(), originalCam.getFrustumBottom() );
cam.setFov(originalCam.getFov());
//camera is looking in a +Z direction. -X is right, +X is left. +Y is up
ViewPort view = app.getRenderManager().createMainView("Under gui ViewPort", cam);
view.setEnabled(true);
view.setClearFlags(false, true, false);
view.attachScene( root );
root.attachChild(createWeapon(app.getAssetManager()));
}
/**
* This just creates a red box to be a "weapon" as an example
* @return
*/
private Geometry createWeapon(AssetManager assetManager){
Box b = new Box(1, 1, 1); // create cube shape
Geometry geom = new Geometry("Box", b); // create cube geometry from the shape
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"); // create a simple material
mat.setColor("Color", ColorRGBA.Blue); // set color of material to blue
geom.setMaterial(mat); // set the cube's material
geom.setLocalTranslation(-2,0,2);
return geom;
}
@Override
public void render(RenderManager rm) {
root.updateGeometricState();
}
@Override
public void update( float tpf ) {
root.updateLogicalState(tpf);
}
}
This can also be used for any "ability to see through walls" overlay
Alternative bad solution; setDepthTest
You can also just put the weapon in the main scene and set geometry.getMaterial().getAdditionalRenderState().setDepthTest(false);
. However this is a less good option because it requires the weapon to constantly be moved as the camera changes position and direction and can only cope with "simple" 3D overlays as if 1 part of the weapon is in front of another part (e.g. the stock is in front of the trigger) which bit is rendered is random, as you've asked JME not to do any depth testing