private bool SectionFace(string[] tokens) { if (tokens[0] == "}") { return(false); } if (3 != int.Parse(tokens[0])) { return(true); } StringBuilder sb = new StringBuilder(); foreach (string i in tokens) { sb.Append(' ').Append(i); } string line = sb.ToString().Trim(); MqoFace f = new MqoFace(); tokens = SplitString(line); current.faces.Add(f); for (int i = 1; i < tokens.Length; ++i) { string t = tokens[i]; string t2 = t.ToLower(); if (t2.StartsWith("v(")) { string[] t3 = SplitParam(t); f.a = ushort.Parse(t3[1]); f.b = ushort.Parse(t3[2]); f.c = ushort.Parse(t3[3]); } else if (t2.StartsWith("m(")) { string[] t3 = SplitParam(t); f.mtl = ushort.Parse(t3[1]); } else if (t2.StartsWith("uv(")) { string[] t3 = SplitParam(t); f.ta = Point2.Parse(t3, 1); f.tb = Point2.Parse(t3, 3); f.tc = Point2.Parse(t3, 5); } } return(true); }
public void Update(TSOMesh mesh) { vh.Clear(); faces.Clear(); foreach (TSOSubMesh sub_mesh in mesh.sub_meshes) { int cnt = 0; ushort a = 0, b = 0, c = 0; Vertex va = new Vertex(), vb = new Vertex(), vc = new Vertex(); foreach (Vertex v in sub_mesh.vertices) { ++cnt; va = vb; a = b; vb = vc; b = c; vc = v; c = vh.Add(new UVertex(v.Pos, v.Wgt, v.Idx, v.Nrm)); if (cnt < 3) { continue; } if (a == b || b == c || c == a) { continue; } if ((cnt & 1) == 0) { MqoFace f = new MqoFace(a, b, c, (ushort)sub_mesh.spec, new Point2(va.Tex.x, 1 - va.Tex.y), new Point2(vb.Tex.x, 1 - vb.Tex.y), new Point2(vc.Tex.x, 1 - vc.Tex.y)); faces.Add(f); } else { MqoFace f = new MqoFace(a, c, b, (ushort)sub_mesh.spec, new Point2(va.Tex.x, 1 - va.Tex.y), new Point2(vc.Tex.x, 1 - vc.Tex.y), new Point2(vb.Tex.x, 1 - vb.Tex.y)); faces.Add(f); } } } }
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); }
protected override bool DoGenerateMeshes() { meshes = new List <TSOMesh>(); foreach (MqoObject obj in mqo.Objects) { if (obj.name.ToLower() == "bone") { continue; } Console.WriteLine("object:" + obj.name); // 一番近い頂点への参照 List <int> vref = new List <int>(obj.vertices.Count); foreach (UVertex i in obj.vertices) { vref.Add(pc.NearestIndex(i.Pos.x, i.Pos.y, i.Pos.z)); } obj.CreateNormal(); List <int> faces_1 = new List <int>(); List <int> faces_2 = new List <int>(); Heap <int> bh = new Heap <int>(); Heap <Vertex> vh = new Heap <Vertex>(); Vertex[] refvs = new Vertex[3]; List <ushort> vert_indices = new List <ushort>(); Dictionary <int, bool> adding_bone_indices = new Dictionary <int, bool>(); List <TSOSubMesh> subs = new List <TSOSubMesh>(); for (int i = 0, n = obj.faces.Count; i < n; ++i) { faces_1.Add(i); } #region ボーンパーティション Console.WriteLine(" vertices bone_indices"); Console.WriteLine(" -------- ------------"); while (faces_1.Count != 0) { int spec = obj.faces[faces_1[0]].spec; bh.Clear(); vh.Clear(); vert_indices.Clear(); foreach (int f in faces_1) { MqoFace face = obj.faces[f]; if (face.spec != spec) { faces_2.Add(f); continue; } for (int k = 0; k < 3; ++k) { refvs[k] = refverts[vref[face.vert_indices[k]]]; } adding_bone_indices.Clear(); for (int k = 0; k < 3; ++k) { UInt32 idx0 = refvs[k].Idx; Point4 wgt0 = refvs[k].Wgt; byte * idx = (byte *)(&idx0); float *wgt = (float *)(&wgt0); for (int l = 0; l < 4; ++l) { if (wgt[l] <= float.Epsilon) { continue; } if (bh.map.ContainsKey(idx[l])) { continue; } adding_bone_indices[idx[l]] = true; } } if (bh.Count + adding_bone_indices.Count > 16) { faces_2.Add(f); continue; } foreach (int i in adding_bone_indices.Keys) { bh.Add(i); } for (int k = 0; k < 3; ++k) { UInt32 idx0 = refvs[k].Idx; Point4 wgt0 = refvs[k].Wgt; byte * idx = (byte *)(&idx0); float *wgt = (float *)(&wgt0); for (int l = 0; l < 4; ++l) { if (wgt[l] <= float.Epsilon) { continue; } idx[l] = (byte)bh[idx[l]]; } refvs[k].Idx = idx0; } Vertex va = new Vertex(obj.vertices[face.a].Pos, refvs[0].Wgt, refvs[0].Idx, obj.vertices[face.a].Nrm, new Point2(face.ta.x, 1 - face.ta.y)); Vertex vb = new Vertex(obj.vertices[face.b].Pos, refvs[1].Wgt, refvs[1].Idx, obj.vertices[face.b].Nrm, new Point2(face.tb.x, 1 - face.tb.y)); Vertex vc = new Vertex(obj.vertices[face.c].Pos, refvs[2].Wgt, refvs[2].Idx, obj.vertices[face.c].Nrm, new Point2(face.tc.x, 1 - face.tc.y)); vert_indices.Add(vh.Add(va)); vert_indices.Add(vh.Add(vc)); vert_indices.Add(vh.Add(vb)); } ushort[] optimized_indices = NvTriStrip.Optimize(vert_indices.ToArray()); TSOSubMesh sub = new TSOSubMesh(); sub.spec = spec; sub.numbones = bh.Count; sub.bones = bh.ary.ToArray(); sub.numvertices = optimized_indices.Length; Vertex[] vertices = new Vertex[optimized_indices.Length]; for (int i = 0; i < optimized_indices.Length; ++i) { vertices[i] = vh.ary[optimized_indices[i]]; } sub.vertices = vertices; Console.WriteLine(" {0,8} {1,12}", sub.vertices.Length, sub.bones.Length); subs.Add(sub); List <int> faces_tmp = faces_1; faces_1 = faces_2; faces_2 = faces_tmp; faces_tmp.Clear(); } #endregion TSOMesh mesh = new TSOMesh(); mesh.name = obj.name; mesh.numsubs = subs.Count; mesh.sub_meshes = subs.ToArray(); mesh.matrix = Matrix44.Identity; mesh.effect = 0; meshes.Add(mesh); } return(true); }
bool SectionFace(string[] tokens) { if (tokens[0] == "}") { return(false); } int nface = int.Parse(tokens[0]); { StringBuilder sb = new StringBuilder(); foreach (string i in tokens) { sb.Append(' ').Append(i); } string line = sb.ToString().Trim(); tokens = SplitString(line); } switch (nface) { case 3: { MqoFace f = new MqoFace(); for (int i = 1; i < tokens.Length; ++i) { string t = tokens[i]; if (t.StartsWith("V(")) { string[] t3 = SplitParam(t); f.a = ushort.Parse(t3[1]); f.b = ushort.Parse(t3[2]); f.c = ushort.Parse(t3[3]); } else if (t.StartsWith("M(")) { string[] t3 = SplitParam(t); f.spec = ushort.Parse(t3[1]); } else if (t.StartsWith("UV(")) { string[] t3 = SplitParam(t); f.ta = Point2.Parse(t3, 1); f.tb = Point2.Parse(t3, 3); f.tc = Point2.Parse(t3, 5); } } obj.faces.Add(f); } break; case 4: { MqoFace f = new MqoFace(); MqoFace f2 = new MqoFace(); for (int i = 1; i < tokens.Length; ++i) { string t = tokens[i]; if (t.StartsWith("V(")) { string[] t3 = SplitParam(t); f.a = ushort.Parse(t3[1]); f.b = ushort.Parse(t3[2]); f.c = ushort.Parse(t3[3]); f2.a = f.a; f2.b = f.c; f2.c = ushort.Parse(t3[4]); } else if (t.StartsWith("M(")) { string[] t3 = SplitParam(t); f.spec = ushort.Parse(t3[1]); f2.spec = f.spec; } else if (t.StartsWith("UV(")) { string[] t3 = SplitParam(t); f.ta = Point2.Parse(t3, 1); f.tb = Point2.Parse(t3, 3); f.tc = Point2.Parse(t3, 5); f2.ta = f.ta; f2.tb = f.tc; f2.tc = Point2.Parse(t3, 7); } } obj.faces.Add(f); obj.faces.Add(f2); } break; default: Console.WriteLine("unsupported: nface {0}", nface); break; } return(true); }