Jump to content
  • Advertisement
Ali Aman

Bullet physics with modern openGL lwjgl

Recommended Posts

I need a tutorial on how to implement Bullet Physics with Modern OpenGL, otherwise here is my problem:

I am currently working on a game engine in LWJGL, legacy OpenGL fixed function pipeline. I am using Bullet Physics library for my physics engine and so far, everything is working excellent (cubes are colliding perfectly, spheres are colliding perfectly) but I don’t want to work in Legacy OpenGL, I want to work with modern OpenGL. The problem is that to make everything work perfectly in legacy OpenGL (my situation currently), I have to use glMultMatrix(). Now if I want to work with Modern OpenGL and have same results, I don’t know how. Because glMultMatrix() is deprecated, it can NOT be used in modern OpenGL. Source code (not all of it):

Share this post


Link to post
Share on other sites
Advertisement
43 minutes ago, Ali Aman said:

LWJGL, legacy OpenGL fixed function pipeline. I am using Bullet Physics library for my physics engine

This is not a Game Design matter. Moving to appropriate forum.

Share this post


Link to post
Share on other sites

Did you mean to include some source code in your post? (I see 'Source code' at the end, but don't see anything after that.)

Are you just using the OpenGL matrix functions for rendering purposes? Or are you also using them for physics by querying matrices from OpenGL?

In other words, what functionality is it exactly that you're currently using OpenGL's matrix functions for, but that you want to implement differently?

Share this post


Link to post
Share on other sites

I don't use OpenGL (or at least not in years) and I'm not sure why it was removed. However you can probably write that function in 10 minutes. Just look up matrix multiplication. Here's the wiki page:

https://en.wikipedia.org/wiki/Matrix_multiplication

Go down to the illustration for the simple explanation.  Alternatively you can find some library which  is optimized for the latest intel intrinsics like this one:

https://software.intel.com/en-us/mkl

Share this post


Link to post
Share on other sites

To translate to modern OpenGL 3.3+ you have to:

1.) Build the matrix stack yourself, as every gl*Matrix* function is deprecated

2.) You cannot use any glBegin(), glVertex*(), glColor*() functions anymore -> Use VBO instead.

3.) You cannot use glClient*() related functions, such as glClientActiveTexture or glEnableClientState

4.) You need to use at least one active shader program, because there is no function pipeline anymore

5.) You need a active vertex array, otherwise you wont see anything (Some drivers have a default VA bound, so keep that in mind)

 

For more details see the following tutorial:

https://ahbejarano.gitbook.io/lwjglgamedev/

Share this post


Link to post
Share on other sites
23 hours ago, Zakwayda said:

Did you mean to include some source code in your post? (I see 'Source code' at the end, but don't see anything after that.)

Are you just using the OpenGL matrix functions for rendering purposes? Or are you also using them for physics by querying matrices from OpenGL?

In other words, what functionality is it exactly that you're currently using OpenGL's matrix functions for, but that you want to implement differently?

Yes, I did mean to include the source code but unfortunately forgot it. I'll paste it again so the problem is more clear. I got a bit updated with my code and moved onto modern opengl (>3.0). Every object is translating appropriately, but they are not rotating as they should.

My problem is clearly in the code commented in the render() method.  

 

package renderEngine;

import java.util.HashSet;
import java.util.Set;

import javax.vecmath.Quat4f;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.glu.Sphere;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.Color;
import org.newdawn.slick.TrueTypeFont;

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.DefaultCollisionConfiguration;
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.ConstraintSolver;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.MotionState;
import com.bulletphysics.linearmath.Transform;

import abstracts.GameObject;
import enums.ObjectID;
import shaders.Shader;
import tools.Utils;

public class Game {
	
	public static Loader loader;
	public static BufferedImageLoader imageLoader = new BufferedImageLoader();

	private static final Transform DEFAULT_BALL_TRANSFORM = new Transform(new javax.vecmath.Matrix4f(new Quat4f(0, 0, 0, 1), new javax.vecmath.Vector3f(0, 35, 0), 1.0f));
	
	private Renderer renderer;
	private Shader shader;
	private Handler handler;
	private Camera camera;
	
	private static DynamicsWorld dynamicsWorld;
    private static Set<RigidBody> balls = new HashSet<RigidBody>();
    private static RigidBody controlBall;
    private static boolean applyForce = false;
    private static boolean createNewShape = false;
    private static boolean resetControlBall = false;
    private static Sphere sphere = new Sphere();
    
    private void setUpPhysics() {
    	Transform DEFAULT_BALL_TRANSFORM = new Transform(new javax.vecmath.Matrix4f(new Quat4f(0, 0, 0, 1), 
    	new javax.vecmath.Vector3f(0, 17, -10), 1.0f));
        BroadphaseInterface broadphase = new DbvtBroadphase();
        CollisionConfiguration collisionConfiguration = new DefaultCollisionConfiguration();
        CollisionDispatcher dispatcher = new CollisionDispatcher(collisionConfiguration);
        ConstraintSolver solver = new SequentialImpulseConstraintSolver();
        dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
        dynamicsWorld.setGravity(new javax.vecmath.Vector3f(0, -10 /* m/s2 */, 0));
        CollisionShape groundShape = new StaticPlaneShape(new javax.vecmath.Vector3f(0, 1, 0), 0.25f /* m */);
        CollisionShape ballShape = new SphereShape(0.5f);
        MotionState groundMotionState = new DefaultMotionState(new Transform(new javax.vecmath.Matrix4f(
                new Quat4f(0, 0, 0, 1),
                new javax.vecmath.Vector3f(0, 0, 0), 1.0f)));
        RigidBodyConstructionInfo groundBodyConstructionInfo = new RigidBodyConstructionInfo(0, groundMotionState, groundShape, new javax.vecmath.Vector3f(0, 0, 0));
        groundBodyConstructionInfo.restitution = 0.25f;
        RigidBody groundRigidBody = new RigidBody(groundBodyConstructionInfo);
        dynamicsWorld.addRigidBody(groundRigidBody);
        MotionState ballMotionState = new DefaultMotionState(DEFAULT_BALL_TRANSFORM);
        javax.vecmath.Vector3f ballInertia = new javax.vecmath.Vector3f(0, 0, 0);
        ballShape.calculateLocalInertia(2.5f, ballInertia);
        RigidBodyConstructionInfo ballConstructionInfo = new RigidBodyConstructionInfo(2.5f, ballMotionState, ballShape, ballInertia);
        ballConstructionInfo.restitution = 0.5f;
        ballConstructionInfo.angularDamping = 0.95f;
        controlBall = new RigidBody(ballConstructionInfo);
        controlBall.setActivationState(CollisionObject.DISABLE_DEACTIVATION);
        balls.add(controlBall);
        dynamicsWorld.addRigidBody(controlBall);
    }
	private static TrueTypeFont font;
	private static TrueTypeFont font2;
	
	private Game() {
		try {			
			Display.setDisplayMode(new DisplayMode(1250, 660));
			Display.setTitle("Game");
			Display.setLocation(54, 32);
			Display.create();
		} catch (LWJGLException e) {
			e.printStackTrace();
		}
	}
	
	private void init() {
		setUpPhysics();
		handler = new Handler();
		camera = new Camera(new Vector3f(0, 17, 0));
		loader = new Loader();
		shader = new Shader("src/shaders/Vertex.glsl", "src/shaders/Fragment.glsl");
		renderer = new Renderer(shader);
		GameObject.init();
	}
	
	private void run() {
		while(!Display.isCloseRequested()) {
			render();
			tick();
			input();
		}
		destroy();
	}
	
	private void render() {
		renderer.prepare();		
		shader.enable();
		Matrix4f viewMatrix = Utils.createViewMatrix(camera);
		shader.loadMatrix(viewMatrix, "viewMatrix");
		sphere.setDrawStyle(GLU.GLU_SILHOUETTE);
		for(RigidBody body : balls) {
			javax.vecmath.Vector3f ballPosition = body.getWorldTransform(new Transform()).origin;
			
			Matrix4f transformationMatrix = new Matrix4f();
			
			transformationMatrix.translate(new Vector3f(ballPosition.x, ballPosition.y, ballPosition.z));
			// ^ this translates the object (of course) appropriately. I don't know how to work around rotation them. 
			// I have tried doing transformationMatrix.rotate(...), it does rotate, but not properly. I don't know how to work around that :(
			
			shader.enable();
			shader.loadMatrix(transformationMatrix, "transformationMatrix");
			renderer.setColor(0, 1, 1, 1, shader);
			renderer.render(GameObject.cube, shader);
		}
		
		System.out.println(balls.size());
		
		Matrix4f trans2 = new Matrix4f();
		shader.enable();
		shader.loadMatrix(trans2, "transformationMatrix");
		renderer.setColor(0.5f, 0.5f, 0.5f, 1, shader);
		renderer.render(GameObject.rect, shader);
		shader.enable();
		shader.enable();
		shader.disable();
		shader.disable();
		handler.renderObjects(renderer);
	}
	
	public static void renderTTF(String text, int x, int y, Color color) {
		font.drawString(x, y, text, color);
	    font2.drawString(-1000, -1000, "", Color.green);
	}
	
	private void tick() {
		camera.move();
		handler.tickObjects();
		dynamicsWorld.stepSimulation(1.0f/60.0f);
		Set<RigidBody> ballsToBeRemoved = new HashSet<RigidBody>();
		for(RigidBody body : balls) {
			javax.vecmath.Vector3f position = body.getWorldTransform(new Transform()).origin;
			if(!body.equals(controlBall) && (position.x > -50 || position.x > 50 || position.z < -50 || position.z > 50)) {
				ballsToBeRemoved.add(body);
			}
		}
		
		for(RigidBody body : ballsToBeRemoved) {
			balls.remove(body);
			dynamicsWorld.removeRigidBody(body);
		}
		
		if (applyForce) {
            Transform controlBallTransform = new Transform();
            controlBall.getMotionState().getWorldTransform(controlBallTransform);
            javax.vecmath.Vector3f controlBallLocation = controlBallTransform.origin;
            javax.vecmath.Vector3f cameraPosition = new javax.vecmath.Vector3f(camera.getPosition().x, camera.getPosition().y, camera.getPosition().z);
            javax.vecmath.Vector3f force = new javax.vecmath.Vector3f();
            force.sub(cameraPosition, controlBallLocation);
            controlBall.activate(true);
            controlBall.applyCentralForce(force);
        }
        if (createNewShape) {
            createNewShape(0, 35, 0);
        }
        if (resetControlBall) {
            controlBall.setCenterOfMassTransform(DEFAULT_BALL_TRANSFORM);
            controlBall.setAngularVelocity(new javax.vecmath.Vector3f(0, 0, 0));
            controlBall.setLinearVelocity(new javax.vecmath.Vector3f(0, 0, 0));
            resetControlBall = false;
        }
		for(int i = 0; i < handler.objects.size(); i++) {
			GameObject object = handler.objects.get(i);
			if(object.getId() == ObjectID.PLAYER) {
				if(Keyboard.isKeyDown(Keyboard.KEY_UP)) object.getPosition().y += 0.04f;
				if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)) object.getPosition().y -= 0.04f;
				if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) object.getPosition().x += 0.04f;
				if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) object.getPosition().x -= 0.04f;
			}
		}
		
		Display.sync(60);
		Display.update();
		
		if (Mouse.isButtonDown(0) && !Mouse.isGrabbed()) {
            Mouse.setGrabbed(true);
        } else if (Mouse.isButtonDown(1) && Mouse.isGrabbed()) {
            Mouse.setGrabbed(false);
        } else if (Mouse.isButtonDown(0) && Mouse.isGrabbed()) {
        	createNewShape(0, 35, 0);
            applyForce = true;
        } else {
            applyForce = false;
        }
        while (Keyboard.next()) {
            if (Keyboard.getEventKeyState()) {
                switch (Keyboard.getEventKey()) {
                    case Keyboard.KEY_G:
                        createNewShape = true;
                        break;
                    case Keyboard.KEY_F:
                        resetControlBall = true;
                        break;
                }
            }
        }
	}
	
	private void createNewShape(float x, float y, float z) {
		CollisionShape shape = new SphereShape(3.0f);
        DefaultMotionState motionState = new DefaultMotionState(new Transform(new javax.vecmath.Matrix4f(new Quat4f(0, 0, 0, 1), new javax.vecmath.Vector3f(x, y, z), 1)));
        javax.vecmath.Vector3f inertia = new javax.vecmath.Vector3f();
        shape.calculateLocalInertia(1.0f, inertia);
        RigidBodyConstructionInfo constructionInfo = new RigidBodyConstructionInfo(1.0f, motionState, shape, inertia);
        constructionInfo.restitution = 0.75f;
        RigidBody body = new RigidBody(constructionInfo);
        dynamicsWorld.addRigidBody(body);
        balls.add(body);
        createNewShape = false;
	}
	
	private void input() {
		
	}
	
	private void destroy() {
		Display.destroy();
	}
	
	public static void main(String[] args) {
		Game game = new Game();
		game.init();
		game.run();
	}
	
}

 

 

Share this post


Link to post
Share on other sites

The first thing I'd check is transform order. The order you want is rotate->translate. Depending on the conventions used by the math library, that could equate to:

transformationMatrix.rotate(...)
transformationMatrix.translate(...)

Or:

transformationMatrix.translate(...)
transformationMatrix.rotate(...)

So I would try both. (Eventually it'd be good to find out what conventions are used so you don't have to guess.)

If that doesn't work, then perhaps you could post the code where you apply the rotation, and describe in what way it's behaving incorrectly.

Share this post


Link to post
Share on other sites
16 minutes ago, Zakwayda said:

The first thing I'd check is transform order. The order you want is rotate->translate. Depending on the conventions used by the math library, that could equate to:


transformationMatrix.rotate(...)
transformationMatrix.translate(...)

Or:


transformationMatrix.translate(...)
transformationMatrix.rotate(...)

So I would try both. (Eventually it'd be good to find out what conventions are used so you don't have to guess.)

If that doesn't work, then perhaps you could post the code where you apply the rotation, and describe in what way it's behaving incorrectly.

Ok, I rotated it before translating. I am getting some really weird results :0 the object is rotation really weirdly. I can't elaborate more than that. It is super weird. 

Share this post


Link to post
Share on other sites
Posted (edited)

Can you post the code where you apply the rotation?

If you're still stuck on this, I'd at least try describing the behavior, even if it seems difficult. Here are some possible questions you could answer. Is the object deforming? Or is it keeping its shape but just rotating incorrectly? Does it look like it's 'orbiting' something, or maybe traveling in a spiral or loop? Or is it rotating around its own center, but just incorrectly? Is it rotating too fast or too slow? And so on.

I've seen people post screen captures here occasionally, so that might be one way to show what's happening if it's difficult to describe in words.

Edit: Something else you might check for is degree<->radian conversion errors.

Edited by Zakwayda

Share this post


Link to post
Share on other sites
Posted (edited)
45 minutes ago, Zakwayda said:

Can you post the code where you apply the rotation?

If you're still stuck on this, I'd at least try describing the behavior, even if it seems difficult. Here are some possible questions you could answer. Is the object deforming? Or is it keeping its shape but just rotating incorrectly? Does it look like it's 'orbiting' something, or maybe traveling in a spiral or loop? Or is it rotating around its own center, but just incorrectly? Is it rotating too fast or too slow? And so on.

I've seen people post screen captures here occasionally, so that might be one way to show what's happening if it's difficult to describe in words.

Edit: Something else you might check for is degree<->radian conversion errors.

Yes, it is orbiting vertically--exactly the word I was looking for--and the speed of orbiting gets slower and slower until it stops. The object is keeping its shape but not rotating correctly.  

Edited by Ali Aman

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!