javaopenglcameralwjgljbullet

LWJGL first person camera using jBullet


I've got a camera set up, and I can move with WASD and rotate the view with the mouse. But now comes the problem: I want to add physics to the camera/player, so that it "interacts" with my other jBullet objects. How do I do that? I thought about creating a RigidBody for the camera and storing the position there, so that jBullet can apply its physics to the camera. Then, when I need to change something (the position), I could simply change it in the RigidBody. But I didn't find any methods for editing the position.

Can you push me in the right direction or maybe give me an example source code?


Solution

  • I was asking the same question myself a few days ago. My solution was as Sierox said. To create a RigidBody of BoxShape and add that to the DynaicsWorld. To move the camera arund, apply force to its rigidbody. I have damping set to .999 for linear and 1 for angular to stop the camera when no force is applied, i.e. the player stops pressing the button.

    I also use body.setAngularFactor(0); so the box isn't tumbling all over the place. Also set the mass really low as not to interfere too much with other objects, but still be able to jump on then and run into them, and otherwise be affected by them.

    Remember to convert your x,y, and z coordinates to cartesian a plane so you move in the direction of the camera. i.e.

    protected void setCartesian(){//set xyz to a standard plane
        yrotrad = (float) (yrot / 180 * Math.PI);
        xrotrad = (float) (xrot / 180 * Math.PI);
        float pd = (float) (Math.PI/180);
        x = (float) (-Math.cos(xrot*pd)*Math.sin(yrot*pd));
        z = (float) (-Math.cos(xrot*pd)*Math.cos(yrot*pd));
        //y = (float) Math.sin(xrot*pd);
    }//..
    
    public void forward(){// move forward from position in direction of camera
        setCartesian();
        x += (Math.sin(yrotrad))*spd;
        z -= (Math.cos(yrotrad))*spd;
        //y -= (Math.sin(xrotrad))*spd;
        body.applyForce(new Vector3f(x,0,z),getThrow());
    }//..
    
    
    public Vector3f getThrow(){// get relative position of the camera
    
        float nx=x,ny=y,nz=z;
        float xrotrad, yrotrad;
        yrotrad = (float) (yrot / 180 * Math.PI);
        xrotrad = (float) (xrot / 180 * Math.PI);
        nx += (Math.sin(yrotrad))*2;
        nz -= (Math.cos(yrotrad))*2;
        ny -= (Math.sin(xrotrad))*2;
        return new Vector3f(nx,ny,nz);
    }//..
    

    to jump just use body.setLinearVelocity(new Vector3f(0,jumpHt,0)); and set jumpHt to whatever velocity you wish.

    I use getThrow to return a vector for other objects i may be "throwing" on screen or carrying. I hope I answered your question and didn't throw in too much non-essential information.I'll try and find the source that gave me this idea. I believe it was on the Bullet forums.

    ------- EDIT ------

    Sorry to have left that part out

    once you have the rigid body functioning properly you just have to get it's coordinates and apply that to your camera for example:

    float mat[] = new float[16];
    
    Transform t = new Transform();
    t = body.getWorldTransform(t);
    t.origin.get(mat);
    
            x = mat[0];
            y = mat[1];
            z = mat[2];
    
       gl.glRotatef(xrot, 1, 0, 0);  //rotate our camera on teh x-axis (left and right)
       gl.glRotatef(yrot, 0, 1, 0);  //rotate our camera on the y-axis (up and down)
       gl.glTranslatef(-x, -y, -z); //translate the screen to the position of our camera
    

    In my case I'm using OpenGL for graphics. xrot and yrot represent the pitch and yaw of your camera. the code above gets the world transform in the form of a matrix and for the purposes of the camera you need only to pull the x,y, and z coordinates then apply the transform.

    from here, to move the camera, you can set the linear velocity of the rigid body to move the camera or apply force.