Implementing physics character node with a orbit camera

Hello guys, it's me, again.



I have some questions about, Orbit camera and PhysicsCharacterNode. I already have my orbir camera, which works preatty well.


package jme.game;

import java.util.concurrent.Callable;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.image.Texture.WrapMode;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.MouseInputListener;
import com.jme.light.PointLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.jmex.game.state.BasicGameState;
import com.jmex.jbullet.PhysicsSpace;
import com.jmex.jbullet.collision.shapes.CollisionShape;
import com.jmex.jbullet.nodes.PhysicsNode;

public class SimpleGameState extends BasicGameState {

    protected Camera cam;
    float camX = 0;
    float camY = 0;

    protected float tpf;
    protected Timer timer;

    private Node pivotNode;

    final PhysicsSpace pSpace = PhysicsSpace.getPhysicsSpace(PhysicsSpace.BroadphaseTypes.AXIS_SWEEP_3);
    protected LightState lightState;

    public SimpleGameState(Camera camera) {
        super("Test");
        this.cam = camera;
        init();
    }

    public void init() {
        PointLight light = new PointLight();
        light.setDiffuse(new ColorRGBA(0.75f, 0.75f, 0.75f, 0.75f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        light.setLocation(new Vector3f(100, 100, 100));
        light.setEnabled(true);

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

        timer = Timer.getTimer();

        GameTaskQueueManager.getManager().update(new Callable<Object>() {
        public Object call() throws Exception {
            setupScene();
            rootNode.updateRenderState();
            return null;
        }});

   rootNode.updateRenderState();
        KeyBindingManager.getKeyBindingManager().set("exit", KeyInput.KEY_ESCAPE);
    }

    @Override
    public void update(float tpf) {
   super.update(tpf);
        pSpace.update(tpf);

        timer.update();
        tpf = timer.getTimePerFrame();

   if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit", false)) {
            Main.getGame().finish();
   }
    }

    public void setupScene() {
        Box floorNode = new Box("Floor", Vector3f.ZERO, new Vector3f(20, .2f, 40));

        Texture text = TextureManager.loadTexture(Main.class.getClassLoader()
            .getResource("jme/data/textures/floor.png"),
            Texture.MinificationFilter.Trilinear,
            Texture.MagnificationFilter.Bilinear);

        text.setScale(new Vector3f(9, 5, 5));
        text.setWrap(WrapMode.Repeat);

        PhysicsNode floor = new PhysicsNode(floorNode, CollisionShape.ShapeTypes.MESH, 0);
        floor.setLocalTranslation(Vector3f.ZERO);

        floor.setModelBound(new BoundingBox());
        floor.updateModelBound();

        TextureState tsCarpett = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
                tsCarpett.setTexture(text);
                floorNode.setRenderState(tsCarpett);

        rootNode.attachChild(floor);
        floor.updateRenderState();
        pSpace.add(floor);

        Box roomNode = new Box("Room Wall's and Roof", Vector3f.ZERO, new Vector3f(20, 30, 40));

        Texture tex = TextureManager.loadTexture(Main.class.getClassLoader()
            .getResource("jme/data/textures/wall.png"),
            Texture.MinificationFilter.Trilinear,
            Texture.MagnificationFilter.Bilinear);

        tex.setScale(new Vector3f(9, 9, 9));
        tex.setWrap(WrapMode.Repeat);

        PhysicsNode room = new PhysicsNode(roomNode, CollisionShape.ShapeTypes.MESH, 0);
        room.setLocalTranslation(Vector3f.ZERO);

        room.setModelBound(new BoundingBox());
        room.updateModelBound();

        TextureState tsCarpet = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
        tsCarpet.setTexture(tex);
        roomNode.setRenderState(tsCarpet);

        rootNode.attachChild(roomNode);
        floor.updateRenderState();
        pSpace.add(floor);

        MouseInput.get().addListener(new MouseInputListener() {

            @Override
            public void onWheel(int wheelDelta, int x, int y) {

            }

            @Override
            public void onMove(int xDelta, int yDelta, int newX, int newY) {
                float speed = 35f;
                        
      camX -= xDelta * timer.getTimePerFrame() * speed;
      camY -= yDelta * timer.getTimePerFrame() * speed;

      pivotNode.getLocalRotation().fromAngles(camY*FastMath.DEG_TO_RAD, camX*FastMath.DEG_TO_RAD, 0);
            }

            public void onButton(int arg0, boolean arg1, int arg2, int arg3) {

            }
   });

   pivotNode = new Node("pivot");
        pivotNode.setLocalTranslation(10, 1.8f, 20);
   rootNode.attachChild(pivotNode);

   CameraNode camNode = new CameraNode("camNode", cam);
   camNode.setLocalTranslation(0, 0, 0);
   pivotNode.attachChild(camNode);
    }
}



But, I don't know how implement PhysicsCharacterNode on that Node. I already looked into TestPhysicsCharacterNode, but I'm like, kicking the air, cause I really don't know how. Can someone show me, using my code or something better? I would really appreciate it.

Regards, Gustavo Borba.
*Hope I don't need to bump this topic (:*

Help, please :confused:

http://code.google.com/p/jbullet-jme/source/browse/trunk/jbullet-jme/src/jmetest/jbullet/TestPhysicsCharacter.java

TestPhysicsCharacter.java maybe confusing because it’s based of the vehicle test I believe, but all you really need to do is attach the pivet node to the character physics node


        character=new PhysicsCharacterNode(pivetNode, CollisionShape.ShapeTypes.SPHERE, .1f);
        character.setLocalTranslation(0,3,0);
        rootNode.attachChild(character);
        character.updateRenderState();
        pSpace.add(character);



Then all you need after that is controls to update the position of the character node with the keyboard, similar to how you did it with the mouse.  Just look at the TestPhysicsCharacter.java for reference.

Yeah sure, already tried that. But it gives me this:


java.lang.NullPointerException
        at com.jmex.jbullet.collision.shapes.SphereCollisionShape.createCollisionSphere(SphereCollisionShape.java:93)
        at com.jmex.jbullet.collision.shapes.SphereCollisionShape.createCollisionSphere(SphereCollisionShape.java:89)
        at com.jmex.jbullet.collision.shapes.SphereCollisionShape.<init>(SphereCollisionShape.java:52)
        at com.jmex.jbullet.nodes.PhysicsGhostNode.buildCollisionShape(PhysicsGhostNode.java:108)
        at com.jmex.jbullet.nodes.PhysicsGhostNode.<init>(PhysicsGhostNode.java:80)
        at com.jmex.jbullet.nodes.PhysicsCharacterNode.<init>(PhysicsCharacterNode.java:55)
        at jme.game.SimpleGameState.setupScene(SimpleGameState.java:167)
        at jme.game.SimpleGameState$1.call(SimpleGameState.java:70)
        at com.jme.util.GameTask.invoke(GameTask.java:140)
        at com.jme.util.GameTaskQueue.execute(GameTaskQueue.java:111)
        at com.jmex.game.StandardGame.update(StandardGame.java:378)
        at com.jmex.game.StandardGame.run(StandardGame.java:250)
        at java.lang.Thread.run(Thread.java:619)



Cause, it's like, it thinks it is a sphere, but it's a node. Then it messes with the camera. :/ Help?

Try setting the model bounds of the pivet node with a BoundingSphere before creating the character node.  And call updateModelBound(), etc.

Stills the same problem, here's my code:


pivotNode = new Node("pivot");
        pivotNode.setLocalTranslation(10, 1.8f, 20);
   rootNode.attachChild(pivotNode);

        pivotNode.setModelBound(new BoundingSphere());
        pivotNode.updateModelBound();

        character = new PhysicsCharacterNode(pivotNode, CollisionShape.ShapeTypes.SPHERE, .1f);
        character.setLocalTranslation(0,3,0);
        rootNode.attachChild(character);
        character.updateRenderState();
        pSpace.add(character);

   CameraNode camNode = new CameraNode("camNode", cam);
   camNode.setLocalTranslation(0, 0, 0);
   pivotNode.attachChild(camNode);

Try also:

pivotNode.updateGeometricState(0, true);

after the updateModelBound();

You know how to debug, right?

kinda, can you tell how?

Oh, btw tried that you said, nothing changed :confused:

Try to create the CollisionSphere before instead of using CollisionShape.ShapeTypes.SPHERE


float radius=1;
SphereCollisionShape collShape=new SphereCollisionShape(radius);
character = new PhysicsCharacterNode(pivotNode, collShape, .1f);

I think there are not method PhysicsCharacterNode with that parameters, normen. Compilersays there isn't :confused:

GustavoBorba said:

I think there are not method PhysicsCharacterNode with that parameters, normen. Compilersays there isn't :/

Yes there is, have a look at the javadoc.

So, must be a compiling problem from Netbeans. Take a look at this screenshot:



http://img339.imageshack.us/i/netbeanserror.png/



.


Even if you dont use the svn version, this is definitely in the latest download version as well:

http://jbullet-jme.googlecode.com/files/jbullet-jme-0_9_5-alpha.zip



Why do you take the time making a screenshot and uploading it to imageshack to prove me wrong about software that I wrote instead of using that time to check if you use the latest version :?



Over and out until I see my video of your nuke :stuck_out_tongue:

Now it worked, sorry for all. (:

One more question, I don't know if I should make a new topic for that or something like that, so I am posting here.



I want to know, how to make the player walk in the direction his looking at. I tried to print camX, but it's not 360 degrees, it's infinite. So if someone knows how to do it, please tell me.



Regards,

Gustavo Borba.

GustavoBorba wrote:
I want to know, how to make the player walk in the direction his looking at.
Have you tried asking him nicely?

-

If you want to get the direction you are looking at (with the camera) try:

Vector3f lookingDirection = camera.getDirection()



Otherwise if you want the direction the character Spatial is rotated towards, use the worldrotation of the Spatial:


// Assuming model starts off looking up the z axis
Vector3f lookingDirection = new Vector3f(0f,0f,1f);
character.getWorldRotation().mult(direction,direction );


Okay, thank you for that ansqwer, but getting that Vector, how am I supposed to move the player to there?

GustavoBorba wrote:
how am I supposed to move the player to there?
That vector is a direction of movement, not a location - you cannot move the player there.

When using a physics character you give it a movement direction and let the physics take care of the rest.

Suggested reading:
jmetest.jbullet.TestPhysicsCharacter

Okay, so you mean like this?:


Vector3f lookingDirection = new Vector3f(0f,0f,1f);

walkDirection.addLocal(character.getWorldRotation().mult(direction, direction));

alright then, more like this:

Vector3f lookingDirection = new Vector3f(0f,0f,1f);
character.getWorldRotation().mult(lookingDirection , lookingDirection )
walkDirection.addLocal(lookingDirection );



The typo in my previous was obviously there to test your powers of observation!  ;)