使用JBullet和lwjgl的第三人称相机

时间:2013-12-27 19:13:16

标签: java camera lwjgl jbullet

我正在使用jbullet和lwjgl开发java游戏。我目前在使我的相机跟随车辆时遇到了麻烦。这是我的代码。它跟随汽车直到它旋转。这是代码。可以有人告诉我,我做错了什么?!

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_FRONT_AND_BACK;
import static org.lwjgl.opengl.GL11.GL_LINE;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glCallList;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glPolygonMode;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glTranslated;
import static org.lwjgl.opengl.GL11.*;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.vecmath.Matrix4f;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;

import model.Vehicle;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

import utility.LWJGLTimer;
import utility.LookAtCamera;
import utility.Model;
import utility.OBJLoader;
import utility.TerrainLoader;

import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.broadphase.DbvtBroadphase;
import com.bulletphysics.collision.dispatch.CollisionConfiguration;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.dispatch.CollisionWorld;
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.SphereShape;
import com.bulletphysics.collision.shapes.StaticPlaneShape;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.DynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.Transform;

public class PlanoFight {

    private static LookAtCamera camera;

    Vector3f position = new Vector3f(0, 0, 0);

    private DynamicsWorld dynamicsWorld = null;

    public PlanoFight() {       
        setUpDisplay();
        setUpCamera();
        setUpDisplayLists();
        setUpPhysics();
        initializeGL();
        startGameLoop();
    }

    private void setUpDisplayLists() {

    }

    Vehicle vehicle;
    private void startGameLoop() {
        LWJGLTimer timer = new LWJGLTimer();        
        double delta = 0;
        timer.initialize();
        while (!Display.isCloseRequested()) {
            timer.update();
            delta = timer.getElapsedTime();
            dynamicsWorld.stepSimulation(1f / 60f, 10);
            checkInput();
            update(delta);
            render();
            Display.update();
            Display.sync(60);
        }

        cleanup();
        Display.destroy();
        System.exit(0);
    }

    private void cleanup() {

    }

    private void initializeGL() {
    }

    private void setUpDisplay() {
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(0);
        }
    }

    private void update(double delta) {
        vehicle.update();
    }

    private void render() {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glEnable(GL_DEPTH_TEST);

        vehicle.updateCamera(camera);
        camera.setMatrices();
        vehicle.render();

    }

    public static void main(String ar[]) {
        new PlanoFight();
    }

    private static void setUpCamera() {
        camera = new LookAtCamera(67, 100f, 0.1f, (float) (Display.getWidth() / Display.getHeight()));
        camera.setPosition(new Vector3f(0,5,0));
    }

    private void checkInput() {
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
            vehicle.deacelerate();
        } else if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
            vehicle.accelerate();
        } else if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
            vehicle.steerLeft();
        } else if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
            vehicle.steerRight();
        }
    }

    private void setUpPhysics() {

        BroadphaseInterface bInterface = new DbvtBroadphase();
        CollisionConfiguration configuration = new DefaultCollisionConfiguration();
        CollisionDispatcher dispather = new CollisionDispatcher(configuration);
        SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver();

        dynamicsWorld = new DiscreteDynamicsWorld(dispather, bInterface, solver, configuration);
        dynamicsWorld.setGravity(new Vector3f(0, -10, 0));

        vehicle=new Vehicle(dynamicsWorld);
    }

}

package model;

import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glCallList;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glMultMatrix;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glRotated;
import static org.lwjgl.opengl.GL11.glTranslatef;
import static org.lwjgl.opengl.GL11.glVertex3f;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import javax.vecmath.Vector3f;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.glu.Cylinder;

import utility.LookAtCamera;
import utility.Model;
import utility.OBJLoader;

import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.CompoundShape;
import com.bulletphysics.collision.shapes.TriangleIndexVertexArray;
import com.bulletphysics.dynamics.DynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
import com.bulletphysics.dynamics.vehicle.DefaultVehicleRaycaster;
import com.bulletphysics.dynamics.vehicle.RaycastVehicle;
import com.bulletphysics.dynamics.vehicle.VehicleRaycaster;
import com.bulletphysics.dynamics.vehicle.VehicleTuning;
import com.bulletphysics.dynamics.vehicle.WheelInfo;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.ObjectArrayList;

public class Vehicle {

    private static final int rightIndex = 0;
    private static final int upIndex = 1;
    private static final int forwardIndex = 2;
    private static final Vector3f wheelDirectionCS0 = new Vector3f(0, -1, 0);
    private static final Vector3f wheelAxleCS = new Vector3f(-1, 0, 0);

    private static float gEngineForce = 0.f;
    private static float gBreakingForce = 0.f;

    private static float maxEngineForce = 1000.f;// this should be
                                                    // engine/velocity dependent
    private static float maxBreakingForce = 100.f;

    private static float gVehicleSteering = 0.f;
    private static float steeringIncrement = 0.04f;
    private static float steeringClamp = 0.3f;
    private static float wheelRadius = 0.5f;
    private static float wheelWidth = 0.4f;
    private static float wheelFriction = 1000;// 1e30f;
    private static float suspensionStiffness = 20.f;
    private static float suspensionDamping = 2.3f;
    private static float suspensionCompression = 4.4f;
    private static float rollInfluence = 0.1f;// 1.0f;

    private static final float suspensionRestLength = 0.6f;

    private static final int CUBE_HALF_EXTENTS = 1;

    public RigidBody carChassis;
    public ObjectArrayList<CollisionShape> collisionShapes = new ObjectArrayList<CollisionShape>();
    public BroadphaseInterface overlappingPairCache;
    public CollisionDispatcher dispatcher;
    public ConstraintSolver constraintSolver;
    public DefaultCollisionConfiguration collisionConfiguration;
    public TriangleIndexVertexArray indexVertexArrays;

    public ByteBuffer vertices;

    public VehicleTuning tuning = new VehicleTuning();
    public VehicleRaycaster vehicleRayCaster;
    public RaycastVehicle vehicle;

    public float cameraHeight;

    public float minCameraDistance;
    public float maxCameraDistance;

    private DynamicsWorld dynamicsWorld;

    private Cylinder cylinder;

    private int carChassisHandle;

    Vector3f direction;

    public Vehicle(DynamicsWorld world) {
        this.dynamicsWorld = world;
        carChassis = null;
        cameraHeight = 4f;
        minCameraDistance = 3f;
        maxCameraDistance = 10f;
        indexVertexArrays = null;
        vertices = null;
        vehicle = null;
        cylinder = new Cylinder();
        direction = new Vector3f(0, 0, -1);
        initPhysics();

        try {
            Model model = OBJLoader.loadModel(new File("res/chassis.obj"));
            carChassisHandle = OBJLoader.createDisplayList(model);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void initPhysics() {

        CollisionShape groundShape = new BoxShape(new Vector3f(50, 3, 50));
        collisionShapes.add(groundShape);
        Transform tr = new Transform();
        tr.setIdentity();

        tr.origin.set(0, -4.5f, 0);

        localCreateRigidBody(0, tr, groundShape);

        CollisionShape chassisShape = new BoxShape(new Vector3f(1.0f, 0.5f, 2.0f));
        collisionShapes.add(chassisShape);

        CompoundShape compound = new CompoundShape();
        collisionShapes.add(compound);
        Transform localTrans = new Transform();
        localTrans.setIdentity();
        localTrans.origin.set(0, 1, 0);

        compound.addChildShape(localTrans, chassisShape);

        tr.origin.set(0, 0, 0);

        carChassis = localCreateRigidBody(800, tr, compound);

        Transform t = new Transform();
        carChassis.getWorldTransform(t);
        Vector3f forward = new Vector3f();
        t.basis.getRow(0, forward);
        System.out.println("0 " + forward);
        t.basis.getRow(1, forward);
        System.out.println("1 " + forward);
        t.basis.getRow(2, forward);
        System.out.println("2 " + forward);

        clientResetScene();

        // create vehicle
        {
            vehicleRayCaster = new DefaultVehicleRaycaster(dynamicsWorld);
            vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster);

            // never deactivate the vehicle
            carChassis.setActivationState(CollisionObject.DISABLE_DEACTIVATION);

            dynamicsWorld.addVehicle(vehicle);

            float connectionHeight = 1.2f;

            boolean isFrontWheel = true;

            vehicle.setCoordinateSystem(rightIndex, upIndex, forwardIndex);
            Vector3f connectionPointCS0 = new Vector3f(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2f * CUBE_HALF_EXTENTS - wheelRadius);

            vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);
            connectionPointCS0.set(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2f * CUBE_HALF_EXTENTS - wheelRadius);
            vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);
            connectionPointCS0.set(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2f * CUBE_HALF_EXTENTS + wheelRadius);
            isFrontWheel = false;
            vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);
            connectionPointCS0.set(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2f * CUBE_HALF_EXTENTS + wheelRadius);
            vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            for (int i = 0; i < vehicle.getNumWheels(); i++) {
                WheelInfo wheel = vehicle.getWheelInfo(i);
                wheel.suspensionStiffness = suspensionStiffness;
                wheel.wheelsDampingRelaxation = suspensionDamping;
                wheel.wheelsDampingCompression = suspensionCompression;
                wheel.frictionSlip = wheelFriction;
                wheel.rollInfluence = rollInfluence;
            }
        }

    }

    public void render() {

        float matrix[] = new float[16];

        glColor3f(0, 0, 1);
        glBegin(GL_QUADS);
        glVertex3f(100, -4.5f, 100);
        glVertex3f(100, -4.5f, -100);
        glVertex3f(-100, -4.5f, -100);
        glVertex3f(-100, -4.5f, 100);
        glEnd();
        FloatBuffer buffer;

        Transform chassisTr = new Transform();
        carChassis.getMotionState().getWorldTransform(chassisTr);

        CollisionShape chassisShape = carChassis.getCollisionShape();
        if (chassisShape instanceof CompoundShape) {
            CollisionShape childShape = ((CompoundShape) chassisShape).getChildShape(0);
            if (childShape instanceof BoxShape) {
                Vector3f size = new Vector3f();
                ((BoxShape) childShape).getHalfExtentsWithoutMargin(size);
                System.out.println(size.x + "  " + size.y + "  " + size.z);
                System.out.println(chassisTr.origin.x + " " + chassisTr.origin.y + " " + chassisTr.origin.z);
            }
        }

        chassisTr.getOpenGLMatrix(matrix);
        buffer = BufferUtils.createFloatBuffer(16 * 4);
        buffer.clear();
        buffer.put(matrix);
        buffer.flip();
        glColor3f(0, 1, 0);
        glPushMatrix();
        glMultMatrix(buffer);
        glTranslatef(0, 1f, 0);
        glCallList(carChassisHandle);
        glPopMatrix();

        for (int i = 0; i < vehicle.getNumWheels(); i++) {
            vehicle.updateWheelTransform(i, true);
            Transform wheelTr = vehicle.getWheelInfo(i).worldTransform;
            wheelTr.getOpenGLMatrix(matrix);
            buffer = BufferUtils.createFloatBuffer(16 * 4);
            buffer.clear();
            buffer.put(matrix);
            buffer.flip();
            glColor3f(1, 0, 0);
            glPushMatrix();
            glMultMatrix(buffer);
            glRotated(90, 0, 1, 0);
            cylinder.draw(wheelRadius, wheelRadius, wheelWidth, 10, 10);
            glPopMatrix();
        }
    }

    public void update() {
        int wheelIndex = 2;
        vehicle.applyEngineForce(gEngineForce, wheelIndex);
        vehicle.setBrake(gBreakingForce, wheelIndex);
        wheelIndex = 3;
        vehicle.applyEngineForce(gEngineForce, wheelIndex);
        vehicle.setBrake(gBreakingForce, wheelIndex);
        wheelIndex = 0;
        vehicle.setSteeringValue(gVehicleSteering, wheelIndex);
        wheelIndex = 1;
        vehicle.setSteeringValue(gVehicleSteering, wheelIndex);
    }

    public void clientResetScene() {
        gVehicleSteering = 0f;
        Transform tr = new Transform();
        tr.setIdentity();
        carChassis.setCenterOfMassTransform(tr);
        carChassis.setLinearVelocity(new Vector3f(0, 0, 0));
        carChassis.setAngularVelocity(new Vector3f(0, 0, 0));
        dynamicsWorld.getBroadphase().getOverlappingPairCache().cleanProxyFromPairs(carChassis.getBroadphaseHandle(), dynamicsWorld.getDispatcher());
        if (vehicle != null) {
            vehicle.resetSuspension();
            for (int i = 0; i < vehicle.getNumWheels(); i++) {
                vehicle.updateWheelTransform(i, true);
            }
        }
    }

    public void steerLeft() {
        System.out.println("steer left");
        gVehicleSteering += steeringIncrement;
        if (gVehicleSteering > steeringIncrement) {
            gVehicleSteering = steeringClamp;
        }
    }

    public void steerRight() {
        gVehicleSteering -= steeringIncrement;
        if (gVehicleSteering < -steeringClamp)
            gVehicleSteering = -steeringClamp;
    }

    public void accelerate() {
        gEngineForce = maxEngineForce;
        gBreakingForce = 0.0f;
    }

    public void deacelerate() {
        gBreakingForce = maxBreakingForce;
        gEngineForce = 0.0f;
    }

    public void updateCamera(LookAtCamera camera) {
        Transform chassisWorldTrans = new Transform();
        carChassis.getMotionState().getWorldTransform(chassisWorldTrans);

        Transform characterWorldTrans = chassisWorldTrans;
        Vector3f up = new Vector3f();
        characterWorldTrans.basis.getRow(1, up);
        Vector3f backward = new Vector3f();
        characterWorldTrans.basis.getRow(2, backward);
        backward.scale(-1);
        up.normalize();
        backward.normalize();

        camera.lookAtVector.set(characterWorldTrans.origin);

        Vector3f cameraPosition = new Vector3f(camera.lookAtVector.x,camera.lookAtVector.y,camera.lookAtVector.z);
        up.scale(4);
        cameraPosition.add(up);
        backward.scale(8);
        cameraPosition.add(backward);

//      System.out.println("lookat" + camera.lookAtVector);
//      System.out.println("position " + cameraPosition + " angle " + cameraPosition.angle(camera.lookAtVector));
//      System.out.println(" " + backward + " " + up);

        camera.position.set(cameraPosition);
    }

    public RigidBody localCreateRigidBody(float mass, Transform startTransform, CollisionShape shape) {
        boolean isDynamic = (mass != 0f);

        Vector3f localInertia = new Vector3f(0f, 0f, 0f);
        if (isDynamic) {
            shape.calculateLocalInertia(mass, localInertia);
        }
        DefaultMotionState myMotionState = new DefaultMotionState(startTransform);

        RigidBodyConstructionInfo cInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);

        RigidBody body = new RigidBody(cInfo);

        dynamicsWorld.addRigidBody(body);

        return body;
    }

        public void printVector(Vector3f origin) {
            System.out.println(origin.x + " " + origin.y + " " + origin.z);
        }
    }

0 个答案:

没有答案