Spica*

プログラミングの話。

libGDXで3Dのモデル表示してみた

f:id:esperia:20150906175305p:plain

MagicaVoxelについての記事 を見てちょっと楽しそうだったので同じ所までやってみました。 libGDXプロジェクトを作成し、MagicaVoxel の標準で用意されているモデルをを、画面上に表示するところまでしてみました。環境はMac

プロジェクト作成

下記設定で作りました。普通ですね。

f:id:esperia:20150906175630p:plain

チュートリアルに沿ってコードを記述

Loading models using libGDX | blog.xoppa.comの通りにコードを書きます。

このドキュメント自体は、libgdx Wiki -> 3D Graphics -> Quick Start -> Basic 3D using libGDX | blog.xoppa.com -> Next: から飛べます。公式…というより公認?のページみたいです。

書くときは、importするクラスには注意して下さい。別パッケージに同じクラス名があるので、間違えるとビルドできません。

package com.esperia09.samples.libgdx.magicavoxel;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Environment;
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.CameraInputController;
import com.badlogic.gdx.utils.Array;

public class MyGdxGame extends ApplicationAdapter {
    private static final String PATH_MODEL = "chr_knight.g3db";
    public PerspectiveCamera cam;
    public CameraInputController camController;
    public ModelBatch modelBatch;
    public AssetManager assets;
    public Array<ModelInstance> instances = new Array<ModelInstance>();
    public Environment environment;
    public boolean loading;

    @Override
    public void create() {
        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));

        cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        cam.position.set(7f, 7f, 7f);
        cam.lookAt(0, 0, 0);
        cam.near = 1f;
        cam.far = 300f;
        cam.update();

        camController = new CameraInputController(cam);
        Gdx.input.setInputProcessor(camController);

        assets = new AssetManager();
        assets.load(PATH_MODEL, Model.class);

        loading = true;
    }

    private void doneLoading() {
        Gdx.app.log(getClass().getSimpleName(), "doneLoading");
        Model ship = assets.get(PATH_MODEL, Model.class);
        ModelInstance shipInstance = new ModelInstance(ship);
        shipInstance.transform.setToScaling(0.5f, 0.5f, 0.5f);
        instances.add(shipInstance);
        loading = false;
    }

    @Override
    public void render() {
        if (loading && assets.update()) {
            doneLoading();
        }
        camController.update();

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

        modelBatch.begin(cam);
        modelBatch.render(instances, environment);
        modelBatch.end();
    }

    @Override
    public void dispose() {
        modelBatch.dispose();
        instances.clear();
        assets.dispose();
    }
}

これだけで表示完了…かつ、

  • ドラッグで移動
  • ホイールで拡大率変更

できます。すごい…

Androidの場合は、二本指での拡大と、スワイプでの回転ができました。

f:id:esperia:20150907201031p:plain

chr_knight.g3dbファイルは、MagicaVoxelについての記事で説明されているように、MagicaVoxelからexportし、libgdx/fbx-convを使って*.obj -> *.g3dbへ変換するとOKです。ちょっとつまずいたこともありましたが、その内容に関しては先程の記事にコメントつけました。

感想

数字全然僕ダメで、行列すら習ってない系だったのでかなり躊躇してたんですが、 最初の敷居すごい低かったのが嬉しかったです。 いや、これで何か考えてるわけではないんですが…何かするきっかけはできたかなという感じです。