Libgdx - Bullet Physics Камера от 3-го лица, Объект становится меньше или удаляется от камеры с течением времени

Я попробовал очень простую камеру от третьего лица, используя свободно падающую (под действием силы тяжести) пулевую сферу. И в render() я попытался установить положение камеры немного выше сферы и установить вид камеры в соответствии с направлением движения сферы.

Сначала сфера визуализируется нормально в течение небольшого промежутка времени, но позже она постепенно (примерно через 5 секунд) становится меньше или может удаляться от камеры, или наблюдаются колебания размера сферы.

Я использовал следующий код:

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

    }
}

Это начальный класс

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);

    }
}

Кто-нибудь, пожалуйста, помогите мне с этой проблемой, а также, пожалуйста, помогите мне создать простую камеру от третьего лица.

Может ли кто-нибудь помочь мне в этом, пожалуйста. Мне нужна камера от третьего лица для libgdx 3d

Спасибо.


person user1573344    schedule 26.11.2014    source источник
comment
Возможно, это поможет вам: github. com/xoppa/world/blob/master/src/com/xoppa/android/world/   -  person noone    schedule 26.11.2014
comment
Спасибо за ссылку. Но не могли бы вы сообщить мне, что пошло не так в приведенном выше коде. Потому что я думаю, что проблема связана с libgdx или, может быть, я использую его неправильно.   -  person user1573344    schedule 26.11.2014


Ответы (1)


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

Это эквивалентно

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

Через некоторое время разница между positionNew и positionOld станет существенной.

Было бы лучше нормализовать subV до фиксированной величины для стабильности.

Надеюсь это поможет.

person Tanmay Patil    schedule 26.11.2014
comment
Спасибо за ваш вклад, но поскольку объект свободно падает с гравитацией 9,8, разрыв между positionOld и positionNew также будет постепенно увеличиваться. Следовательно, он может не быть приблизительно равен positionNew. Пожалуйста, поправьте меня, если я изношен. - person user1573344; 27.11.2014