3D オブジェクトのインポートおよびテクスチャマッピング ( Android OpenGL フレームワーク “Rajawali” と戯れる #07 )

Rajawali

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Android OpenGL フレームワーク "Rajawali" と戯れるシリーズ
第 07 回目は、外部の 3D オブジェクトの取り扱い方について解説します。

Rajawali が提供する 3D オブジェクトパーサ

Rajawali では、下記 3D オブジェクトパーサのクラスが用意されています。

  • Max3DSPaser
  • ObjParser
  • FBXParser
  • MD2Paser
  • MD5AnimParser
  • MD5MeshParser

中にはアニメーションをサポートするクラスもあるのですが、今回はアニメーション情報を保持しない単純な 3D オブジェクトのインポートを目的としているので、ObjParser を題材に解説を進めます。

ObjParser クラスで読み込めるファイルおよびお約束事

Rajawali の ObjParser クラスでは Wavefront OBJ File (*.obj) をパースすることが可能ですが、すべての仕様をカバーしているわけではないようで、最低でも以下のお約束事を守らなければなりません。

  • 3D オブジェクトは、三角ポリゴンで構築すること
  • テクスチャを使用する場合、UV 座標も書き出すこと
  • .obj ファイルのグループを示す "g …" が正しく解釈されないので、"# g …" とコメントアウト or 削除すること

.obj ファイルの詳細仕様については下記を参照してください。
https://en.wikipedia.org/wiki/Wavefront_.obj_file

ObjParser クラスによるパースとデータ取得

実装はとてもシンプルです。

ファイルのパース

ObjParser parser = new ObjParser(mContext.getResources(), mTextureManager, R.raw.≪任意の .obj ファイル≫);
paeser.parse();

パースしたデータの取得

BaseObject3D obj = paeser.getParsedObject();

シンプルですね。

取得したデータのテクスチャマッピング

こちらも非常にシンプルです。

Bitmap texture = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.≪任意のテクスチャ画像≫);
obj.setMaterial( ≪任意のマテリアルオブジェクト≫ );
obj.addTexture( mTextureManager.addTexture(texture) );

実装例

ソース素材

今更で出尽くした感があるかもしれませんが、三次元CG@七葉にて保管されているズサ氏制作のはちゅねミク 3D オブジェクト+テクスチャ データを拝借してサンプルを作成してみました。( .mpo -> .obj 変換しています )

ちなみに、LightWave 3D で開いた状態は以下のとおり。

ソースコード

Lesson05Renderer.java

package jp.classmethod.sample.renderer;
import jp.classmethod.sample.R;
import rajawali.BaseObject3D;
import rajawali.lights.PointLight;
import rajawali.materials.DiffuseMaterial;
import rajawali.parser.ObjParser;
import rajawali.renderer.RajawaliRenderer;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
 * RajawaliRenderer のサブクラス
 */
public class Lesson05Renderer extends RajawaliRenderer {
    /** パースされた 3D オブジェクトデータ */
    private BaseObject3D mObj;
    /** コンストラクタ */
    public Lesson05Renderer(Context context) {
        super(context);
        setFrameRate(60);
        setBackgroundColor(0xffffff);
    }
    @Override
    /** シーン初期化 */
    protected void initScene() {
        Resources r = mContext.getResources();

        PointLight light = new PointLight();
        light.setPower(1f);
        light.setColor(0xffffff);
        light.setPosition(0f, 0f, -2f);

        Bitmap texture = BitmapFactory.decodeResource(r, R.drawable.miku);

        ObjParser parser = new ObjParser(r, mTextureManager, R.raw.miku);
        parser.parse();

        mObj = parser.getParsedObject();
        mObj.setMaterial(new DiffuseMaterial());
        mObj.addTexture( mTextureManager.addTexture(texture) );
        mObj.setRotation(25, 190, 0);
        mObj.setScale(1f);
        mObj.addLight(light);
        
        addChild(mObj);
    }
}

出力結果

DiffuseMaterial で散光させるとホラーホラーしいですね。。。

次回

アニメーション情報付き 3D オブジェクトのインポートについて解説します。