2011年6月7日火曜日

AndroidでMetasequoiaのmqoを読み込むコード その4 Meshクラス

まだ続くのかよって感じですね。 なんでこんなに小出しかって? 仕事中にこっそり書いてるからだよ!!

と、いうわけで、やっとMeshクラスです。 今後メタセコイア以外のファイル形式にも対応するかもなので、先にMeshLoaderなんつー抽象クラスを作っておいて、継承して各種ローダーを作ってもらおうかと。

とりあえず、今あるのはmqoだけ。 (学生が同じ要領でfbxローダーを作ったらしい。未確認)

ともかく、ローダークラス
import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 抽象クラス 3Dモデルを読み込むためのインタフェース
 * これを軽傷して自前のローダークラスをつくってもらいたい
 * @author ksz
 *
 */
public abstract class MeshLoader {
 public Mesh load(int id) throws Exception {
  BufferedReader in = new BufferedReader(new InputStreamReader(Global.view.getResources().openRawResource(id)));
  return load(in);
 }

 public Mesh load(String name) throws Exception {
  BufferedReader in = new BufferedReader(new InputStreamReader(Global.view.getContext().getAssets().open(name)));
  return load(in);
 }

 /**
  * コレをオーバーライドして、自前のローダー等を作ってください。
  * @param in
  * @return
  * @throws Exception
  */
 abstract public Mesh load(BufferedReader in) throws Exception;
}

このローダークラスを指定して実際にMeshクラスを作る流れ。 拡張子で自動で選ぶとか、クラス名からロードしてプラグインみたいな感じにするとか・・・。 まぁ、夢はひろがリングだけど、そこまでする必要ないかなって気もします。

import java.util.HashMap;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.content.Context;

/**
 * @author ksz
 *
 */
public class Mesh {
 private Vbo[] vbo;
 private Texture[] texs;

 /**
  * 指定されたSubsetの配列からVBOとテクスチャのセットを作成
  * そのままSubsetを使えば良いと思うかもだけど、SubsetクラスのFloarArrayListとかのインスタンスが残るのが嫌だったので。
  * @param subset
  */
 public Mesh(Subset[] subset) {
  vbo = new Vbo[subset.length];
  texs = new Texture[subset.length];
  for (int i = 0; i < subset.length; i++) {
   vbo[i] = subset[i].makeVBO();
   texs[i] = subset[i].getTex();
  }
 }

 /**
  * 全サブセット描画
  * @param x 座標x
  * @param y 座標y
  * @param z 座標z
  * @param param レンダリングパラメーター
  */
 public void render(float x, float y, float z, RenderParam param) {
  GL11 gl = Global.gl;
  gl.glMatrixMode(GL10.GL_MODELVIEW);
  gl.glPushMatrix();
  gl.glTranslatef(x, y, z);
  gl.glRotatef(param.az, 0, 0, 1);
  gl.glRotatef(param.ay, 0, 1, 0);
  gl.glRotatef(param.ax, 1, 0, 0);
  gl.glScalef(param.sx, param.sy, param.sz);

  int len = vbo.length;

  for (int i = 0; i < len; i++) {
   if (texs[i] != null) {
    Texture.setTexture(texs[i].texID);
   } else {
    Texture.setTexture(0);
   }
   vbo[i].draw();
  }
  gl.glMatrixMode(GL10.GL_MODELVIEW);
  gl.glPopMatrix();
 }

 /**
  * 管理用マップ
  */
 public static HashMap meshMap = new HashMap();

 /**
  * 文字列からリソース読み込み
  * @param resName 読み込むリソース名
  * @param loader 使用するローダー
  * @return Meshインスタンス。 すでに読み込まれている場合はそれを返します。
  * @throws Exception
  */
 public static Mesh get(String resName,MeshLoader loader)throws Exception {
  Context context = Global.view.getContext();
  int point = resName.lastIndexOf(".");
  if (point != -1) {
   resName = resName.substring(0, point);
  }
  int id = context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
  return get(id,loader);
 }

 /**
  * 文字列からリソース読み込み
  * @param resID 読み込むリソースのID
  * @param resName 読み込むリソース名
  * @param loader 使用するローダー
  * @return Meshインスタンス。 すでに読み込まれている場合はそれを返します。
  * @throws Exception
  */
 public static Mesh get(int resID,MeshLoader loader)throws Exception {
  //既に読み込まれている
  if (meshMap.containsKey(resID)) {
   return meshMap.get(resID);
  }
  //まだ読み込まれていないので新規で読み込み
  Mesh newMesh = loader.load(resID);
  meshMap.put(resID, newMesh);
  return newMesh;
 }
}

後はローダー部分だけです。
いや、そこがメインなんですけどね・・・。 需要があるのかないのか・・・。

本当はもうプロジェクト毎ザクっとどこかにアップしたいところなんですけど。 bloggerってそういうファイル置き場って無いのかな・・・。

うむん。

0 件のコメント:

コメントを投稿