0

I have tried a very simple 3rd person camera using a freely falling (under gravity) bullet sphere. And in render() I have tried to set the camera position slightly above the sphere and set the look-at of camera according to the direction of movement of sphere.

The sphere is rendering ok initially for little duration , but later on it is gradually (approx after 5 seconds) becoming smaller or may be moving away from camera or fluctuations is size of sphere is observed.

I have used the following code:

package a.b.c;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.bullet.collision.btBoxShape;
import com.badlogic.gdx.physics.bullet.collision.btBroadphaseInterface;
import com.badlogic.gdx.physics.bullet.collision.btCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher;
import com.badlogic.gdx.physics.bullet.collision.btCollisionShape;
import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase;
import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.collision.btSphereShape;
import com.badlogic.gdx.physics.bullet.dynamics.btConstraintSolver;
import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody;
import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody.btRigidBodyConstructionInfo;
import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver;
import com.badlogic.gdx.physics.bullet.linearmath.btDefaultMotionState;
import com.badlogic.gdx.tests.bullet.BaseBulletTest;
import com.badlogic.gdx.tests.bullet.BulletTest;
    import com.badlogic.gdx.utils.Array;


public class BasicBulletTest1 implements ApplicationListener {
    ModelBatch modelBatch;
    Environment lights;
    btRigidBody sphereBody ;
    ModelBuilder modelBuilder = new ModelBuilder();
    ModelInstance sphere;
    btCollisionConfiguration collisionConfiguration;
    btCollisionDispatcher dispatcher;
    btBroadphaseInterface broadphase;
    btConstraintSolver solver;
    btDynamicsWorld collisionWorld;
    Vector3 gravity = new Vector3(0, -9.81f, 0);
    Vector3 tempVector = new Vector3();

    Array<Model> models = new Array<Model>();
    Array<ModelInstance> instances = new Array<ModelInstance>();
    Array<btDefaultMotionState> motionStates = new Array<btDefaultMotionState>();
    Array<btRigidBodyConstructionInfo> bodyInfos = new Array<btRigidBodyConstructionInfo>();
    Array<btCollisionShape> shapes = new Array<btCollisionShape>();
    Array<btRigidBody> bodies = new Array<btRigidBody>();
    public PerspectiveCamera camera;
    @Override
    public void create () {



        lights = new Environment();
        lights.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.2f, 0.2f, 0.2f, 1.f));
        lights.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -0.5f, -1f, -0.7f));

        // Set up the camera
final float width = Gdx.graphics.getWidth();
final float height = Gdx.graphics.getHeight();
if (width > height)
    camera = new PerspectiveCamera(67f, 3f * width / height, 3f);
else
    camera = new PerspectiveCamera(67f, 3f, 3f * height / width);
camera.position.set(0f, 35f, 0f);
camera.lookAt(0, 0, 0);
camera.update();
// Create the model batch
modelBatch = new ModelBatch();
// Create some basic models
final Model groundModel = modelBuilder.createRect(
    20f,
    0f,
    -20f,
    -20f,
    0f,
    -20f,
    -20f,
    0f,
    20f,
    20f,
    0f,
    20f,
    0,
    1,
    0,
    new Material(ColorAttribute.createDiffuse(Color.BLUE), ColorAttribute.createSpecular(Color.WHITE), FloatAttribute
        .createShininess(16f)), Usage.Position | Usage.Normal);
models.add(groundModel);
final Model sphereModel = modelBuilder.createSphere(
    1f,
    1f,
    1f,
    10,
    10,
    new Material(ColorAttribute.createDiffuse(Color.RED), ColorAttribute.createSpecular(Color.WHITE), FloatAttribute
        .createShininess(64f)), Usage.Position | Usage.Normal);
models.add(sphereModel);
// Load the bullet library
BaseBulletTest.init(); // Normally use: Bullet.init();
// Create the bullet world
collisionConfiguration = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfiguration);
broadphase = new btDbvtBroadphase();
solver = new btSequentialImpulseConstraintSolver();
collisionWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
collisionWorld.setGravity(gravity);
// Create the shapes and body construction infos
btCollisionShape groundShape = new btBoxShape(tempVector.set(20, 0, 20));
shapes.add(groundShape);
btRigidBodyConstructionInfo groundInfo = new btRigidBodyConstructionInfo(0f, null, groundShape, Vector3.Zero);
bodyInfos.add(groundInfo);
btCollisionShape sphereShape = new btSphereShape(0.5f);
shapes.add(sphereShape);
sphereShape.calculateLocalInertia(1f, tempVector);
btRigidBodyConstructionInfo sphereInfo = new btRigidBodyConstructionInfo(1f, null, sphereShape, tempVector);
bodyInfos.add(sphereInfo);
// Create the ground
ModelInstance ground = new ModelInstance(groundModel);
instances.add(ground);
btDefaultMotionState groundMotionState = new btDefaultMotionState();
groundMotionState.setWorldTransform(ground.transform);
motionStates.add(groundMotionState);
btRigidBody groundBody = new btRigidBody(groundInfo);
groundBody.setMotionState(groundMotionState);
bodies.add(groundBody);
collisionWorld.addRigidBody(groundBody);
// Create the spheres
//for (float x = -10f; x <= 10f; x += 2f) {
//for (float y = 5f; y <= 15f; y += 2f) {
//for (float z = 0f; z <= 0f; z += 2f) {
float x=30,y=10,z=-10;
             sphere = new ModelInstance(sphereModel);
            instances.add(sphere);
            sphere.transform.trn(x + 0.1f * MathUtils.random(), y + 0.1f * MathUtils.random(), z + 0.1f * MathUtils.random());
            btDefaultMotionState sphereMotionState = new btDefaultMotionState();
            sphereMotionState.setWorldTransform(sphere.transform);
            motionStates.add(sphereMotionState);
             sphereBody = new btRigidBody(sphereInfo);
            sphereBody.setMotionState(sphereMotionState);
            bodies.add(sphereBody);
            collisionWorld.addRigidBody(sphereBody);
        //}
//}
//}
}
private Vector3 positionOld=new Vector3();
private Vector3 positionNew=new Vector3();

@Override
public void render () {
    sphereBody.getWorldTransform().getTranslation(positionOld);     


    Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);


    ((btDynamicsWorld)collisionWorld).stepSimulation(Gdx.graphics.getDeltaTime(), 5);


    int c = motionStates.size;
    for (int i = 0; i < c; i++) {
        motionStates.get(i).getWorldTransform(instances.get(i).transform);
    }

    modelBatch.begin(camera);
    modelBatch.render(instances, lights);
    modelBatch.end();



    //super.render();
sphereBody.getWorldTransform().getTranslation(positionNew);

Vector3 subV=positionNew.cpy();
Vector3 temp=positionNew.cpy();
subV.sub(positionOld);
//System.out.println("OLD: "+positionOld+" NEW: "+positionNew+" Temp"+temp);
//positionNew.z=positionNew.z+3;
temp.y=temp.y+3;
camera.position.set(temp);
System.out.println(subV.y+"                                                                             "+Gdx.graphics.getDeltaTime()+"        "+positionOld);
    camera.lookAt(positionNew.add(subV));
    camera.update();
}

@Override
public void dispose () {
    collisionWorld.dispose();
    solver.dispose();
    broadphase.dispose();
    dispatcher.dispose();
    collisionConfiguration.dispose();

    for (btRigidBody body : bodies)
        body.dispose();
    bodies.clear();
    for (btDefaultMotionState motionState : motionStates)
        motionState.dispose();
    motionStates.clear();
    for (btCollisionShape shape : shapes)
        shape.dispose();
    shapes.clear();
    for (btRigidBodyConstructionInfo info : bodyInfos)
        info.dispose();
    bodyInfos.clear();

    modelBatch.dispose();
    instances.clear();
    for (Model model : models)
        model.dispose();
    models.clear();
}

@Override
public void resize (int width, int height) {
    // TODO Auto-generated method stub

}

@Override
public void pause () {
    // TODO Auto-generated method stub

}

@Override
public void resume () {
    // TODO Auto-generated method stub

    }
}

This is the starter class

import a.b.c.BasicBulletTest1;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;

public class Main {
    public static void main(String[] args) {
        LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
        cfg.title = "hello-world";

        cfg.width = 640;
        cfg.height = 480;

        new LwjglApplication(new BasicBulletTest1(), cfg);

    }
}

Any one please help me with this issue and also please help me in creating a simple 3 rd person camera.

Can any one help me in this please .. I need a 3 rd person camera for libgdx 3d

Thank you.

user1573344
  • 63
  • 1
  • 1
  • 8
  • 1
    Maybe this will help you: https://github.com/xoppa/world/blob/master/src/com/xoppa/android/world/ChaseCamera.java – noone Nov 26 '14 at 10:08
  • Thank you for link. But can you please let me know what went wrong in above code.Because I think the issue is with libgdx or may be I am using it in wrong way. – user1573344 Nov 26 '14 at 13:02

1 Answers1

0
Vector3 subV=positionNew.cpy();
subV.sub(positionOld);
camera.lookAt(positionNew.add(subV));

This is equivalent to

camera.lookAt(positionNew + positionNew - positionOld); // Hypothetical non-java code

After some time, difference between positionNew and positionOld will become substantial.

It would be better to normalize subV to a fixed magnitude for stability.

Hope this helps.

Tanmay Patil
  • 6,882
  • 2
  • 25
  • 45
  • Thanks for your input , but as the object is freely falling with gravity of 9.8 the gap between positionOld and positionNew will also insrease gradually. Hense it may not be approximately equal to positionNew. Please correct me if I am worng . – user1573344 Nov 27 '14 at 10:05