(libGDX | Help) Rotate & zoom camera in/out and around a sphere (planet viewer)

Hello everyone!

As the title states I’m trying to make a simple 3d planet viewer. In this you can zoom in/out and rotate around the sphere object. The sphere will be mapped with a texture that represents a world.

So far I was able to add the sphere and rotate, kinda, but my approach is not working. This is my first time working with 3d and I thought a 3d plant viewer would be a good and small introduction into 3d, but it’s harder than I thought. xD

Here is my code:

WorldViewerMain.java

package world.viewer;

import com.badlogic.gdx.Game;
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;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
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.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.math.Vector3;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class WorldViewerMain extends Game {

    private PerspectiveCamera camera;
    private Model model;
    private ModelInstance instance;
    private ModelBatch modelBatch;
    private Environment environment;
    private BitmapFont font;
    private Batch batch;

    private float mainWorldSize = 10f;
    private float cameraX, cameraY, cameraZ;

    @Override
    public void create() {
        Gdx.input.setInputProcessor(new InputKeyboard(this));

        font = new BitmapFont();
        batch = new SpriteBatch();

        cameraX = cameraY = cameraZ = 10f;

        camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        camera.position.set(cameraX, cameraY, cameraZ);
        camera.lookAt(0, 0, 0);
        camera.near = 1f;
        camera.far = 300f;
        camera.update();

        ModelBuilder modelBuilder = new ModelBuilder();
        Material material = new Material(ColorAttribute.createDiffuse(Color.RED));
        final long attributes = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates;
        model = modelBuilder.createSphere(mainWorldSize, mainWorldSize, mainWorldSize, 24, 24, material, attributes);
        instance = new ModelInstance(model);

        modelBatch = new ModelBatch();
        environment = new Environment();
        environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
        environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
    }

    @Override
    public void dispose() {
        if (screen != null) screen.hide();
        model.dispose();
        font.dispose();
        modelBatch.dispose();
    }

    @Override
    public void pause() {
        if (screen != null) screen.pause();
    }

    @Override
    public void resume() {
        if (screen != null) screen.resume();
    }

    @Override
    public void render() {
        if (screen != null) screen.render(Gdx.graphics.getDeltaTime());

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

        camera.position.set(cameraX, cameraY, cameraZ);

        camera.rotateAround(Vector3.Zero, new Vector3(1, 1, 1), 1f);
        camera.update();

        modelBatch.begin(camera);
        modelBatch.render(instance, environment);
        modelBatch.end();

        batch.begin();
//        font.draw(batch, "MOUSE X: " + mouseX + ", Y: " + mouseY, 10, 60);
        font.draw(batch, "ZOOM: " + camera.position.x + " ," + camera.position.y + " ," + camera.position.z, 10, 40);
        font.draw(batch, "FPS: " + Gdx.graphics.getFramesPerSecond(), 10, 20);
        batch.end();
    }

    @Override
    public void resize(int width, int height) {
        if (screen != null) screen.resize(width, height);
    }

}

InputKeyboard.java

package world.viewer;

import com.badlogic.gdx.InputProcessor;

public class InputKeyboard implements InputProcessor {

    private WorldViewerMain worldViewerMain;

    public InputKeyboard(WorldViewerMain worldViewerMain) {
        this.worldViewerMain = worldViewerMain;
    }

    @Override
    public boolean keyDown(int keycode) {
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {

        float x = worldViewerMain.getCamera().position.x;
        float y = worldViewerMain.getCamera().position.y;
        float z = worldViewerMain.getCamera().position.z;

        if (amount == -1) {
            worldViewerMain.setCameraX(x - 1);
            worldViewerMain.setCameraY(y - 1);
            worldViewerMain.setCameraZ(z - 1);
        } else if (amount == 1) {
            worldViewerMain.setCameraX(x + 1);
            worldViewerMain.setCameraY(y + 1);
            worldViewerMain.setCameraZ(z + 1);
        }

        return false;
    }
}

Thank you for any and all help! Please forgive me as I have tried to do some research.

Before I posted I purchased and read some of:

I have also gone to:


http://www.gamefromscratch.com/post/2014/01/10/LibGDX-minimal-3D-app.aspx

If I have missed something I apologize!

Search for “arcball camera”.