/** * 法線を求める * * @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; }
/** * 描画用マテリアル情報を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; }