OSDN Git Service

bd0aa53be3d7ea84f9d3c4160b81eddb60e5f61c
[tdcgexplorer/tso2mqo.git] / TSOFile.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.IO;\r
4 using System.Text;\r
5 using System.ComponentModel;\r
6 \r
7 namespace Tso2MqoGui\r
8 {\r
9     public class TSOFile : TDCGFile\r
10     {\r
11         internal Dictionary<string, TSONode>    nodemap;\r
12         internal Dictionary<string, TSOTex>     texturemap;\r
13         internal TSONode[]          nodes;\r
14         internal TSOTex[]           textures;\r
15         internal TSOEffect[]        effects;\r
16         internal TSOMaterial[]      materials;\r
17         internal TSOMesh[]          meshes;\r
18 \r
19         public TSOFile(string file)    : base(file) {}\r
20         public TSOFile(Stream s)       : base(s)    {}\r
21         public TSOFile(BinaryReader r) : base(r)    {}\r
22 \r
23         public void SaveTo(string file)\r
24         {\r
25         }\r
26 \r
27         [System.Diagnostics.Conditional("DEBUG_DETAIL")]\r
28         public static void WriteLine(string s)\r
29         {\r
30             System.Diagnostics.Debug.WriteLine(s);\r
31         }\r
32 \r
33         public static void ExchangeChannel(byte[] data, int depth)\r
34         {\r
35             for(int j= 0; j < data.Length; j+=depth)\r
36             {\r
37                 byte    tmp = data[j+2];\r
38                 data[j+2]   = data[j+0];\r
39                 data[j+0]   = tmp;\r
40             }\r
41         }\r
42 \r
43         public void ReadAll()\r
44         {\r
45             byte[]  magic                   = r.ReadBytes(4);\r
46 \r
47             if(magic[0] != (byte)'T'\r
48             || magic[1] != (byte)'S'\r
49             || magic[2] != (byte)'O'\r
50             || magic[3] != (byte)'1')\r
51                 throw new Exception("File is not TSO");\r
52 \r
53             //----- ノード -------------------------------------------------\r
54             nodemap                         = new Dictionary<string, TSONode>();\r
55             int     count                   = r.ReadInt32();\r
56             nodes                           = new TSONode[count];\r
57 \r
58             for(int i= 0; i < count; ++i)\r
59             {\r
60                 nodes[i]                    = new TSONode();\r
61                 nodes[i].id                 = i;\r
62                 nodes[i].name               = ReadString();\r
63                 nodes[i].sname              = nodes[i].name.Substring(nodes[i].name.LastIndexOf('|')+1);\r
64                 nodemap.Add(nodes[i].name, nodes[i]);\r
65 \r
66                 WriteLine(i+ ": " + nodes[i].name);\r
67             }\r
68 \r
69             for(int i= 0; i < count; ++i)\r
70             {\r
71                 int     index   = nodes[i].name.LastIndexOf('|');\r
72 \r
73                 if(index <= 0)\r
74                     continue;\r
75 \r
76                 string  pname   = nodes[i].name.Substring(0, index);\r
77                 WriteLine(pname);\r
78                 nodes[i].parent = nodemap[pname];\r
79                 nodes[i].parent.children.Add(nodes[i]);\r
80             }\r
81 \r
82             WriteLine(r.BaseStream.Position.ToString("X"));\r
83 \r
84             count                           = r.ReadInt32();\r
85 \r
86             // Node Matrix\r
87             for(int i= 0; i < count; ++i)\r
88             {\r
89                 nodes[i].matrix             = ReadMatrix();\r
90             }\r
91 \r
92             WriteLine(r.BaseStream.Position.ToString("X"));\r
93 \r
94             //----- テクスチャ ---------------------------------------------\r
95             count                           = r.ReadInt32();\r
96             textures                        = new TSOTex[count];\r
97             texturemap                      = new Dictionary<string, TSOTex>();\r
98 \r
99             for(int i= 0; i < count; ++i)\r
100             {\r
101                 textures[i]                 = new TSOTex();\r
102                 textures[i].id              = i;\r
103                 textures[i].name            = ReadString();\r
104                 textures[i].file            = ReadString();\r
105                 textures[i].width           = r.ReadInt32();\r
106                 textures[i].height          = r.ReadInt32();\r
107                 textures[i].depth           = r.ReadInt32();\r
108                 textures[i].data            = r.ReadBytes(textures[i].width * textures[i].height * textures[i].depth);\r
109                 texturemap.Add(textures[i].name, textures[i]);\r
110 \r
111                 ExchangeChannel(textures[i].data, textures[i].depth);\r
112 \r
113                 WriteLine(r.BaseStream.Position.ToString("X"));\r
114             }\r
115 \r
116             //----- エフェクト ---------------------------------------------\r
117             count                   = r.ReadInt32();\r
118             effects                 = new TSOEffect[count];\r
119 \r
120             for(int i= 0; i < count; ++i)\r
121             {\r
122                 StringBuilder   sb          = new StringBuilder();\r
123                 effects[i]                  = new TSOEffect();\r
124                 effects[i].name             = ReadString();\r
125                 effects[i].line             = r.ReadInt32();\r
126 \r
127                 for(int j= 0; j < effects[i].line; ++j)\r
128                     sb.Append(ReadString()).Append('\n');\r
129 \r
130                 effects[i].code             = sb.ToString();\r
131 \r
132                 WriteLine(r.BaseStream.Position.ToString("X"));\r
133             }\r
134 \r
135             //----- マテリアル ---------------------------------------------\r
136             count                           = r.ReadInt32();\r
137             materials                       = new TSOMaterial[count];\r
138 \r
139             for(int i= 0; i < count; ++i)\r
140             {\r
141                 StringBuilder   sb          = new StringBuilder();\r
142                 materials[i]                = new TSOMaterial();\r
143                 materials[i].id             = i;\r
144                 materials[i].name           = ReadString();\r
145                 materials[i].file           = ReadString();\r
146                 materials[i].line           = r.ReadInt32();\r
147 \r
148                 for(int j= 0; j < materials[i].line; ++j)\r
149                     sb.Append(ReadString()).Append('\n');\r
150 \r
151                 materials[i].code           = sb.ToString();\r
152                 materials[i].ParseParameters();\r
153 \r
154                 WriteLine(r.BaseStream.Position.ToString("X"));\r
155             }\r
156 \r
157             //----- メッシュ -----------------------------------------------\r
158             count                           = r.ReadInt32();\r
159             meshes                          = new TSOMesh[count];\r
160             int             check           = 0;\r
161             for(int i= 0; i < count; ++i)\r
162             {\r
163                 meshes[i]                   = new TSOMesh();\r
164                 meshes[i].file              = this;\r
165                 meshes[i].name              = ReadString();\r
166                 meshes[i].matrix            = ReadMatrix();\r
167                 meshes[i].effect            = r.ReadInt32();\r
168                 meshes[i].numsubs           = r.ReadInt32();\r
169                 meshes[i].sub               = new TSOSubMesh[meshes[i].numsubs];\r
170 \r
171                 for(int j= 0; j < meshes[i].numsubs; ++j)\r
172                 {\r
173                     meshes[i].sub[j]            = new TSOSubMesh();\r
174                     meshes[i].sub[j].owner      = meshes[i];\r
175                     meshes[i].sub[j].spec       = r.ReadInt32();\r
176                     meshes[i].sub[j].numbones   = r.ReadInt32();\r
177                     meshes[i].sub[j].bones      = new int[meshes[i].sub[j].numbones];\r
178 \r
179                     meshes[i].sub[j].ink        = materials[meshes[i].sub[j].spec].technique.ToUpper().IndexOf("INKOFF") < 0;\r
180                   //meshes[i].sub[j].shadow     = specs[meshes[i].sub[j].spec].technique.ToUpper().IndexOf(Shadow\r
181 \r
182                     for(int k= 0; k < meshes[i].sub[j].numbones; ++k)\r
183                         meshes[i].sub[j].bones[k]   = r.ReadInt32();\r
184 \r
185                     meshes[i].sub[j].numvertices= r.ReadInt32();\r
186                     Vertex[]    v               =  new Vertex[meshes[i].sub[j].numvertices];\r
187                     meshes[i].sub[j].vertices= v;\r
188 \r
189                     for(int k= 0; k < meshes[i].sub[j].numvertices; ++k)\r
190                     {\r
191                         ReadVertex(ref v[k]);\r
192                     }\r
193 \r
194                     WriteLine(r.BaseStream.Position.ToString("X"));\r
195                     System.Diagnostics.Debug.WriteLine(r.BaseStream.Position.ToString("X"));\r
196                 }\r
197             }\r
198 \r
199             WriteLine(r.BaseStream.Position.ToString("X"));\r
200             WriteLine(check.ToString("X"));\r
201 \r
202             r.BaseStream.Dispose();\r
203         }\r
204     }\r
205 \r
206     public class TSONode\r
207     {\r
208         internal int            id;\r
209         internal string         name;\r
210         internal string         sname;\r
211         internal Matrix44       matrix;\r
212         internal Matrix44       world;\r
213         internal List<TSONode>  children    = new List<TSONode>();\r
214         internal TSONode        parent;\r
215 \r
216         [Category("General")] public int      ID        { get { return id; } }\r
217         [Category("General")] public string   Name      { get { return name; } }\r
218         [Category("General")] public string   ShortName { get { return sname; } }\r
219         [Category("Detail")]  public Matrix44 Matrix    { get { return matrix; } set { matrix= value; } }\r
220         [Category("Detail")]  public Matrix44 World     { get { return world;  } set { world = value; } }\r
221 \r
222         public override string ToString()\r
223         {\r
224             StringBuilder   sb  = new StringBuilder();\r
225             sb.Append("Name:           ").AppendLine(name);\r
226             sb.Append("Matrix:         ").AppendLine(matrix.ToString());\r
227             sb.Append("Children.Count: ").AppendLine(children.Count.ToString());\r
228             return sb.ToString();\r
229         }\r
230     }\r
231 \r
232     public class TSOTex\r
233     {\r
234         internal int            id;\r
235         internal string         name;\r
236         internal string         file;\r
237         internal int            width;\r
238         internal int            height;\r
239         internal int            depth;\r
240         internal byte[]         data;\r
241 \r
242         [Category("General")] public int      ID      { get { return id; } }\r
243         [Category("General")] public string   Name    { get { return name; } }\r
244         [Category("Detail")]  public string   File    { get { return file; } set { file= value; } }\r
245         [Category("Detail")]  public int      Width   { get { return width; } }\r
246         [Category("Detail")]  public int      Height  { get { return height; } }\r
247         [Category("Detail")]  public int      Depth   { get { return depth; } }\r
248 \r
249         public override string ToString()\r
250         {\r
251             StringBuilder   sb  = new StringBuilder();\r
252             sb.Append("Name:        ").AppendLine(name);\r
253             sb.Append("File:        ").AppendLine(file);\r
254             sb.Append("Width:       ").AppendLine(width.ToString());\r
255             sb.Append("Height:      ").AppendLine(height.ToString());\r
256             sb.Append("Depth:       ").AppendLine(depth.ToString());\r
257             sb.Append("Data.Length: ").AppendLine(data.Length.ToString());\r
258             return sb.ToString();\r
259         }\r
260     }\r
261 \r
262     public class TSOEffect\r
263     {\r
264         internal string         name;\r
265         internal int            line;\r
266         internal string         code;\r
267 \r
268         [Category("General")] public string   Name    { get { return name; } }\r
269         [Category("Detail")]  public string   Code    { get { return code; } set { code= value; } }\r
270 \r
271         public override string ToString()\r
272         {\r
273             StringBuilder   sb  = new StringBuilder();\r
274             sb.Append("Name:           ").AppendLine(name);\r
275             sb.Append("Line:           ").AppendLine(line.ToString());\r
276             sb.AppendLine("Code:").AppendLine(code);\r
277             return sb.ToString();\r
278         }\r
279     }\r
280 \r
281     public class TSOParameter\r
282     {\r
283         public string   Name;\r
284         public string   Type;\r
285         public string   Value;\r
286 \r
287         public TSOParameter(string type, string name, string value)\r
288         {\r
289             Name    = name;\r
290             Type    = type;\r
291             Value   = value;\r
292         }\r
293 \r
294         public override string ToString()\r
295         {\r
296 #if true\r
297             return Type + " " + Name + " = "  + Value;\r
298 #else\r
299             switch(Type)\r
300             {\r
301             case "string":  return Type + " " + Name + " = \"" + Value + "\"";\r
302             case "float":   return Type + " " + Name + " = ["  + Value + "]";\r
303             case "float4":  return Type + " " + Name + " = ["  + Value + "]";\r
304             default:        return Type + " " + Name + " = "  + Value;\r
305             }\r
306 #endif\r
307         }\r
308     }\r
309 \r
310     public class TSOMaterialCode : Dictionary<string, TSOParameter>\r
311     {\r
312         public TSOMaterialCode(string code)\r
313             : this(code.Split('\r', '\n'))\r
314         {\r
315         }\r
316 \r
317             public string GetValue(string index)\r
318             {\r
319             return this[index].Value;\r
320             }\r
321 \r
322             public void SetValue(string index, string value)\r
323             {\r
324             TSOParameter    p   = this[index];\r
325             p.Value             = value;\r
326             }\r
327 \r
328         public TSOMaterialCode(string[] code)\r
329         {\r
330             foreach(string i in code)\r
331             {\r
332                 try\r
333                 {\r
334                     int n1, n2;\r
335 \r
336                     if((n1= i.IndexOf(' ')) < 0)        continue;\r
337                     if((n2= i.IndexOf('=', n1+1)) < 0)  continue;\r
338 \r
339                     TSOParameter    p   = new TSOParameter(\r
340                         i.Substring(0, n1)    .Trim(),\r
341                         i.Substring(n1, n2-n1).Trim(),\r
342                         i.Substring(n2+1)     .Trim());\r
343                     TSOFile.WriteLine(p.ToString());\r
344                     Add(p.Name, p);\r
345                 } catch(Exception e)\r
346                 {\r
347                     System.Diagnostics.Debug.WriteLine(e);\r
348                 }\r
349             }\r
350         }\r
351 \r
352         public static TSOMaterialCode GenerateFromFile(string filename)\r
353         {\r
354             return new TSOMaterialCode(File.ReadAllLines(filename));\r
355         }\r
356     }\r
357 \r
358     public class TSOMaterial\r
359     {\r
360         internal int            id;\r
361         internal string         name;\r
362         internal string         file;\r
363         internal int            line;\r
364         internal string         code;\r
365         internal TSOMaterialCode    codedata;\r
366 \r
367         internal string     description;     // = "TA ToonShader v0.50"\r
368         internal string     shader;          // = "TAToonshade_050.cgfx"\r
369         internal string     technique;       // = "ShadowOn"\r
370         internal float      lightDirX;       // = [-0.00155681]\r
371         internal float      lightDirY;       // = [-0.0582338]\r
372         internal float      lightDirZ;       // = [-0.998302]\r
373         internal float      lightDirW;       // = [0]\r
374         internal Point4     shadowColor;     // = [0, 0, 0, 1]\r
375         internal string     shadeTex;        // = Ninjya_Ribbon_Toon_Tex\r
376         internal float      highLight;       // = [0]\r
377         internal float      colorBlend;      // = [10]\r
378         internal float      highLightBlend;  // = [10]\r
379         internal Point4     penColor;        // = [0.166, 0.166, 0.166, 1]\r
380         internal float      ambient;         // = [38]\r
381         internal string     colorTex;        // = file24\r
382         internal float      thickness;       // = [0.018]\r
383         internal float      shadeBlend;      // = [10]\r
384         internal float      highLightPower;  // = [100]\r
385 \r
386         [Category("General")]    public int         ID              { get { return id; } }\r
387         [Category("General")]    public string      Name            { get { return name; } }\r
388         [Category("Detail")]     public string      File            { get { return file; } }\r
389         [Category("Detail")]     public string      Code            { get { return code; } set { code= value; } }\r
390 \r
391         [Category("Parameters")] public string      Description     { get { return description;    } set { description   = value; } }\r
392         [Category("Parameters")] public string      Shader                      { get { return shader;         } set { shader        = value; } }\r
393         [Category("Parameters")] public string      Technique           { get { return technique;      } set { technique     = value; } }\r
394         [Category("Parameters")] public float       LightDirX           { get { return lightDirX;      } set { lightDirX     = value; } }\r
395         [Category("Parameters")] public float       LightDirY           { get { return lightDirY;      } set { lightDirY     = value; } }\r
396         [Category("Parameters")] public float       LightDirZ           { get { return lightDirZ;      } set { lightDirZ     = value; } }\r
397         [Category("Parameters")] public float       LightDirW           { get { return lightDirW;      } set { lightDirW     = value; } }\r
398         [Category("Parameters")] public Point4      ShadowColor     { get { return shadowColor;    } set { shadowColor   = value; } }\r
399         [Category("Parameters")] public string      ShadeTex            { get { return shadeTex;       } set { shadeTex      = value; } }\r
400         [Category("Parameters")] public float       HighLight           { get { return highLight;      } set { highLight     = value; } }\r
401         [Category("Parameters")] public float       ColorBlend          { get { return colorBlend;     } set { colorBlend    = value; } }\r
402         [Category("Parameters")] public float       HighLightBlend      { get { return highLightBlend; } set { highLightBlend= value; } }\r
403         [Category("Parameters")] public Point4      PenColor            { get { return penColor;       } set { penColor      = value; } }\r
404         [Category("Parameters")] public float       Ambient                 { get { return ambient;        } set { ambient       = value; } }\r
405         [Category("Parameters")] public string      ColorTex            { get { return colorTex;       } set { colorTex      = value; } }\r
406         [Category("Parameters")] public float       Thickness           { get { return thickness;      } set { thickness     = value; } }\r
407         [Category("Parameters")] public float       ShadeBlend          { get { return shadeBlend;     } set { shadeBlend    = value; } }\r
408         [Category("Parameters")] public float       HighLightPower      { get { return highLightPower; } set { highLightPower= value; } }\r
409 \r
410         public override string ToString()\r
411         {\r
412             StringBuilder   sb  = new StringBuilder();\r
413             sb.Append("Name:           ").AppendLine(name);\r
414             sb.Append("File:           ").AppendLine(file);\r
415             sb.Append("Line:           ").AppendLine(line.ToString());\r
416             sb.AppendLine("Code:").AppendLine(code);\r
417 \r
418             return sb.ToString();\r
419         }\r
420 \r
421         public void ParseParameters()\r
422         {\r
423             codedata    = new TSOMaterialCode(code);\r
424 \r
425             foreach(TSOParameter i in codedata.Values)\r
426                 SetValue(i.Type, i.Name, i.Value);\r
427         }\r
428 \r
429         public void SetValue(string type, string name, string value)\r
430         {\r
431             switch(name)\r
432             {\r
433             case "description":     description     = GetString (value); break;  // = "TA ToonShader v0.50"\r
434             case "shader":          shader          = GetString (value); break;  // = "TAToonshade_050.cgfx"\r
435             case "technique":       technique       = GetString (value); break;  // = "ShadowOn"\r
436             case "LightDirX":       lightDirX       = GetFloat  (value); break;  // = [-0.00155681]\r
437             case "LightDirY":       lightDirY       = GetFloat  (value); break;  // = [-0.0582338]\r
438             case "LightDirZ":       lightDirZ       = GetFloat  (value); break;  // = [-0.998302]\r
439             case "LightDirW":       lightDirW       = GetFloat  (value); break;  // = [0]\r
440             case "ShadowColor":     shadowColor     = GetPoint4 (value); break;  // = [0, 0, 0, 1]\r
441             case "ShadeTex":        shadeTex        = GetTexture(value); break;  // = Ninjya_Ribbon_Toon_Tex\r
442             case "HighLight":       highLight       = GetFloat  (value); break;  // = [0]\r
443             case "ColorBlend":      colorBlend      = GetFloat  (value); break;  // = [10]\r
444             case "HighLightBlend":  highLightBlend  = GetFloat  (value); break;  // = [10]\r
445             case "PenColor":        penColor        = GetPoint4 (value); break;  // = [0.166, 0.166, 0.166, 1]\r
446             case "Ambient":         ambient         = GetFloat  (value); break;  // = [38]\r
447             case "ColorTex":        colorTex        = GetTexture(value); break;  // = file24\r
448             case "Thickness":       thickness       = GetFloat  (value); break;  // = [0.018]\r
449             case "ShadeBlend":      shadeBlend      = GetFloat  (value); break;  // = [10]\r
450             case "HighLightPower":  highLightPower  = GetFloat  (value); break;  // = [100]\r
451             default:\r
452                 TSOFile.WriteLine("Unknown parameter. type=" + type + ", name=" + name + ", value=" + value);\r
453                 break;\r
454             }\r
455         }\r
456 \r
457         public string   GetTexture(string value)\r
458         {\r
459             return value;\r
460         }\r
461 \r
462         public string   GetString(string value)\r
463         {\r
464             return value.Trim('"');\r
465         }\r
466 \r
467         public float    GetFloat(string value)\r
468         {\r
469             return float.Parse(value.Trim('[', ']', ' '));\r
470         }\r
471 \r
472         public Point4   GetPoint4(string value)\r
473         {\r
474             string[]    token   = value.Trim('[', ']', ' ').Split(',');\r
475             Point4      p       = new Point4();\r
476             p.X                 = float.Parse(token[0].Trim());\r
477             p.Y                 = float.Parse(token[1].Trim());\r
478             p.Z                 = float.Parse(token[2].Trim());\r
479             p.W                 = float.Parse(token[3].Trim());\r
480             return p;\r
481         }\r
482     }\r
483 \r
484     public class TSOMesh\r
485     {\r
486         internal TSOFile        file;\r
487         internal string         name;\r
488         internal Matrix44       matrix;\r
489         internal int            effect;\r
490         internal int            numsubs;\r
491         internal TSOSubMesh[]   sub;\r
492 \r
493         [Category("General")]   public string   Name    { get { return name; } set { name= value; } }\r
494       //[Category("Detail")]    public int      Effect  { get { return name; } set { name= value; } }\r
495         [Category("Detail")]    public Matrix44 Matrix  { get { return matrix; } set { matrix= value; } }\r
496 \r
497         public override string ToString()\r
498         {\r
499             StringBuilder   sb  = new StringBuilder();\r
500             sb.Append("Name:           ").AppendLine(name);\r
501             sb.Append("Matrix:         ").AppendLine(matrix.ToString());\r
502             sb.Append("Effect?:        ").AppendLine(effect.ToString());\r
503             sb.Append("NumSubs:        ").AppendLine(numsubs.ToString());\r
504             sb.Append("SubMesh.Count:  ").AppendLine(sub.Length.ToString());\r
505             return sb.ToString();\r
506         }\r
507     }\r
508 \r
509     public class TSOSubMesh\r
510     {\r
511         internal int            spec;\r
512         internal int            numbones;\r
513         internal int[]          bones;\r
514         internal int            numvertices;\r
515         internal Vertex[]       vertices;\r
516         internal TSOMesh        owner;\r
517       //internal bool           shadow;\r
518         internal bool           ink;\r
519 \r
520         [Category("Detail")]    public int      Spec    { get { return spec; } set { spec= value; } }\r
521       //[Category("Detail")]    public int      Effect  { get { return name; } set { name= value; } }\r
522 \r
523         public override string ToString()\r
524         {\r
525             StringBuilder   sb  = new StringBuilder();\r
526             sb.Append("Spec:           ").AppendLine(spec.ToString());\r
527             sb.Append("NumBones:       ").AppendLine(numbones.ToString());\r
528             sb.Append("NumVertices:    ").AppendLine(numvertices.ToString());\r
529             return sb.ToString();\r
530         }\r
531     }\r
532 \r
533     public struct Matrix44\r
534     {\r
535         public static readonly Matrix44 Identity    = new Matrix44(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1);\r
536 \r
537         public float m11, m12, m13, m14;\r
538         public float m21, m22, m23, m24;\r
539         public float m31, m32, m33, m34;\r
540         public float m41, m42, m43, m44;\r
541 \r
542         public float M11 { get { return m11; } set { m11= value; } }\r
543         public float M12 { get { return m12; } set { m12= value; } }\r
544         public float M13 { get { return m13; } set { m13= value; } }\r
545         public float M14 { get { return m14; } set { m14= value; } }\r
546         public float M21 { get { return m21; } set { m21= value; } }\r
547         public float M22 { get { return m22; } set { m22= value; } }\r
548         public float M23 { get { return m23; } set { m23= value; } }\r
549         public float M24 { get { return m24; } set { m24= value; } }\r
550         public float M31 { get { return m31; } set { m31= value; } }\r
551         public float M32 { get { return m32; } set { m32= value; } }\r
552         public float M33 { get { return m33; } set { m33= value; } }\r
553         public float M34 { get { return m34; } set { m34= value; } }\r
554         public float M41 { get { return m41; } set { m41= value; } }\r
555         public float M42 { get { return m42; } set { m42= value; } }\r
556         public float M43 { get { return m43; } set { m43= value; } }\r
557         public float M44 { get { return m44; } set { m44= value; } }\r
558 \r
559         public Matrix44(\r
560             float a11, float a12, float a13, float a14,\r
561             float a21, float a22, float a23, float a24,\r
562             float a31, float a32, float a33, float a34,\r
563             float a41, float a42, float a43, float a44)\r
564         {\r
565             m11=a11; m12=a12; m13=a13; m14=a14;\r
566             m21=a21; m22=a22; m23=a23; m24=a24;\r
567             m31=a31; m32=a32; m33=a33; m34=a34;\r
568             m41=a41; m42=a42; m43=a43; m44=a44;\r
569         }\r
570 \r
571         public Point3 Translation   { get { return new Point3(M41, M42, M43); } } \r
572 \r
573         public override string ToString()\r
574         {\r
575             StringBuilder   sb  = new StringBuilder();\r
576             sb.AppendFormat("[{0:F4}, {1:F4}, {2:F4}, {3:F4}], ",  M11, M12, M13, M14)\r
577               .AppendFormat("[{0:F4}, {1:F4}, {2:F4}, {3:F4}], ",  M21, M22, M23, M24)\r
578               .AppendFormat("[{0:F4}, {1:F4}, {2:F4}, {3:F4}], ",  M31, M32, M33, M34)\r
579               .AppendFormat("[{0:F4}, {1:F4}, {2:F4}, {3:F4}]",    M41, M42, M43, M44);\r
580             return sb.ToString();\r
581         }\r
582 \r
583         public static Matrix44 Mul(Matrix44 a, Matrix44 b)\r
584         {\r
585             Matrix44    m   = new Matrix44();\r
586 \r
587             m.M11   = a.M11*b.M11 + a.M12*b.M21 + a.M13*b.M31 + a.M14*b.M41;\r
588             m.M12   = a.M11*b.M12 + a.M12*b.M22 + a.M13*b.M32 + a.M14*b.M42;\r
589             m.M13   = a.M11*b.M13 + a.M12*b.M23 + a.M13*b.M33 + a.M14*b.M43;\r
590             m.M14   = a.M11*b.M14 + a.M12*b.M24 + a.M13*b.M34 + a.M14*b.M44;\r
591 \r
592             m.M21   = a.M21*b.M11 + a.M22*b.M21 + a.M23*b.M31 + a.M24*b.M41;\r
593             m.M22   = a.M21*b.M12 + a.M22*b.M22 + a.M23*b.M32 + a.M24*b.M42;\r
594             m.M23   = a.M21*b.M13 + a.M22*b.M23 + a.M23*b.M33 + a.M24*b.M43;\r
595             m.M24   = a.M21*b.M14 + a.M22*b.M24 + a.M23*b.M34 + a.M24*b.M44;\r
596 \r
597             m.M31   = a.M31*b.M11 + a.M32*b.M21 + a.M33*b.M31 + a.M34*b.M41;\r
598             m.M32   = a.M31*b.M12 + a.M32*b.M22 + a.M33*b.M32 + a.M34*b.M42;\r
599             m.M33   = a.M31*b.M13 + a.M32*b.M23 + a.M33*b.M33 + a.M34*b.M43;\r
600             m.M34   = a.M31*b.M14 + a.M32*b.M24 + a.M33*b.M34 + a.M34*b.M44;\r
601 \r
602             m.M41   = a.M41*b.M11 + a.M42*b.M21 + a.M43*b.M31 + a.M44*b.M41;\r
603             m.M42   = a.M41*b.M12 + a.M42*b.M22 + a.M43*b.M32 + a.M44*b.M42;\r
604             m.M43   = a.M41*b.M13 + a.M42*b.M23 + a.M43*b.M33 + a.M44*b.M43;\r
605             m.M44   = a.M41*b.M14 + a.M42*b.M24 + a.M43*b.M34 + a.M44*b.M44;\r
606 \r
607             return m;\r
608         }\r
609     }\r
610 \r
611     public partial struct Vertex : IComparable<Vertex>\r
612     {\r
613         public Point3       Pos;\r
614         public Point4       Wgt;\r
615         public UInt32       Idx;\r
616         public Point3       Nrm;\r
617         public Point2       Tex;\r
618       //public int          Count;\r
619       //public Weights[]    Weights;\r
620 \r
621         public Vertex(Point3 pos, Point4 wgt, UInt32 idx, Point3 nrm, Point2 tex)\r
622         {\r
623             Pos = pos;\r
624             Wgt = wgt;\r
625             Idx = idx;\r
626             Nrm = nrm;\r
627             Tex = tex;\r
628         }\r
629 \r
630         public int CompareTo(Vertex o)\r
631         {\r
632             if(Pos.x < o.Pos.x) return -1; if(Pos.x > o.Pos.x) return 1;\r
633             if(Pos.y < o.Pos.y) return -1; if(Pos.y > o.Pos.y) return 1;\r
634             if(Pos.z < o.Pos.z) return -1; if(Pos.z > o.Pos.z) return 1;\r
635             if(Nrm.x < o.Nrm.x) return -1; if(Nrm.x > o.Nrm.x) return 1;\r
636             if(Nrm.y < o.Nrm.y) return -1; if(Nrm.y > o.Nrm.y) return 1;\r
637             if(Nrm.z < o.Nrm.z) return -1; if(Nrm.z > o.Nrm.z) return 1;\r
638             if(Tex.x < o.Tex.x) return -1; if(Tex.x > o.Tex.x) return 1;\r
639             if(Tex.y < o.Tex.y) return -1; if(Tex.y > o.Tex.y) return 1;\r
640             if(Wgt.x < o.Wgt.x) return -1; if(Wgt.x > o.Wgt.x) return 1;\r
641             if(Wgt.y < o.Wgt.y) return -1; if(Wgt.y > o.Wgt.y) return 1;\r
642             if(Wgt.z < o.Wgt.z) return -1; if(Wgt.z > o.Wgt.z) return 1;\r
643             if(Wgt.w < o.Wgt.w) return -1; if(Wgt.w > o.Wgt.w) return 1;\r
644             if(Idx   < o.Idx)   return -1; if(Idx   > o.Idx)   return 1;\r
645             return 0;\r
646         }\r
647 \r
648         public override int GetHashCode()\r
649         {\r
650             return Pos.x.GetHashCode() ^ Pos.y.GetHashCode() ^ Pos.z.GetHashCode()\r
651                  ^ Nrm.x.GetHashCode() ^ Nrm.y.GetHashCode() ^ Nrm.z.GetHashCode()\r
652                  ^ Tex.x.GetHashCode() ^ Tex.y.GetHashCode() ^ Wgt.w.GetHashCode()\r
653                  ^ Wgt.x.GetHashCode() ^ Wgt.y.GetHashCode() ^ Wgt.z.GetHashCode()\r
654                  ^ Idx.GetHashCode();\r
655         }\r
656 \r
657         public override bool Equals(object obj)\r
658         {\r
659             Vertex  o   = (Vertex)obj;\r
660 \r
661             return Pos.x==o.Pos.x && Pos.y==o.Pos.y && Pos.z==o.Pos.z\r
662                 && Nrm.x==o.Nrm.x && Nrm.y==o.Nrm.y && Nrm.z==o.Nrm.z\r
663                 && Tex.x==o.Tex.x && Tex.y==o.Tex.y && Wgt.w==o.Wgt.w\r
664                 && Wgt.x==o.Wgt.x && Wgt.y==o.Wgt.y && Wgt.z==o.Wgt.z\r
665                 && Idx  ==o.Idx;\r
666         }\r
667     }\r
668 \r
669     /*\r
670     public struct Weights\r
671     {\r
672         public int          Index;\r
673         public float        Weight;\r
674     }\r
675     */\r
676 }\r