Physics error, while adding/removing physics nodes

Im removing physics nodes of the previous map in my game and assigning the current map's physics nodes to the physics space. the event occurs when i enter a portal… when i enter any portal the third time it shows this error.



i dont have any idea what is this error, please help me 


08 21, 10 1:15:29 AM com.jmex.game.DefaultUncaughtExceptionHandler uncaughtException
SEVERE: Main game loop broken by uncaught exception
java.lang.NullPointerException
        at com.bulletphysics.collision.dispatch.CollisionWorld$ConvexResultCallback.needsCollision(CollisionWorld.java:739)
        at com.bulletphysics.collision.dispatch.GhostObject.convexSweepTest(GhostObject.java:111)
        at com.bulletphysics.dynamics.character.KinematicCharacterController.stepUp(KinematicCharacterController.java:450)
        at com.bulletphysics.dynamics.character.KinematicCharacterController.playerStep(KinematicCharacterController.java:236)
        at com.bulletphysics.dynamics.character.KinematicCharacterController.updateAction(KinematicCharacterController.java:137)
        at com.bulletphysics.dynamics.DiscreteDynamicsWorld.updateActions(DiscreteDynamicsWorld.java:456)
        at com.bulletphysics.dynamics.DiscreteDynamicsWorld.internalSingleStepSimulation(DiscreteDynamicsWorld.java:388)
        at com.bulletphysics.dynamics.DiscreteDynamicsWorld.stepSimulation(DiscreteDynamicsWorld.java:338)
        at com.jmex.jbullet.PhysicsSpace.update(PhysicsSpace.java:279)
        at com.jmex.jbullet.PhysicsSpace.update(PhysicsSpace.java:264)
        at salipawpaw.characters.PlayerGameState.update(PlayerGameState.java:155)
        at com.jmex.game.state.GameStateNode.update(GameStateNode.java:71)
        at com.jmex.game.StandardGame.update(StandardGame.java:381)
        at com.jmex.game.StandardGame.run(StandardGame.java:250)
        at java.lang.Thread.run(Thread.java:619)

Please provide more info on how or when you add or remove the objects, "entering a portal" is not really saying anything when I dont know the code :slight_smile:



Cheers,

Normen

sorry,  



I have a static arrayList for each mapGameState. They are declared in their respective game states. The arrayList contains  PhysicsNodes of their map.


public static ArrayList<PhysicsNode> antiphonPhysicsNodeArray = new ArrayList<PhysicsNode>();
public static ArrayList<PhysicsNode> ridanPhysicsNodeArray = new ArrayList<PhysicsNode>();
public static ArrayList<PhysicsNode> coraxPhysicsNodeArray = new ArrayList<PhysicsNode>();



In my Portal class:

I have a portal class for each game state.. this portal class takes care of my gameStates' deactivation and activation when i enter a portal.

I have an import static of the three arrayList in every map

import static salipawpaw.AntiphonGameState.antiphonPhysicsNodeArray;
import static salipawpaw.CoraxGameState.coraxPhysicsNodeArray;
import static salipawpaw.RidanGameState.ridanPhysicsNodeArray;



then when a collision between a portal and the player, the portal class do this


removePhysics();
GameStateManager.getInstance().getChild("CORAX").setActive(false);
            GameStateManager.getInstance().getChild("PLAYER").setActive(false);
            GameStateManager.getInstance().getChild("ANTIPHON").setActive(true);
            setAntiphonPhysics();
            physicsPlayer.setLocalTranslation(new Vector3f(-162.0f, terrainPage.getHeight(-162.0f, 162.0f)+10, 162.0f));


This is the code to remove the current physics

    private void removePhysics() {
        for(int i=0; i<coraxPhysicsNodeArray.size(); i++) {
            physicsSpace.remove(coraxPhysicsNodeArray.get(i));
        }
}
    


This is the code to set the physics of Antiphon map

    private void setAntiphonPhysics() {
        for(int i=0; i<antiphonPhysicsNodeArray.size(); i++) {
            physicsSpace.add(antiphonPhysicsNodeArray.get(i));
        }
    }



Thank You Sir


This is the complete class for CoraxGameState


public class CoraxGameState extends GameState {

    protected Node rootNode;
    protected FogState fogState;
    protected LightState lightState;
    protected ZBufferState zBuffState;
    protected CullState cullState;
    protected Spatial terrain;
    protected Skybox sky;

    protected TerrainPage terrainPage;
    protected CoraxPortals coraxPortals;
    protected CoraxObjects coraxObjects;

    private PhysicsCharacterNode physicsPlayer;
    //private PhysicsSpace physicsSpace = PhysicsSpace.getPhysicsSpace();
    public static ArrayList<PhysicsNode> coraxPhysicsNodeArray = new ArrayList<PhysicsNode>();

    public CoraxGameState(PhysicsCharacterNode physicsPlayer) {
        this.physicsPlayer = physicsPlayer;
        this.setName("CORAX");
        rootNode = new Node("CORAX: ROOT NODE");

        setEnvironment();
        setTerrain();
        setObjects();
        setPortals();

        rootNode.updateRenderState();
        //rootNode.updateGeometricState(0.0f, true);
    }

    private void setEnvironment() {

        try {
            GameTaskQueueManager.getManager().render(new Callable<Object>() {
               public Object call() throws Exception {
                   DisplaySystem.getDisplaySystem().getRenderer().setBackgroundColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
                   return null;
               }
            }).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        zBuffState = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
        zBuffState.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
        zBuffState.setEnabled(true);
        rootNode.setRenderState(zBuffState);

        DirectionalLight dl = new DirectionalLight();
        dl.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
        dl.setDiffuse(new ColorRGBA(0.3f, 0.3f, 0.3f, 1.0f));
        dl.setDirection(new Vector3f(0.5f, -1.0f, 0.0f));
        dl.setEnabled(true);

        lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
        lightState.attach(dl);
        lightState.setEnabled(true);
        rootNode.setRenderState(lightState);

        fogState = DisplaySystem.getDisplaySystem().getRenderer().createFogState();
        fogState.setColor(new ColorRGBA(1.5f, 1.5f, 1.5f, 1.0f));
        fogState.setDensity(10.0f);
        fogState.setStart(1.0f);
        fogState.setEnd(300.0f);
        fogState.setDensityFunction(FogState.DensityFunction.Linear);
        fogState.setQuality(FogState.Quality.PerVertex);
        fogState.setEnabled(true);
        rootNode.setRenderState(fogState);

        cullState = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
        cullState.setCullFace(CullState.Face.Back);
        cullState.setEnabled(true);
        rootNode.setRenderState(cullState);
    }

    private void setTerrain() {
        SpaceTerrain1 spaceTerrain = new SpaceTerrain1();
        terrain = spaceTerrain.getTerrain();
        terrainPage = spaceTerrain.getTerrainPage();

        addTerrainPagePhysics(terrainPage, terrainPage.getLocalTranslation());
        rootNode.attachChild(terrain);
    }

    private void addTerrainPagePhysics(TerrainPage terrainPage, Vector3f translation) {
       for (Spatial childTerrain : terrainPage.getChildren()) {
                       if (childTerrain instanceof TerrainBlock) {
            MeshCollisionShape collisionShape = new MeshCollisionShape((TriMesh)childTerrain);
            PhysicsNode terrainPhysicsNode = new PhysicsNode(null, collisionShape, 0);
            terrainPhysicsNode.setLocalTranslation(childTerrain.getLocalTranslation().add(translation));
                                coraxPhysicsNodeArray.add(terrainPhysicsNode);
         } else {
            addTerrainPagePhysics((TerrainPage)childTerrain, translation.add(childTerrain.getLocalTranslation()));
         }
      }
    }


    @Override
    public void update(float tpf) {
        coraxPortals.update(tpf);
        portalCheck();
        rootNode.updateGeometricState(tpf, true);
    }

    @Override
    public void render(float tpf) {
        DisplaySystem.getDisplaySystem().getRenderer().draw(rootNode);
        coraxPortals.draw();
    }

    @Override
    public void cleanup() {
    }

    private void setPortals(){
        coraxPortals = new CoraxPortals(physicsPlayer, terrainPage);
    }

    public TerrainPage getTerrainPage() {
        return terrainPage;
    }

    public void portalCheck(){
        if(SalipawpawGameState.isEntered) {
            coraxPortals.portalCheck();
        }
    }

    private void setObjects() {
        coraxObjects = new CoraxObjects(terrainPage);
        rootNode.attachChild(coraxObjects.getObjectNode());
    }

  
    public Node getRootNode() {
        return rootNode;
    }

}



And its portal class, CoraxPortal class



import com.jme.bounding.BoundingBox;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jmex.game.state.GameStateManager;
import com.jmex.jbullet.nodes.PhysicsCharacterNode;
import com.jmex.terrain.TerrainPage;
import java.util.ArrayList;
import salipawpaw.util.Portal;
import static salipawpaw.AudioFactory.portalTrack;
import static salipawpaw.AntiphonGameState.antiphonPhysicsNodeArray;
import static salipawpaw.CoraxGameState.coraxPhysicsNodeArray;
import static salipawpaw.RidanGameState.ridanPhysicsNodeArray;
import static salipawpaw.SalipawpawGameState.physicsSpace;

public class CoraxPortals {

    protected ArrayList<Portal> portalList;
    protected Node portalNode;

    private TerrainPage terrainPage;
    protected PhysicsCharacterNode physicsPlayer;

    public CoraxPortals(PhysicsCharacterNode physicsPlayer, TerrainPage terrainPage) {
        portalNode = new Node("CORAX PORTAL NODE");
        portalList = new ArrayList<Portal>();

        this.terrainPage = terrainPage;
        this.physicsPlayer = physicsPlayer;

        setPortals();
    }

    public void setPortals() {

        ZBufferState zBuffState = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
        zBuffState.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
        zBuffState.setEnabled(true);
        portalNode.setRenderState(zBuffState);

        // to Antiphon
        Portal portal0 = new Portal("CORAX: PORTAL 0");
        portal0.setModelBound(new BoundingBox());
        portal0.updateModelBound();
        portal0.setLocalTranslation(new Vector3f(-20.0f, terrainPage.getHeight(-20.0f, 139.0f) + 0.80f, 139.0f));
        portalList.add(portal0);
        portalNode.attachChild(portal0);

        //to Ridan
        Portal portal1 = new Portal("CORAX: PORTAL 1");
        portal1.setModelBound(new BoundingBox());
        portal1.updateModelBound();
        portal1.setLocalTranslation(new Vector3f(139.0f, terrainPage.getHeight(139.0f, -174.0f) + 0.5f, -174.0f));
        portalList.add(portal1);
        portalNode.attachChild(portal1);
        
        portalNode.updateRenderState();
        portalNode.updateGeometricState(0.0f, true);
    }

    public void update(float tpf) {
        portalList.get(0).update(tpf);
        portalList.get(1).update(tpf);
        portalNode.updateGeometricState(tpf, true);
    }

    public void draw() {
        DisplaySystem.getDisplaySystem().getRenderer().draw(portalNode);
    }

    public void portalCheck() {

        boolean isEntered = false;
        int portalIndex = -1;

        if(portalList.get(0).getWorldBound().intersects(physicsPlayer.getWorldBound())) {
            isEntered = true;
            portalIndex = 0;
        }
        else if(portalList.get(1).getWorldBound().intersects(physicsPlayer.getWorldBound())) {
            isEntered = true;
            portalIndex = 1;
        }

        if(isEntered) {
            mapTransition(portalIndex);
        }
    }

    private void mapTransition(int portalIndex) {

        portalTrack.play();
        removePhysics();

        if(portalIndex == 0) {
            GameStateManager.getInstance().getChild("CORAX").setActive(false);
            GameStateManager.getInstance().getChild("PLAYER").setActive(false);
            GameStateManager.getInstance().getChild("ANTIPHON").setActive(true);
            setAntiphonPhysics();
            physicsPlayer.setLocalTranslation(new Vector3f(-162.0f, terrainPage.getHeight(-162.0f, 162.0f)+10, 162.0f));
        }

        if(portalIndex == 1) {
            GameStateManager.getInstance().getChild("CORAX").setActive(false);
            GameStateManager.getInstance().getChild("PLAYER").setActive(false);
            GameStateManager.getInstance().getChild("RIDAN").setActive(true);
            setRidanPhysics();
            physicsPlayer.setLocalTranslation(new Vector3f(173.0f, terrainPage.getHeight(173.0f, -82.0f)+10, -82.0f));
        }
    }

    private void removePhysics() {
        for(int i=0; i<coraxPhysicsNodeArray.size(); i++) {
            physicsSpace.remove(coraxPhysicsNodeArray.get(i));
        }
    }

    private void setAntiphonPhysics() {
        for(int i=0; i<antiphonPhysicsNodeArray.size(); i++) {
            physicsSpace.add(antiphonPhysicsNodeArray.get(i));
        }
    }

    private void setRidanPhysics() {
        for(int i=0; i<ridanPhysicsNodeArray.size(); i++) {
            physicsSpace.add(ridanPhysicsNodeArray.get(i));
        }
    }
}



Uhm, the problem happens because of a character node, so its not the pbysicsnodes themselves. When do you remove them? In the exact moment the collision happens? Maybe you should only register the removal when you get a collision and then actually remove it in the update() loop (or use a Callable). While the collision happens the physics space is still updated and that could lead to problems.

Cheers,

Normen

The removal happens when a collision happens and a key is pressed. I solved the problem, but solved it by destroying the physics space and recreating it… then attach the new physics nodes. it may not be the best way but works for me…  :smiley:

The PhysicsCharacterNode gives me a lot of headache… 



Thanks