protected override bool DoGenerateMeshes() { meshes = new List <TSOMesh>(); foreach (MqoObject i in mqo.Objects) { if (i.name.ToLower() == "bone") { continue; } Console.WriteLine("object:" + i.name); // 法線生成 Point3[] nrm = new Point3[i.vertices.Count]; foreach (MqoFace j in i.faces) { Point3 v1 = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]); Point3 v2 = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]); Point3 n = Point3.Normalize(Point3.Cross(v1, v2)); nrm[j.a] -= n; nrm[j.b] -= n; nrm[j.c] -= n; } for (int j = 0; j < nrm.Length; ++j) { nrm[j] = Point3.Normalize(nrm[j]); } // ボーン情報作成 uint idx = 0x00000000; Point4 wgt = new Point4(1, 0, 0, 0); int[] bones = new int[1]; string bone = ObjectBoneNames[i.name]; bones[0] = nodes[bone].ID; // マテリアル別に処理を実行 List <ushort> indices = new List <ushort>(); VertexHeap <Vertex> vh = new VertexHeap <Vertex>(); List <TSOSubMesh> subs = new List <TSOSubMesh>(); Console.WriteLine(" vertices bone_indices"); Console.WriteLine(" -------- ------------"); for (int j = 0, n = materials.Count; j < n; ++j) { int mtl = j; indices.Clear(); foreach (MqoFace f in i.faces) { if (f.mtl != mtl) { continue; } Vertex va = new Vertex(i.vertices[f.a], wgt, idx, nrm[f.a], new Point2(f.ta.x, 1 - f.ta.y)); Vertex vb = new Vertex(i.vertices[f.b], wgt, idx, nrm[f.b], new Point2(f.tb.x, 1 - f.tb.y)); Vertex vc = new Vertex(i.vertices[f.c], wgt, idx, nrm[f.c], new Point2(f.tc.x, 1 - f.tc.y)); indices.Add(vh.Add(va)); indices.Add(vh.Add(vc)); indices.Add(vh.Add(vb)); } if (indices.Count == 0) { continue; } // フェイス最適化 ushort[] nidx = NvTriStrip.Optimize(indices.ToArray()); // サブメッシュ生成 Vertex[] verts = vh.verts.ToArray(); TSOSubMesh sub = new TSOSubMesh(); sub.spec = mtl; sub.numbones = bones.Length; sub.bones = bones; sub.numvertices = nidx.Length; sub.vertices = new Vertex[nidx.Length]; for (int k = 0; k < nidx.Length; ++k) { sub.vertices[k] = verts[nidx[k]]; } Console.WriteLine(" {0,8} {1,12}", sub.vertices.Length, sub.bones.Length); subs.Add(sub); } // メッシュ生成 TSOMesh mesh = new TSOMesh(); mesh.name = i.name; mesh.numsubs = subs.Count; mesh.sub = subs.ToArray(); mesh.matrix = Matrix44.Identity; mesh.effect = 0; meshes.Add(mesh); } return(true); }
protected override bool DoGenerateMeshes() { meshes = new List <TSOMesh>(); foreach (MqoObject i in mqo.Objects) { if (i.name.ToLower() == "bone") { continue; } Console.WriteLine("object:" + i.name); // 一番近い頂点への参照 List <int> vref = new List <int>(i.vertices.Count); foreach (Point3 j in i.vertices) { vref.Add(pc.NearestIndex(j.x, j.y, j.z)); } // 法線生成 Point3[] nrm = new Point3[i.vertices.Count]; foreach (MqoFace j in i.faces) { Point3 v1 = Point3.Normalize(i.vertices[j.b] - i.vertices[j.a]); Point3 v2 = Point3.Normalize(i.vertices[j.c] - i.vertices[j.b]); Point3 n = Point3.Normalize(Point3.Cross(v1, v2)); nrm[j.a] -= n; nrm[j.b] -= n; nrm[j.c] -= n; } for (int j = 0; j < nrm.Length; ++j) { nrm[j] = Point3.Normalize(nrm[j]); } // フェイスの組成 List <int> faces1 = new List <int>(); List <int> faces2 = new List <int>(); //int[] bonecnv = new int[tsor.nodes.Length]; // ボーン変換テーブル VertexHeap <Vertex> vh = new VertexHeap <Vertex>(); Vertex[] v = new Vertex[3]; List <int> bones = new List <int>(16); List <ushort> indices = new List <ushort>(); Dictionary <int, int> selected = new Dictionary <int, int>(); Dictionary <int, int> work = new Dictionary <int, int>(); List <TSOSubMesh> subs = new List <TSOSubMesh>(); for (int j = 0, n = i.faces.Count; j < n; ++j) { faces1.Add(j); } #region ボーンパーティション Console.WriteLine(" vertices bone_indices"); Console.WriteLine(" -------- ------------"); while (faces1.Count > 0) { int mtl = i.faces[faces1[0]].mtl; selected.Clear(); indices.Clear(); vh.Clear(); bones.Clear(); foreach (int j in faces1) { MqoFace f = i.faces[j]; if (f.mtl != mtl) { faces2.Add(j); continue; } v[0] = vlst[vref[f.a]]; v[1] = vlst[vref[f.b]]; v[2] = vlst[vref[f.c]]; work.Clear(); for (int k = 0; k < 3; ++k) { Vertex vv = v[k]; UInt32 idx0 = vv.Idx; Point4 wgt0 = vv.Wgt; byte * idx = (byte *)(&idx0); float *wgt = (float *)(&wgt0); for (int l = 0; l < 4; ++l) { if (wgt[l] <= float.Epsilon) { continue; } if (selected.ContainsKey(idx[l])) { continue; } if (!work.ContainsKey(idx[l])) { work.Add(idx[l], 0); } } } if (selected.Count + work.Count > 16) { faces2.Add(j); continue; } // ボーンリストに足してvalid foreach (KeyValuePair <int, int> l in work) { selected.Add(l.Key, selected.Count); // ボーンテーブルに追加 bones.Add(l.Key); } // \todo 点の追加 Vertex va = new Vertex(i.vertices[f.a], v[0].Wgt, v[0].Idx, nrm[f.a], new Point2(f.ta.x, 1 - f.ta.y)); Vertex vb = new Vertex(i.vertices[f.b], v[1].Wgt, v[1].Idx, nrm[f.b], new Point2(f.tb.x, 1 - f.tb.y)); Vertex vc = new Vertex(i.vertices[f.c], v[2].Wgt, v[2].Idx, nrm[f.c], new Point2(f.tc.x, 1 - f.tc.y)); indices.Add(vh.Add(va)); indices.Add(vh.Add(vc)); indices.Add(vh.Add(vb)); } // フェイス最適化 ushort[] nidx = NvTriStrip.Optimize(indices.ToArray()); // 頂点のボーン参照ローカルに変換 Vertex[] verts = vh.verts.ToArray(); for (int j = 0; j < verts.Length; ++j) { uint idx0 = verts[j].Idx; byte * idx = (byte *)(&idx0); Point4 wgt0 = verts[j].Wgt; float *wgt = (float *)(&wgt0); for (int k = 0; k < 4; ++k) { if (wgt[k] > float.Epsilon) { idx[k] = (byte)selected[idx[k]]; } } verts[j].Idx = idx0; } // サブメッシュ生成 TSOSubMesh sub = new TSOSubMesh(); sub.spec = mtl; sub.numbones = bones.Count; sub.bones = bones.ToArray(); sub.numvertices = nidx.Length; sub.vertices = new Vertex[nidx.Length]; for (int j = 0; j < nidx.Length; ++j) { sub.vertices[j] = verts[nidx[j]]; } Console.WriteLine(" {0,8} {1,12}", sub.vertices.Length, sub.bones.Length); subs.Add(sub); // 次の周回 List <int> t = faces1; faces1 = faces2; faces2 = t; t.Clear(); } #endregion // \todo TSOMesh生成 TSOMesh mesh = new TSOMesh(); mesh.name = i.name; mesh.numsubs = subs.Count; mesh.sub = subs.ToArray(); mesh.matrix = Matrix44.Identity; mesh.effect = 0; meshes.Add(mesh); } return(true); }
public void Write(TSOFile file) { tw.WriteLine("Metasequoia Document"); tw.WriteLine("Format Text Ver 1.0"); tw.WriteLine(""); tw.WriteLine("Scene {"); tw.WriteLine("\tpos -7.0446 4.1793 1541.1764"); tw.WriteLine("\tlookat 11.8726 193.8590 0.4676"); tw.WriteLine("\thead 0.8564"); tw.WriteLine("\tpich 0.1708"); tw.WriteLine("\tortho 0"); tw.WriteLine("\tzoom2 31.8925"); tw.WriteLine("\tamb 0.250 0.250 0.250"); tw.WriteLine("}"); VertexHeap <UVertex> vh = new VertexHeap <UVertex>(); List <ushort> face = new List <ushort>(2048 * 3); List <float> uv = new List <float>(2048 * 3 * 2); List <int> mtl = new List <int>(2048); foreach (TSOTex tex in file.textures) { CreateTextureFile(tex); } tw.WriteLine("Material {0} {{", file.materials.Length); foreach (TSOMaterial mat in file.materials) { if (mat.ColorTex != null) { TSOTex tex = file.texturemap[mat.ColorTex]; tw.WriteLine( "\t\"{0}\" col(1.000 1.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00) tex(\"{1}\")", mat.name, GetTexturePath(tex)); } else { tw.WriteLine( "\t\"{0}\" col(1.000 1.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00))", mat.name); } } tw.WriteLine("}"); foreach (TSOMesh i in file.meshes) { vh.Clear(); face.Clear(); uv.Clear(); mtl.Clear(); foreach (TSOSubMesh j in i.sub) { int cnt = 0; ushort a = 0, b = 0, c = 0; Vertex va = new Vertex(), vb = new Vertex(), vc = new Vertex(); foreach (Vertex k in j.vertices) { ++cnt; va = vb; a = b; vb = vc; b = c; vc = k; c = vh.Add(new UVertex(k.Pos, k.Nrm, k.Tex, j.spec)); if (cnt < 3) { continue; } if (a == b || b == c || c == a) { continue; } if ((cnt & 1) == 0) { face.Add(a); uv.Add(va.Tex.x); uv.Add(1 - va.Tex.y); face.Add(b); uv.Add(vb.Tex.x); uv.Add(1 - vb.Tex.y); face.Add(c); uv.Add(vc.Tex.x); uv.Add(1 - vc.Tex.y); mtl.Add(j.spec); } else { face.Add(a); uv.Add(va.Tex.x); uv.Add(1 - va.Tex.y); face.Add(c); uv.Add(vc.Tex.x); uv.Add(1 - vc.Tex.y); face.Add(b); uv.Add(vb.Tex.x); uv.Add(1 - vb.Tex.y); mtl.Add(j.spec); } } } tw.WriteLine("Object \"{0}\" {{", i.Name); tw.WriteLine("\tvisible {0}", 15); tw.WriteLine("\tlocking {0}", 0); tw.WriteLine("\tshading {0}", 1); tw.WriteLine("\tfacet {0}", 59.5); tw.WriteLine("\tcolor {0:F3} {1:F3} {2:F3}", 0.898f, 0.498f, 0.698f); tw.WriteLine("\tcolor_type {0}", 0); // tw.WriteLine("\tvertex {0} {{", vh.Count); foreach (UVertex j in vh.verts) { WriteVertex(j.Pos.x, j.Pos.y, j.Pos.z); } tw.WriteLine("\t}"); // tw.WriteLine("\tface {0} {{", face.Count / 3); System.Diagnostics.Debug.Assert(face.Count * 2 == uv.Count); System.Diagnostics.Debug.Assert(face.Count == mtl.Count * 3); for (int j = 0, n = face.Count; j < n; j += 3) { WriteFace(face[j + 0], face[j + 1], face[j + 2], uv[j * 2 + 0], uv[j * 2 + 1], uv[j * 2 + 2], uv[j * 2 + 3], uv[j * 2 + 4], uv[j * 2 + 5], mtl[j / 3]); } tw.WriteLine("\t}"); tw.WriteLine("}"); } // ボーンを出す switch (BoneMode) { case MqoBoneMode.None: break; case MqoBoneMode.RokDeBone: { // マトリクス計算 foreach (TSONode i in file.nodes) { if (i.parent == null) { i.world = i.Matrix; } else { i.world = Matrix44.Mul(i.Matrix, i.parent.World); } } List <Point3> points = new List <Point3>(); List <int> bones = new List <int>(); tw.WriteLine("Object \"{0}\" {{", "Bone"); tw.WriteLine("\tvisible {0}", 15); tw.WriteLine("\tlocking {0}", 0); tw.WriteLine("\tshading {0}", 1); tw.WriteLine("\tfacet {0}", 59.5); tw.WriteLine("\tcolor {0} {1} {2}", 1, 0, 0); tw.WriteLine("\tcolor_type {0}", 0); foreach (TSONode i in file.nodes) { if (i.children.Count == 0) { continue; } Point3 q = new Point3(i.world.M41, i.world.M42, i.world.M43); Point3 p = new Point3(); foreach (TSONode j in i.children) { p.x += j.world.M41; p.y += j.world.M42; p.z += j.world.M43; } p.x /= i.children.Count; p.y /= i.children.Count; p.z /= i.children.Count; bones.Add(points.Count); points.Add(q); bones.Add(points.Count); points.Add(p); } tw.WriteLine("\tvertex {0} {{", points.Count); foreach (Point3 j in points) { WriteVertex(j.x, j.y, j.z); } tw.WriteLine("\t}"); // tw.WriteLine("\tface {0} {{", bones.Count / 2); for (int j = 0, n = bones.Count; j < n; j += 2) { tw.WriteLine(string.Format("\t\t2 V({0} {1})", bones[j + 0], bones[j + 1])); } tw.WriteLine("\t}"); tw.WriteLine("}"); } break; case MqoBoneMode.Mikoto: { } break; } tw.WriteLine("Eof"); }