OSDN Git Service

TSOGeneratorMqxBone
[tdcgexplorer/tso2mqo.git] / TSOGeneratorRefBone.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Text;
5
6 namespace Tso2MqoGui
7 {
8     public unsafe class TSOGeneratorRefBone : TSOGenerator
9     {
10         public TSOGeneratorRefBone(TSOGeneratorConfig config)
11             : base(config)
12         {
13         }
14
15         // 参照tso上の全頂点を保持する
16         List<Vertex> refverts;
17         // 最近傍探索
18         PointCluster pc;
19
20         void CreateRefVerts(TSOFile tso)
21         {
22             refverts = new List<Vertex>();
23
24             foreach (TSOMesh i in tso.meshes)
25                 foreach (TSOSubMesh j in i.sub_meshes)
26                     refverts.AddRange(j.vertices);
27         }
28
29         void CreatePointCluster()
30         {
31             pc = new PointCluster(refverts.Count);
32
33             foreach (Vertex i in refverts)
34                 pc.Add(i.Pos);
35
36             pc.Clustering();
37         }
38
39         protected override bool DoLoadRefTSO(string path)
40         {
41             tsoref = LoadTSO(path);
42             tsoref.SwitchBoneIndicesOnMesh();
43             CreateRefVerts(tsoref);
44             CreatePointCluster();
45             return true;
46         }
47
48         protected override bool DoGenerateMeshes()
49         {
50             meshes = new List<TSOMesh>();
51
52             foreach (MqoObject obj in mqo.Objects)
53             {
54                 if (obj.name.ToLower() == "bone")
55                     continue;
56
57                 Console.WriteLine("object:" + obj.name);
58
59                 // 一番近い頂点への参照
60                 List<int> vref = new List<int>(obj.vertices.Count);
61
62                 foreach (UVertex i in obj.vertices)
63                     vref.Add(pc.NearestIndex(i.Pos.x, i.Pos.y, i.Pos.z));
64
65                 obj.CreateNormal();
66
67                 List<int> faces_1 = new List<int>();
68                 List<int> faces_2 = new List<int>();
69                 Heap<int> bh = new Heap<int>();
70                 Heap<Vertex> vh = new Heap<Vertex>();
71                 Vertex[] refvs = new Vertex[3];
72                 List<ushort> vert_indices = new List<ushort>();
73                 Dictionary<int, bool> adding_bone_indices = new Dictionary<int, bool>();
74                 List<TSOSubMesh> subs = new List<TSOSubMesh>();
75
76                 for (int i = 0, n = obj.faces.Count; i < n; ++i)
77                     faces_1.Add(i);
78
79                 #region ボーンパーティション
80                 Console.WriteLine("  vertices bone_indices");
81                 Console.WriteLine("  -------- ------------");
82
83                 while (faces_1.Count != 0)
84                 {
85                     int spec = obj.faces[faces_1[0]].spec;
86                     bh.Clear();
87                     vh.Clear();
88                     vert_indices.Clear();
89
90                     foreach (int f in faces_1)
91                     {
92                         MqoFace face = obj.faces[f];
93
94                         if (face.spec != spec)
95                         {
96                             faces_2.Add(f);
97                             continue;
98                         }
99
100                         for (int k = 0; k < 3; ++k)
101                         {
102                             refvs[k] = refverts[vref[face.vert_indices[k]]];
103                         }
104
105                         adding_bone_indices.Clear();
106
107                         for (int k = 0; k < 3; ++k)
108                         {
109                             UInt32 idx0 = refvs[k].Idx;
110                             Point4 wgt0 = refvs[k].Wgt;
111                             byte* idx = (byte*)(&idx0);
112                             float* wgt = (float*)(&wgt0);
113
114                             for (int l = 0; l < 4; ++l)
115                             {
116                                 if (wgt[l] <= float.Epsilon)
117                                     continue;
118                                 if (bh.map.ContainsKey(idx[l]))
119                                     continue;
120
121                                 adding_bone_indices[idx[l]] = true;
122                             }
123                         }
124
125                         if (bh.Count + adding_bone_indices.Count > 16)
126                         {
127                             faces_2.Add(f);
128                             continue;
129                         }
130
131                         foreach (int i in adding_bone_indices.Keys)
132                         {
133                             bh.Add(i);
134                         }
135
136                         for (int k = 0; k < 3; ++k)
137                         {
138                             UInt32 idx0 = refvs[k].Idx;
139                             Point4 wgt0 = refvs[k].Wgt;
140                             byte* idx = (byte*)(&idx0);
141                             float* wgt = (float*)(&wgt0);
142
143                             for (int l = 0; l < 4; ++l)
144                             {
145                                 if (wgt[l] <= float.Epsilon)
146                                     continue;
147
148                                 idx[l] = (byte)bh[idx[l]];
149                             }
150
151                             refvs[k].Idx = idx0;
152                         }
153
154                         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));
155                         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));
156                         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));
157
158                         vert_indices.Add(vh.Add(va));
159                         vert_indices.Add(vh.Add(vc));
160                         vert_indices.Add(vh.Add(vb));
161                     }
162
163                     ushort[] optimized_indices = NvTriStrip.Optimize(vert_indices.ToArray());
164
165                     TSOSubMesh sub = new TSOSubMesh();
166                     sub.spec = spec;
167                     sub.numbones = bh.Count;
168                     sub.bones = bh.ary.ToArray();
169
170                     sub.numvertices = optimized_indices.Length;
171                     Vertex[] vertices = new Vertex[optimized_indices.Length];
172                     for (int i = 0; i < optimized_indices.Length; ++i)
173                     {
174                         vertices[i] = vh.ary[optimized_indices[i]];
175                     }
176                     sub.vertices = vertices;
177
178                     Console.WriteLine("  {0,8} {1,12}", sub.vertices.Length, sub.bones.Length);
179
180                     subs.Add(sub);
181
182                     List<int> faces_tmp = faces_1;
183                     faces_1 = faces_2;
184                     faces_2 = faces_tmp;
185                     faces_tmp.Clear();
186                 }
187                 #endregion
188                 TSOMesh mesh = new TSOMesh();
189                 mesh.name = obj.name;
190                 mesh.numsubs = subs.Count;
191                 mesh.sub_meshes = subs.ToArray();
192                 mesh.matrix = Matrix44.Identity;
193                 mesh.effect = 0;
194                 meshes.Add(mesh);
195             }
196
197             return true;
198         }
199
200         protected override bool DoCleanup()
201         {
202             pc = null;
203             refverts = null;
204             return base.DoCleanup();
205         }
206     }
207 }