OSDN Git Service

assign MqoBone#node_id.
[tdcgexplorer/tso2mqo.git] / MqxReader.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Text;
5 using System.Xml;
6
7 namespace Tso2MqoGui
8 {
9     /// MqxFileを読み込みます。
10     public class MqxReader
11     {
12         // mqo path
13         //todo: rename to MqoPath
14         public string MqoFile;
15
16         string GetMqxPath()
17         {
18             return Path.ChangeExtension(MqoFile, ".mqx");
19         }
20
21         // ボーン配列 [out]
22         public MqoBone[] bones;
23
24         //頂点ウェイト配列 [out]
25         public MqoWeit[] weits;
26
27         public void CreateWeits()
28         {
29             weits = new MqoWeit[4];
30             for (int i = 0; i < 4; ++i)
31             {
32                 weits[i] = new MqoWeit();
33             }
34         }
35
36         // MqxFileを読み込む。
37         public bool Load(string mqo_file)
38         {
39             MqoFile = mqo_file;
40             string mqx_path = GetMqxPath();
41
42             if (! File.Exists(mqx_path))
43                 return false;
44
45             XmlReader reader = XmlReader.Create(mqx_path);
46             Read(reader);
47             reader.Close();
48
49             return true;
50         }
51
52         Dictionary<int, MqoBone> bone_idmap;
53
54         // create bone_idmap
55         // map id to bone
56         void CreateBoneMap()
57         {
58             bone_idmap = new Dictionary<int, MqoBone>();
59             foreach (MqoBone bone in bones)
60             {
61                 bone_idmap[bone.id] = bone;
62             }
63         }
64         void UpdateBones()
65         {
66             // assign node.parent
67             foreach (MqoBone bone in bones)
68             {
69                 if (bone.pid != 0)
70                 {
71                     bone.parent = bone_idmap[bone.pid];
72                 }
73                 else
74                     bone.parent = null;
75             }
76             // assign node.path
77             foreach (MqoBone bone in bones)
78             {
79                 if (bone.parent != null)
80                 {
81                     bone.path = bone.parent.path + "|" + bone.name;
82                 }
83                 else
84                     bone.path = "|" + bone.name;
85             }
86             // assign node.local_position
87             foreach (MqoBone bone in bones)
88             {
89                 if (bone.parent != null)
90                 {
91                     bone.local_position = bone.world_position - bone.parent.world_position;
92                 }
93                 else
94                     bone.local_position = bone.world_position;
95             }
96         }
97
98         public void Read(XmlReader reader)
99         {
100             reader.Read();
101
102             reader.ReadStartElement("MetasequoiaDocument");
103
104             reader.ReadStartElement("IncludedBy");
105             string mqo_file = reader.ReadString();
106             Console.WriteLine(mqo_file);
107             reader.ReadEndElement();//IncludedBy
108
109             reader.ReadStartElement("Plugin.56A31D20.71F282AB");
110             reader.ReadStartElement("BoneSet");
111             int len = 255;
112             bones = new MqoBone[len];
113             int i = 0;
114             while (reader.IsStartElement("Bone"))
115             {
116                 MqoBone bone = new MqoBone(i);
117                 bone.Read(reader);
118                 this.bones[i++] = bone;
119             }
120             reader.ReadEndElement();//BoneSet
121
122             len = i;
123             Array.Resize(ref bones, len);
124
125             CreateBoneMap();
126             UpdateBones();
127
128             while (reader.IsStartElement("Obj"))
129             {
130                 //Console.WriteLine("Obj");
131                 //Console.WriteLine("  id:{0}", reader.GetAttribute("id"));
132                 reader.Read();//Obj
133             }
134
135             while (reader.IsStartElement("Poses"))
136             {
137                 //Console.WriteLine("Poses");
138                 //Console.WriteLine("  isExist:{0}", reader.GetAttribute("isExist"));
139                 bool empty = reader.IsEmptyElement;
140                 reader.Read();//Poses
141                 if (empty)
142                     continue;
143                 while (reader.IsStartElement("Pose"))
144                 {
145                     //Console.WriteLine("Pose");
146                     //Console.WriteLine("  id:{0}", reader.GetAttribute("id"));
147                     reader.Read();//Pose
148                 }
149                 reader.ReadEndElement();//Poses
150             }
151             reader.ReadEndElement();//Plugin.56A31D20.71F282AB
152             reader.ReadEndElement();//MetasequoiaDocument
153         }
154
155         List<Dictionary<int, List<MqoWeit>>> weitmap;
156
157         public void CreateWeitMap()
158         {
159             int maxobjects = 255;
160             weitmap = new List<Dictionary<int, List<MqoWeit>>>(maxobjects);
161             for (int i = 0; i < maxobjects; i++)
162             {
163                 weitmap.Add(new Dictionary<int, List<MqoWeit>>(2048));
164             }
165             foreach (MqoBone bone in bones)
166             {
167                 foreach (MqoWeit weit in bone.weits)
168                 {
169                     Dictionary<int, List<MqoWeit>> map = weitmap[weit.object_id];
170                     List<MqoWeit> weits;
171                     if (! map.TryGetValue(weit.vertex_id, out weits))
172                     {
173                         weits = map[weit.vertex_id] = new List<MqoWeit>(4);
174                     }
175                     weits.Add(weit);
176                 }
177             }
178         }
179
180         public void UpdateWeits(int object_id, int vertex_id)
181         {
182             List<MqoWeit> weits = weitmap[object_id][vertex_id];
183             int len = weits.Count;
184             if (len > 4)
185                 len = 4;
186
187             //todo: sort
188
189             for (int i = 0; i < len; ++i)
190             {
191                 this.weits[i].node_id = weits[i].node_id;
192                 this.weits[i].weit = weits[i].weit; 
193             }
194             for (int i = len; i < 4; ++i)
195             {
196                 this.weits[i].node_id = 0;
197                 this.weits[i].weit = 0.0f;
198             }
199         }
200     }
201 }