/** * 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; }
/** * 法線を求める * * @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; }