OSDN Git Service

rename var v to refvs.
[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                         refvs[0] = refverts[vref[face.a]];
101                         refvs[1] = refverts[vref[face.b]];
102                         refvs[2] = refverts[vref[face.c]];
103
104                         adding_bone_indices.Clear();
105
106                         for (int k = 0; k < 3; ++k)
107                         {
108                             UInt32 idx0 = refvs[k].Idx;
109                             Point4 wgt0 = refvs[k].Wgt;
110                             byte* idx = (byte*)(&idx0);
111                             float* wgt = (float*)(&wgt0);
112
113                             for (int l = 0; l < 4; ++l)
114                             {
115                                 if (wgt[l] <= float.Epsilon)
116                                     continue;
117                                 if (bh.map.ContainsKey(idx[l]))
118                                     continue;
119
120                                 adding_bone_indices[idx[l]] = true;
121                             }
122                         }
123
124                         if (bh.Count + adding_bone_indices.Count > 16)
125                         {
126                             faces_2.Add(f);
127                             continue;
128                         }
129
130                         foreach (int i in adding_bone_indices.Keys)
131                         {
132                             bh.Add(i);
133                         }
134
135                         for (int k = 0; k < 3; ++k)
136                         {
137                             UInt32 idx0 = refvs[k].Idx;
138                             Point4 wgt0 = refvs[k].Wgt;
139                             byte* idx = (byte*)(&idx0);
140                             float* wgt = (float*)(&wgt0);
141
142                             for (int l = 0; l < 4; ++l)
143                             {
144                                 if (wgt[l] <= float.Epsilon)
145                                     continue;
146
147                                 idx[l] = (byte)bh[idx[l]];
148                             }
149
150                             //refvs[k]は値型なのでrefvertsに影響しない。
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 }