/*
* PROJECT: NyARMqoView
* --------------------------------------------------------------------------------
* これはMetaseqファイル(.MQO)ファイルをjavaに読み込み&描画するクラスです。
* Copyright (C)2008 kei
*
*
* オリジナルファイルの著作権はkeiさんにあります。
* オリジナルのファイルは以下のURLから入手できます。
* http://www.sainet.or.jp/~kkoni/OpenGL/reader.html
*
* このファイルは、http://www.sainet.or.jp/~kkoni/OpenGL/20080408.zipにあるファイルを
* ベースに、NyARMqoView用にカスタマイズしたものです。
*
* For further information please contact.
* A虎@nyatla.jp
* http://nyatla.jp/nyatoolkit/
* <airmail(at)ebony.plala.or.jp>
*
*/
package jp.nyatla.kGLModel;
import java.io.*;
import java.util.*;
import java.nio.*;
import java.lang.reflect.*;
import java.io.InputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.microedition.khronos.opengles.*;
import android.content.res.*;
import android.util.Log;
/**
* MQOファイルの読み込みと描画<br>
* (描画は親クラスで実装済み)<br>
* <br>
* インスタンス化も親クラスのKGLModelData::createGLModelを使用する<br>
* メタセコファイルフォーマットは<br>
* <a href="http://www.metaseq.net/">http://www.metaseq.net/</a><br>
* 参照。
*
* @author kei
*
*/
public class KGLMetaseq extends KGLModelData
{
/**
* 「"」で囲まれた文字を取り出す
*
* @param st
* 操作対象文字列
* @return 前後の「"」を抜いた文字列
*/
protected String getDoubleQuoatString(String st) {
String ret;
ret = st.trim();
if (ret.charAt(0) != '\"') {
return ret;
}
int p;
p = ret.indexOf("\"", 1);
return ret.substring(1, p);
}
/**
* 法線を求める
*
* @param V
* 頂点配列
* @param A
* 頂点の位置
* @param B
* 頂点の位置
* @param C
* 頂点の位置
* @return 法線ベクトル
*/
protected KGLPoint calcNormal(KGLPoint[] V, int A, int B, int C) {
KGLPoint ret = null;
KGLPoint BA = null;
KGLPoint BC = null;
// ベクトルB->A
BA = KGLPoint.vector(V[B], V[A]);
// ベクトルB->C
BC = KGLPoint.vector(V[B], V[C]);
// 法線の計算
ret = KGLPoint.createXYZ(BA.Y() * BC.Z() - BA.Z() * BC.Y(), BA.Z()
* BC.X() - BA.X() * BC.Z(), BA.X() * BC.Y() - BA.Y() * BC.X());
ret.normalize();// 正規化
return ret;
}
/**
* 頂点法線を求める
*
* @param mqoObj
* 読み込んだMQOデータ
* @return 頂点法線
*/
protected KGLPoint[] vNormal(objects mqoObj) {
KGLPoint[] ret = null;
KGLPoint sn = null;
// 頂点に接している面の法線を頂点法線に足し込んでいく
ret = new KGLPoint[mqoObj.vertex.length];
for (int f = 0; f < mqoObj.face.length; f++) {
sn = calcNormal(mqoObj.vertex, mqoObj.face[f].V[0],
mqoObj.face[f].V[1], mqoObj.face[f].V[2]);
if (sn == null)
continue;
for (int i = 0; i < 3; i++) {
if (ret[mqoObj.face[f].V[i]] == null) {
ret[mqoObj.face[f].V[i]] = KGLPoint.createXYZ(0, 0, 0);
}
ret[mqoObj.face[f].V[i]].add(sn);
}
}
// 正規化(長さを求めて、ソレで割って0~1の値にする!)
for (int v = 0; v < ret.length; v++)
{
if (ret[v] == null)
continue;
ret[v].normalize();
}
return ret;
}
/**
* オブジェクトのフィールドにデータを設定する<br>
* Integer、Float、Float[]、Stringにしか対応していない
*
* @param obj
* 設定対象オブジェクト
* @param fl
* 設定対象フィールド
* @param ty
* 設定対象フィールドの型
* @param data
* 設定データ
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
protected void dataSetter(Object obj, Field fl, Class ty, String data)
throws IllegalArgumentException, IllegalAccessException {
// Integer型のデータを設定
if (ty.toString().equals("class java.lang.Integer")) {
fl.set(obj, Integer.parseInt(data));
}
// Float型のデータを設定
if (ty.toString().equals("class java.lang.Float")) {
fl.set(obj, Float.parseFloat(data));
}
// String型のデータを設定(""の内側)
if (ty.toString().equals("class java.lang.String")) {
fl.set(obj, getDoubleQuoatString(data));
}
// Float[]型のデータを設定
if (ty.toString().equals("class [Ljava.lang.Float;")) {
String[] s;
s = data.split(" ");
Float[] f = new Float[s.length];
for (int i = 0; i < s.length; i++) {
f[i] = Float.parseFloat(s[i]);
}
fl.set(obj, f);
}
}
/**
* MQOファイルのMaterial情報読み込み&データ保持クラス
*
*/
private class material {
/**
* マテリアル名
*/
String name = null;
class material_data {
Integer shader = null;
Float[] col = null;
Float dif = null;
Float amb = null;
Float emi = null;
Float spc = null;
Float pow = null;
String tex = null;
String aplane = null;
}
material_data data = null;
String[] fls_names = null;
Field[] fls = null;
Class[] tys = null;
public material() {
// データフィールドをとりだす
data = new material_data();
fls = data.getClass().getDeclaredFields();
int len;
len = fls.length;
fls_names = new String[len];
tys = new Class[len];
for (int i = 0; i < len; i++) {
// フィールド名とフィールド型を取り出す
fls_names[i] = fls[i].getName();
tys[i] = fls[i].getType();
}
}
public void set(String line) throws Exception {
name = getDoubleQuoatString(line);
int p;
int pe;
for (int fn = 0; fn < fls_names.length; fn++) {
p = line.indexOf(fls_names[fn] + "(");
if (p == -1)
continue;
pe = line.indexOf(")", p);
dataSetter(data, fls[fn], tys[fn], line.substring(p
+ fls_names[fn].length() + 1, pe));
}
//data.texとdata.alphaにファイル識別子を書き出している?
//これはファイルプロバイダの機能にまかせる。
// File wf;
// if (data.tex != null){
// wf = new File(data.tex);
// if (!wf.isAbsolute()) {// 相対パス
// if (targetMQO.getParent() != null) {
// data.tex = targetMQO.getParent() + File.separator
// + data.tex;
// }
// }
// }
// if (data.aplane != null) {
// wf = new File(data.aplane);
// if (!wf.isAbsolute()) {// 相対パス
// if (targetMQO.getParent() != null) {
// data.aplane = targetMQO.getParent() + File.separator
// + data.aplane;
// }
// }
// }
}
public String toString() {
String ret;
ret = name;
if (data.shader != null)
ret += " shader(" + data.shader + ")";
if (data.col != null) {
ret += " col(";
for (int i = 0; i < data.col.length; i++) {
if (i != 0)
ret += ", ";
ret += data.col[i];
}
ret += ")";
}
if (data.dif != null)
ret += " dif(" + data.dif + ")";
if (data.amb != null)
ret += " amb(" + data.amb + ")";
if (data.emi != null)
ret += " emi(" + data.emi + ")";
if (data.spc != null)
ret += " spc(" + data.spc + ")";
if (data.pow != null)
ret += " pow(" + data.pow + ")";
if (data.tex != null)
ret += " tex(" + data.tex + ")";
if (data.aplane != null)
ret += " aplane(" + data.aplane + ")";
return ret;
}
}
/**
* MQOファイルのObject情報読み込みクラス
*
*/
private class objects {
String name = null;
class objects_data {
Integer depth = null;
Integer folding = null;
Float[] scale = null;
Float[] rotation = null;
Float[] translation = null;
Integer patch = null;
Integer segment = null;
Integer visible = null;
Integer locking = null;
Integer shading = null;
Float facet = null;
Float[] color = null;
Integer mirror = null;
Integer color_type = null;
Integer mirror_axis = null;
Float mirror_dis = null;
}
objects_data data = null;;
String[] fls_names = null;
Field[] fls = null;
Class[] tys = null;
KGLPoint[] vertex = null;
class Face {
Integer[] V = null;
Integer M = null;
Float[] UV = null;
Float[] COL = null;
}
Face[] face;
public objects() {
// データフィールドをとりだす
data = new objects_data();
fls = data.getClass().getDeclaredFields();
int len;
len = fls.length;
fls_names = new String[len];
tys = new Class[len];
// フィールド名とフィールド型を取り出す
for (int i = 0; i < len; i++) {
fls_names[i] = fls[i].getName();
tys[i] = fls[i].getType();
}
}
/**
* vertexチャンクの読み込み
*
* @param num
* チャンクにあるデータ数
* @param br
* 読み込みストリーム
* @param scale
* モデルの倍率
* @return 頂点配列
* @throws Exception
*/
private KGLPoint[] readVertex(int num, multiInput br, float scale) throws Exception
{
KGLPoint[] ret = null;
String line = null;
String[] s;
int cnt;
ret = new KGLPoint[num];
cnt = 0;
try {
while ((line = br.readLine()) != null) {
if (line.length() <= 0)
continue;
line = line.trim();
if (line.equals("}"))
break;
s = line.split(" ", 3);
ret[cnt] = KGLPoint.createXYZ(Float.parseFloat(s[0])
* scale, Float.parseFloat(s[1]) * scale, Float
.parseFloat(s[2])
* scale);
cnt++;
}
} catch (Exception e) {
Log.e("KGLMetaseq", "MQOファイル フォーマットエラー(Object>vertex)[" + line+ "]");
throw e;
}
if (cnt != num)
return null;
return ret;
}
/**
* BVertexチャンクの読み込み
*
* @param br
* 読み込みストリーム
* @return 頂点配列
* @param scale
* モデルの倍率
* @throws Exception
*/
private KGLPoint[] readBvertex(multiInput br, float scale)
throws Exception {
KGLPoint[] ret = null;
String line = null;
String[] s;
int p;
int pe;
int datasize = 0;
try {
while ((line = br.readLine().trim()) != null) {
if (line.length() <= 0)
continue;
s = line.split(" ");
if (s[0].equals("Vector")) {
if (s.length != 3) {
line = null;
break;
}
p = s[2].indexOf("[");
pe = s[2].indexOf("]");
datasize = Integer.parseInt(s[2].substring(p + 1, pe));
break;
}
}
} catch (Exception e) {
Log.e("KGLMetaseq", "MQOファイル フォーマットエラー(Object>Bvertex)[" + line+ "]");
throw new KGLException(e);
}
if (line == null){
return null;
}
if (datasize == 0)
return null;
byte[] bbuf = new byte[datasize];
if (datasize != br.read(bbuf))
return null;
ByteBuffer bb;
bb = ByteBuffer.wrap(bbuf);
bb.order(ByteOrder.LITTLE_ENDIAN);// MQOファイルのエンディアンはIntel形式
FloatBuffer fb = bb.asFloatBuffer();
ret = new KGLPoint[fb.limit() / 3];
fb.position(0);
float[] wf = new float[3];
for (int i = 0; i < ret.length; i++) {
fb.get(wf);
ret[i] = KGLPoint.create(wf).scale(scale);
}
while ((line = br.readLine().trim()) != null) {
if (line.equals("}"))
break;
}
return ret;
}
/**
* faceチャンクの読み込み
*
* @param br
* 読み込みストリーム
* @return 面配列
* @throws Exception
*/
private Face[] readFace(multiInput br) throws Exception
{
ArrayList<Face> qf;
String line = null;
String[] s;
Integer Mn;
Face[] wface = null;
int p;
int pe;
qf = new ArrayList<Face>();
try {
while ((line = br.readLine()) != null) {
if (line.length() <= 0)
continue;
line = line.trim();
if (line.equals("}"))
break;
wface = null;
Mn = null;
p = line.indexOf("M(");
if (p != -1) {
pe = line.indexOf(")", p);
Mn = Integer.parseInt(line.substring(p + 2, pe));
}
p = line.indexOf("V(");
if (p == -1)
continue;
pe = line.indexOf(")", p);
s = line.substring(p + 2, pe).split(" ");
if (s.length == 3) {
wface = new Face[1];
wface[0] = new Face();
wface[0].V = new Integer[3];
wface[0].V[0] = Integer.parseInt(s[0]);
wface[0].V[1] = Integer.parseInt(s[1]);
wface[0].V[2] = Integer.parseInt(s[2]);
wface[0].M = Mn;
p = line.indexOf("UV(");
if (p != -1) {
pe = line.indexOf(")", p);
s = line.substring(p + 3, pe).split(" ");
if (s.length != 2 * 3)
throw new Exception("UVの数が不正");
wface[0].UV = new Float[2 * 3];
for (int i = 0; i < s.length; i++) {
wface[0].UV[i] = Float.parseFloat(s[i]);
}
}
p = line.indexOf("COL(");
if (p != -1) {
pe = line.indexOf(")", p);
s = line.substring(p + 4, pe).split(" ");
if (s.length != 3)
throw new Exception("COLの数が不正");
wface[0].COL = new Float[4 * 3];
long wl;
float wf;
for (int i = 0; i < s.length; i++) {
wl = Long.parseLong(s[i]);
wf = (wl >>> 0) & 0x000000ff;
wface[0].COL[i * 4 + 0] = wf / 255f;
wf = (wl >>> 8) & 0x000000ff;
wface[0].COL[i * 4 + 1] = wf / 255f;
wf = (wl >>> 16) & 0x000000ff;
wface[0].COL[i * 4 + 2] = wf / 255f;
wf = (wl >>> 24) & 0x000000ff;
wface[0].COL[i * 4 + 3] = wf / 255f;
}
}
}
// 頂点配列はすべて三角にするので、四角は三角x2に分割
// 0 3 0 0 3
// □ → △ ▽
// 1 2 1 2 2
if (s.length == 4) {
wface = new Face[2];
wface[0] = new Face();
wface[1] = new Face();
wface[0].V = new Integer[3];
wface[0].V[0] = Integer.parseInt(s[0]);
wface[0].V[1] = Integer.parseInt(s[1]);
wface[0].V[2] = Integer.parseInt(s[2]);
wface[0].M = Mn;
wface[1].V = new Integer[3];
wface[1].V[0] = Integer.parseInt(s[0]);
wface[1].V[1] = Integer.parseInt(s[2]);
wface[1].V[2] = Integer.parseInt(s[3]);
wface[1].M = Mn;
p = line.indexOf("UV(");
if (p != -1) {
int uv_p;
pe = line.indexOf(")", p);
s = line.substring(p + 3, pe).split(" ");
if (s.length != 2 * 4)
throw new Exception("UVの数が不正");
wface[0].UV = new Float[2 * 3];
wface[1].UV = new Float[2 * 3];
for (int i = 0; i < 2; i++) {
uv_p = 0;
for (int j = 0; j < 4; j++) {
if (i == 0 && j == 3)
continue;
if (i == 1 && j == 1)
continue;
wface[i].UV[uv_p++] = Float
.parseFloat(s[j * 2 + 0]);
wface[i].UV[uv_p++] = Float
.parseFloat(s[j * 2 + 1]);
}
}
}
p = line.indexOf("COL(");
if (p != -1) {
pe = line.indexOf(")", p);
s = line.substring(p + 4, pe).split(" ");
if (s.length != 4)
throw new Exception("COLの数が不正");
wface[0].COL = new Float[4 * 3];
wface[1].COL = new Float[4 * 3];
long wl;
float wf;
int col_p;
for (int i = 0; i < 2; i++) {
col_p = 0;
for (int j = 0; j < s.length; j++) {
if (i == 0 && j == 3)
continue;
if (i == 1 && j == 1)
continue;
wl = Long.parseLong(s[j]);
wf = (wl >>> 0) & 0x000000ff;
wface[i].COL[col_p * 4 + 0] = wf / 255f;
wf = (wl >>> 8) & 0x000000ff;
wface[i].COL[col_p * 4 + 1] = wf / 255f;
wf = (wl >>> 16) & 0x000000ff;
wface[i].COL[col_p * 4 + 2] = wf / 255f;
wf = (wl >>> 24) & 0x000000ff;
wface[i].COL[col_p * 4 + 3] = wf / 255f;
col_p++;
}
}
}
}
if (wface != null) {
for (int i = 0; i < wface.length; i++) {
qf.add(wface[i]);
}
}
}
} catch (Exception e) {
Log.e("KGLMetaseq", "MQOファイル フォーマットエラー(Object>face)"+ e.getMessage() + "[" + line + "]");
throw e;
}
if (qf.size() == 0)
return null;
return qf.toArray(new Face[0]);
}
private void set(String in_name, multiInput br, float scale)throws Exception
{
String line[];
name = getDoubleQuoatString(in_name);
while ((line = Chank(br, true)) != null) {
if (line[0].equals("}"))
break;
if (line[line.length - 1].equals("{")) { // 内部チャンク
if (line[0].equals("vertex")) {
vertex = readVertex(Integer.parseInt(line[1]), br,
scale);
continue;
}
if (line[0].equals("BVertex")) {
vertex = readBvertex(br, scale);
continue;
}
if (line[0].equals("face")) {
face = readFace(br);
continue;
}
String single = null;
while ((single = br.readLine()) != null) {
if (single.trim().equals("}"))
break;
}
continue;
}
for (int i = 0; i < fls_names.length; i++) {
if (fls_names[i].equals(line[0])) {
dataSetter(data, fls[i], tys[i], line[1]);
}
}
}
}
public String toString() {
String ret;
ret = name;
if (data.visible != null)
ret += " visible(" + data.visible + ")";
if (data.color != null) {
ret += " color(";
for (int i = 0; i < data.color.length; i++) {
if (i != 0)
ret += ", ";
ret += data.color[i];
}
ret += ")";
}
if (data.facet != null)
ret += " facet(" + data.facet + ")";
return ret;
}
}
/**
* 描画用マテリアル情報をMQOデータから作成
*
* @param mqomat
* MQOファイルから読み込んだマテリアル情報
* @param i_mqomat
* MQOファイルのマテリアル番号
* @param mqoObjs
* MQOファイルのオブジェクト情報
* @param vn
* 頂点法線配列
* @return 描画用マテリアル情報
*/
private GLMaterial makeMats(GL10 gl, material mqomat, int i_mqomat, objects mqoObjs,KGLPoint[] vn) {
GLMaterial ret = new GLMaterial();
ArrayList<KGLPoint> apv = new ArrayList<KGLPoint>();
ArrayList<KGLPoint> apn = new ArrayList<KGLPoint>();
ArrayList<KGLPoint> apuv = new ArrayList<KGLPoint>();
ArrayList<KGLPoint> apc = new ArrayList<KGLPoint>();
KGLPoint wpoint = null;
boolean uvValid = false;
boolean colValid = false;
KGLPoint fn;
float s;
for (int f = 0; f < mqoObjs.face.length; f++) {
if(mqoObjs.face[f].M==null){
continue;
}
if (mqoObjs.face[f].M != i_mqomat)
continue;
fn = calcNormal(mqoObjs.vertex, mqoObjs.face[f].V[0],
mqoObjs.face[f].V[1], mqoObjs.face[f].V[2]);
for (int v = 0; v < 3; v++) {
apv.add(mqoObjs.vertex[mqoObjs.face[f].V[v]]);
// apv.add(new KGLPoint(mqoObjs.vertex[mqoObjs.face[f].V[v]])) ;
s = (float) Math.acos(fn.X() * vn[mqoObjs.face[f].V[v]].X()
+ fn.Y() * vn[mqoObjs.face[f].V[v]].Y() + fn.Z()
* vn[mqoObjs.face[f].V[v]].Z());
if (mqoObjs.data.facet < s) {
apn.add(fn);
} else {
apn.add(vn[mqoObjs.face[f].V[v]]);
}
wpoint = new KGLPoint(2);
if (mqoObjs.face[f].UV == null) {
wpoint.set_UV(0, 0);
} else {
wpoint.set_UV(mqoObjs.face[f].UV[v * 2 + 0],
mqoObjs.face[f].UV[v * 2 + 1]);
uvValid = true;
}
apuv.add(wpoint);
wpoint = new KGLPoint(4);
if (mqoObjs.face[f].COL == null) {
if (mqomat.data.col == null) {
wpoint.set_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
} else {
wpoint.set_COLOR(mqomat.data.col[0],
mqomat.data.col[1], mqomat.data.col[2],
mqomat.data.col[3]);
}
} else {
wpoint.set_COLOR(mqoObjs.face[f].COL[v * 4 + 0],
mqoObjs.face[f].COL[v * 4 + 1],
mqoObjs.face[f].COL[v * 4 + 2],
mqoObjs.face[f].COL[v * 4 + 3]);
colValid = true;
}
apc.add(wpoint);
}
}
ret.texID = texPool.getGLTexture(gl, mqomat.data.tex, mqomat.data.aplane,
false);
// @@@ reload 用
if (ret.texID != 0) {
ret.texName = mqomat.data.tex;
ret.alphaTexName = mqomat.data.aplane;
} else {
ret.texName = null;
ret.alphaTexName = null;
}
if (apv.size() == 0)
return null;
uvValid &= (ret.texID != 0);
ret.name = mqomat.name;
// uvValid = false ;
KGLPoint[] wfv = null;
KGLPoint[] wfn = null;
KGLPoint[] wft = null;
KGLPoint[] wfc = null;
wfv = apv.toArray(new KGLPoint[0]);
wfn = apn.toArray(new KGLPoint[0]);
wft = apuv.toArray(new KGLPoint[0]);
wfc = apc.toArray(new KGLPoint[0]);
ret.vertex_num = wfv.length;
// @@@ interleaveFormat は無いので分ける
ret.uvValid = uvValid;
ret.colValid = colValid;
ret.vertexBuffer = ByteBuffer.allocateDirect(ret.vertex_num * 3 * 4);
ret.vertexBuffer.order(ByteOrder.nativeOrder());
ret.vertexBuffer.position(0);
ret.normalBuffer = ByteBuffer.allocateDirect(ret.vertex_num * 3 * 4);
ret.normalBuffer.order(ByteOrder.nativeOrder());
ret.normalBuffer.position(0);
if (uvValid) {
ret.uvBuffer = ByteBuffer.allocateDirect(ret.vertex_num * 2 * 4);
ret.uvBuffer.order(ByteOrder.nativeOrder());
ret.uvBuffer.position(0);
}
if (colValid) {
ret.colBuffer = ByteBuffer.allocateDirect(ret.vertex_num * 4 * 4);
ret.colBuffer.order(ByteOrder.nativeOrder());
ret.colBuffer.position(0);
}
// Log.i("KGLMetaseq", "vertex_num: "+ ret.vertex_num);
for (int v = 0; v < ret.vertex_num; v++) {
ret.vertexBuffer.putFloat(wfv[v].X());
ret.vertexBuffer.putFloat(wfv[v].Y());
ret.vertexBuffer.putFloat(wfv[v].Z());
ret.normalBuffer.putFloat(wfn[v].X());
ret.normalBuffer.putFloat(wfn[v].Y());
ret.normalBuffer.putFloat(wfn[v].Z());
if (uvValid) {
ret.uvBuffer.putFloat(wft[v].U());
ret.uvBuffer.putFloat(wft[v].V());
}
if (colValid) {
ret.colBuffer.putFloat(wfc[v].R());
ret.colBuffer.putFloat(wfc[v].G());
ret.colBuffer.putFloat(wfc[v].B());
ret.colBuffer.putFloat(wfc[v].A());
}
}
if (mqomat.data.col != null) {
ret.color = new float[mqomat.data.col.length];
for (int c = 0; c < mqomat.data.col.length; c++) {
ret.color[c] = mqomat.data.col[c];
}
if (mqomat.data.dif != null) {
ret.dif = new float[mqomat.data.col.length];
for (int c = 0; c < mqomat.data.col.length; c++) {
ret.dif[c] = mqomat.data.dif * mqomat.data.col[c];
}
// KEICHECK difでアルファ値を1未満にすると透明度が変化する?
ret.dif[3] = mqomat.data.col[3];
}
if (mqomat.data.amb != null) {
ret.amb = new float[mqomat.data.col.length];
for (int c = 0; c < mqomat.data.col.length; c++) {
ret.amb[c] = mqomat.data.amb * mqomat.data.col[c];
}
}
if (mqomat.data.emi != null) {
ret.emi = new float[mqomat.data.col.length];
for (int c = 0; c < mqomat.data.col.length; c++) {
ret.emi[c] = mqomat.data.emi * mqomat.data.col[c];
}
}
if (mqomat.data.spc != null) {
ret.spc = new float[mqomat.data.col.length];
for (int c = 0; c < mqomat.data.col.length; c++) {
ret.spc[c] = mqomat.data.spc * mqomat.data.col[c];
}
}
}
if (mqomat.data.pow != null) {
ret.power = new float[1];
ret.power[0] = mqomat.data.pow;
}
ret.shadeMode_IsSmooth = true;// defaultはtrue
if (mqoObjs.data.shading == 0)
ret.shadeMode_IsSmooth = false;
return ret;
}
/**
* 描画用オブジェクト情報を作成する
*
* @param mqoMats
* MQOファイルから読み込んだマテリアル情報配列
* @param mqoObjs
* MQOファイルのオブジェクト情報
* @return 描画用オブジェクト情報
*/
private GLObject makeObjs(GL10 gl, material mqoMats[], objects mqoObjs)
{
GLObject ret = null;
ArrayList<GLMaterial> mats = new ArrayList<GLMaterial>();
GLMaterial mr;
KGLPoint[] vn = null;
vn = vNormal(mqoObjs);
for (int m = 0; m < mqoMats.length; m++) {
mr = makeMats(gl, mqoMats[m], m, mqoObjs, vn);
if (mr != null) {
mats.add(mr);
}
}
if (mats.size() == 0)
return null;
ret = new GLObject();
ret.name = mqoObjs.name;
ret.mat = mats.toArray(new GLMaterial[0]);
ret.isVisible = (mqoObjs.data.visible != 0);
return ret;
}
// 後で復帰させる
// protected KGLMetaseq(GL in_gl, KGLTextures in_texPool, File mqoFile,float scale, boolean isUseVBO)
// {
//
// }
/**
* コンストラクタ ここでファイルからデータを読み込んでいる
*
* @param in_gl
* OpenGLコマンド群をカプセル化したクラス
* @param in_texPool
* テクスチャ管理クラス
* @param i_provider
* ファイルデータプロバイダ
* @param mqoFile
* 読み込みファイル
* @param scale
* モデルの倍率
* @param isUseVBO
* 頂点配列バッファを使用するかどうか
*/
protected KGLMetaseq(GL10 gl, KGLTextures in_texPool, AssetManager am, String msqname, float scale)
{
super(in_texPool, am, scale);
// targetMQO = in_moq;
material mats[] = null;
InputStream fis = null;
// InputStreamReader isr = null ;
// BufferedReader br = null;
multiInput br = null;
String chankName[] = null;
GLObject glo = null;
ArrayList<GLObject> globjs = new ArrayList<GLObject>();
try {
fis = am.open(msqname);
// isr = new InputStreamReader(fis) ;
// br = new BufferedReader(isr);
br = new multiInput(fis);
while ((chankName = Chank(br, false)) != null) {
/*
* for( int i = 0 ; i < chankName.length ; i++ ) {
* System.out.print(chankName[i]+" ") ; } System.out.println() ;
*/
if (chankName[0].trim().toUpperCase().equals("MATERIAL")) {
try {
mats = new material[Integer.parseInt(chankName[1])];
for (int m = 0; m < mats.length; m++) {
mats[m] = new material();
mats[m].set(br.readLine().trim());
// Log.i("KGLMetaseq", "Material(" + m+") :" + mats[m].toString());
}
} catch (Exception mat_e) {
Log.e("KGLMetaseq", "MQOファイル Materialチャンク読み込み例外発生 "+ mat_e.getMessage());
throw new KGLException(mat_e);
}
}
try {
if (chankName[0].trim().toUpperCase().equals("OBJECT")) {
objects object = new objects();
object.set(chankName[1], br, scale);
// System.out.println(object.toString()) ;
if (object.face == null){
continue;// 面情報のないオブジェクトは飛ばす
}
glo = makeObjs(gl, mats, object);
if (glo != null){
globjs.add(glo);
}
}
}catch (Exception obj_e) {
Log.e("KGLMetaseq", "MQOファイル Object[" + chankName[1]+ "]チャンク読み込み例外発生 " + obj_e.toString());
throw new KGLException(obj_e);
}
}
br.close();// 読み込み終了
br = null;
glObj = globjs.toArray(new GLObject[0]);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* チャンクサーチ
*
* @param br
* 読み込みストリーム
* @param isInner
* true:チャンク内部のチャンクサーチ false:一番外のチャンクサーチ
* @return チャンク文字列
* @throws IOException
*/
private String[] Chank(multiInput br, boolean isInner) throws IOException {
String ret[] = null;
String ws[] = null;
String read = null;
char c;
while ((read = br.readLine()) != null) {
if (read.length() <= 0)
continue;
c = read.charAt(read.length() - 1);
if (c == '{') {
ws = read.split(" ");
if (ws.length == 2) {
ret = new String[2];
ret[0] = ws[0].trim();
ret[1] = "{";
break;
}
ret = new String[3];
ret[0] = ws[0].trim();
ret[1] = read.substring(ws[0].length(), read.length() - 2)
.trim();
ret[2] = "{";
break;
}
if (isInner) {
ws = read.split(" ", 2);
ret = new String[ws.length];
for (int i = 0; i < ws.length; i++)
ret[i] = ws[i].trim();
break;
}
}
return ret;
}
}