Ok so I guess viewport state it is, thanks for all your help guys, it works finally, still has a stutter when the player moves though. Here is kind of the rough source code as to the 2 viewport approach in case anyone out there is in the same pickle as me. Looking through forums for previous posts and seeing the similar “weapon through wall” problems with no solution source code or an explanation posted really made me frustrated. I hope this comes useful for anyone else in the future.
public class FPSAppState extends SimpleApplication implements ActionListener{
/**
* @param args the command line arguments
*/
final int SHADOWMAP_SIZE = 1024;
private DirectionalLightShadowRenderer dlsr;
private BulletAppState bulletAppstate;
private RigidBodyControl landscape;
private Node player;
private BetterCharacterControl playerControl;
private Vector3f walkDirection = new Vector3f(0,0,0);
private boolean left,right,front,back;
private boolean zoomEnabled = true;
private Spatial weapon;
private Node modelNode;
public static void main(String[] args) {
FPSAppState fas = new FPSAppState();
fas.start();
}
public void simpleInitApp(){
bulletAppstate = new BulletAppState();
stateManager.attach(bulletAppstate);
viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
rootNode.setShadowMode(RenderQueue.ShadowMode.Off);
this.initTerrain();
this.setUpLight();
this.initKeys();
this.initPlayer();
this.initWeapon();
}
public void initTerrain(){
this.assetManager.registerLocator("town.zip", ZipLocator.class);
Spatial map = this.assetManager.loadModel("main.scene");
map.setLocalScale(2f);
map.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
CollisionShape sceneShape =
CollisionShapeFactory.createMeshShape((Node) map);
this.landscape = new RigidBodyControl(sceneShape,0.0f);
map.addControl(this.landscape);
this.bulletAppstate.getPhysicsSpace().add(this.landscape);
this.rootNode.attachChild(map);
}
private void setUpLight() {
// We add light so we see the scene
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
rootNode.addLight(al);
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
rootNode.addLight(dl);
this.dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
this.dlsr.setLight(dl);
viewPort.addProcessor(dlsr);
}
private void initPlayer(){
player = new Node("player");
playerControl = new BetterCharacterControl(0.5f, 1.8f, 80f);
playerControl.setApplyPhysicsLocal(true);
playerControl.setSpatial(player);
player.addControl(playerControl);
bulletAppstate.getPhysicsSpace().add(playerControl);
playerControl.warp(new Vector3f(58f, 6f, 0.0f));
rootNode.attachChild(player);
playerControl.setGravity(new Vector3f(0f,-5f,0f));
}
private void initWeapon(){
// modelNode = new Node();
//
// weapon = this.assetManager.loadModel("Models/Weapons/M81/M81.j3o");
// weapon.rotate(0f, 270*FastMath.DEG_TO_RAD, 0f);
// weapon.setLocalTranslation(new Vector3f(0.6f,0.8f,-1.3f));
//
// modelNode.attachChild(weapon);
// player.attachChild(modelNode);
ViewPortState fps = new ViewPortState();
stateManager.attach(fps);
cam.setViewPort(0.0f, 1.0f, 0.0f, 1.0f);
}
public void initKeys() {
this.inputManager.addMapping("Left", new KeyTrigger(keyInput.KEY_A));
this.inputManager.addMapping("Right", new KeyTrigger(keyInput.KEY_D));
this.inputManager.addMapping("Front", new KeyTrigger(keyInput.KEY_W));
this.inputManager.addMapping("Back", new KeyTrigger(keyInput.KEY_S));
this.inputManager.addListener(this, "Left");
this.inputManager.addListener(this, "Right");
this.inputManager.addListener(this, "Front");
this.inputManager.addListener(this, "Back");
}
@Override
public void simpleUpdate(float tpf){
Vector3f camDir = cam.getDirection().mult(10f);
Vector3f camLeft = cam.getLeft().mult(5f);
walkDirection.set(0, 0, 0);
if(left) {
walkDirection.addLocal(camLeft);
}
if(right) {
walkDirection.addLocal(camLeft.negate());
}
if(front) {
walkDirection.addLocal(camDir);
}
if(back) {
camDir = cam.getDirection().mult(2.5f);
walkDirection.addLocal(camDir.negate());
}
walkDirection.setY(0.0f);
playerControl.setWalkDirection(walkDirection);
cam.setLocation(player.getLocalTranslation().add(0,1.8f,0));
player.setLocalRotation(cam.getRotation());
}
public void onAction(String name, boolean isPressed, float tpf){
if(name.equals("Left")) {
left = isPressed;
} else if(name.equals("Right")) {
right = isPressed;
} else if(name.equals("Front")) {
front = isPressed;
} else if(name.equals("Back")) {
back = isPressed;
} else if(name.equals("Jump")) {
playerControl.jump();
}
}
}
and the viewport state
public class ViewPortState extends AbstractAppState {
final int SHADOWMAP_SIZE = 1024;
private Camera cam;
private ViewPort view;
private Node root;
private AssetManager assetManager;
private Node weapon;
public ViewPortState(){
root = new Node("root");
}
public Node getRoot(){
return this.root;
}
public Camera getCamera(){
return this.cam;
}
@Override
public void initialize(AppStateManager stateManager, Application app) {
super.initialize(stateManager, app);
this.assetManager = app.getAssetManager();
root = new Node("ViewPort Root");
//root.setCullHint(CullHint.Never);
cam = app.getCamera();
cam.setViewPort(0.0f, 1.0f, 0.0f, 1.0f);
this.initWeapon(app);
this.view = app.getRenderManager().createPostView("WeaponViewPort", cam);
view.setEnabled(true);
view.setClearFlags(false, true, false);
view.attachScene(root);
//Light
this.setUpLight();
root.updateLogicalState(1);
root.updateGeometricState();
}
public void setUpLight() {
// We add light so we see the scene
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(1.3f));
root.addLight(al);
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
root.addLight(dl);
// DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, this.SHADOWMAP_SIZE, 4);
// dlsr.setLight(dl);
// view.addProcessor(dlsr);
}
private void initWeapon(Application app){
weapon = (Node)app.getAssetManager().loadModel("Models/Weapons/M81/M81.j3o");
weapon.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
weapon.setLocalScale(0.75f);
weapon.setLocalTranslation(4f, -5f, 0);
weapon.rotate(0,FastMath.PI,0);
//Material weaponMat = new Material(assetManager, "Common/MatDefs/Misc/ColoredTextured.j3md");
//weapon.setMaterial(weaponMat);
this.root.attachChild(weapon);
}
@Override
public void update(float tpf) {
root.updateLogicalState(tpf);
//gun alignment
Vector3f vectorDifference = new Vector3f(cam.getLocation().subtract(weapon.getWorldTranslation()));
weapon.setLocalTranslation(vectorDifference.addLocal(weapon.getLocalTranslation()));
Quaternion worldDiff = new Quaternion(cam.getRotation().mult(weapon.getWorldRotation().inverse()));
weapon.setLocalRotation(worldDiff.multLocal(weapon.getLocalRotation()));
//Move gun to the bottom right of the screen
weapon.move(cam.getDirection().mult(3));
weapon.move(cam.getUp().mult(-0.8f));
weapon.move(cam.getLeft().mult(-1f));
weapon.rotate(0.0f,0,0);
}
@Override
public void render(RenderManager rm){
root.updateGeometricState();
}
@Override
public void cleanup() {
super.cleanup();
//TODO: clean up what you initialized in the initialize method,
//e.g. remove all spatials from rootNode
//this is called on the OpenGL thread after the AppState has been detached
}
}
Once again thank you all for all your help.