source: OniSplit/Level/PhysicsImporter.cs

Last change on this file was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 8.9 KB
Line 
1using System.Collections.Generic;
2using System.Globalization;
3using System.IO;
4using System.Xml;
5
6namespace Oni.Level
7{
8 using Akira;
9 using Metadata;
10 using Motoko;
11 using Physics;
12 using Xml;
13
14 partial class LevelImporter
15 {
16 private void ReadPhysics(XmlReader xml, string basePath)
17 {
18 if (xml.SkipEmpty())
19 return;
20
21 xml.ReadStartElement("Physics");
22
23 while (xml.IsStartElement())
24 ReadObjectSetup(xml, basePath);
25
26 xml.ReadEndElement();
27 }
28
29 private void ReadObjectSetup(XmlReader xml, string basePath)
30 {
31 var scriptId = -1;
32 var name = xml.GetAttribute("Name");
33 var position = Vector3.Zero;
34 var rotation = Quaternion.Identity;
35 var scale = 1.0f;
36 var flags = ObjectSetupFlags.None;
37 var physicsType = ObjectPhysicsType.None;
38 var particles = new List<ObjectParticle>();
39 var nodes = new List<ObjectNode>();
40 string geometryName = null;
41 string animationName = null;
42
43 xml.ReadStartElement("Object");
44
45 while (xml.IsStartElement())
46 {
47 switch (xml.LocalName)
48 {
49 case "Name":
50 name = xml.ReadElementContentAsString();
51 break;
52 case "ScriptId":
53 scriptId = xml.ReadElementContentAsInt();
54 break;
55 case "Flags":
56 flags = xml.ReadElementContentAsEnum<ObjectSetupFlags>() & ~ObjectSetupFlags.InUse;
57 break;
58 case "Position":
59 position = xml.ReadElementContentAsVector3();
60 break;
61 case "Rotation":
62 rotation = xml.ReadElementContentAsEulerXYZ();
63 break;
64 case "Scale":
65 scale = xml.ReadElementContentAsFloat();
66 break;
67 case "Physics":
68 physicsType = xml.ReadElementContentAsEnum<ObjectPhysicsType>();
69 break;
70 case "Particles":
71 particles.AddRange(ReadParticles(xml, basePath));
72 break;
73
74 case "Geometry":
75 geometryName = xml.ReadElementContentAsString();
76 if (nodes.Count > 0)
77 {
78 error.WriteLine("Geometry cannot be used together with Import, ignoring");
79 break;
80 }
81 break;
82
83 case "Animation":
84 animationName = xml.ReadElementContentAsString();
85 if (nodes.Count > 0)
86 {
87 error.WriteLine("Animation cannot be used together with Import, ignoring");
88 break;
89 }
90 break;
91
92 case "Import":
93 if (geometryName != null || animationName != null)
94 {
95 error.WriteLine("Import cannot be used together with Geometry and Animation, ignoring");
96 break;
97 }
98 nodes.AddRange(ImportObjectGeometry(xml, basePath));
99 break;
100
101 default:
102 error.WriteLine("Unknown physics object element {0}", xml.LocalName);
103 xml.Skip();
104 break;
105 }
106 }
107
108 xml.ReadEndElement();
109
110 if (geometryName != null)
111 {
112 var m3gm = FindSharedInstance(TemplateTag.M3GM, geometryName, objectLoadContext);
113 var geometry = GeometryDatReader.Read(m3gm);
114 var animation = new ObjectAnimation[0];
115
116 if (animationName != null)
117 {
118 var oban = FindSharedInstance(TemplateTag.OBAN, animationName, objectLoadContext);
119 animation = new[] { ObjectDatReader.ReadAnimation(oban) };
120 }
121
122 nodes.Add(new ObjectNode(new[] { new ObjectGeometry(geometry) }) {
123 FileName = Path.GetFileName(geometryName),
124 Name = m3gm.Name,
125 ScriptId = scriptId,
126 Flags = flags,
127 Animations = animation
128 });
129 }
130
131 for (int i = 0; i < nodes.Count; i++)
132 {
133 var node = nodes[i];
134
135 var setup = new ObjectSetup {
136 Name = node.Name,
137 FileName = node.FileName,
138 ScriptId = scriptId++,
139 Flags = flags,
140 PhysicsType = physicsType,
141 };
142
143 setup.Particles.AddRange(particles);
144
145 setup.Geometries = node.Geometries
146 .Where(n => (n.Flags & GunkFlags.Invisible) == 0)
147 .Select(n => n.Geometry.Name).ToArray();
148
149 foreach (var nodeGeometry in node.Geometries.Where(g => (g.Flags & GunkFlags.Invisible) == 0))
150 {
151 var writer = new DatWriter();
152 GeometryDatWriter.Write(nodeGeometry.Geometry, writer.ImporterFile);
153 writer.Write(outputDirPath);
154 }
155
156 setup.Position = position;
157 setup.Orientation = rotation;
158 setup.Scale = scale;
159 setup.Origin = Matrix.CreateFromQuaternion(setup.Orientation)
160 * Matrix.CreateScale(setup.Scale)
161 * Matrix.CreateTranslation(setup.Position);
162
163 foreach (var animation in node.Animations)
164 {
165 if (nodes.Count > 1)
166 animation.Name += i.ToString("d2", CultureInfo.InvariantCulture);
167
168 if ((animation.Flags & ObjectAnimationFlags.Local) != 0)
169 {
170 //animation.Scale = Matrix.CreateScale(setup.Scale);
171
172 foreach (var key in animation.Keys)
173 {
174 key.Rotation = setup.Orientation * key.Rotation;
175 key.Translation += setup.Position;
176 }
177 }
178
179 if ((animation.Flags & ObjectAnimationFlags.AutoStart) != 0)
180 {
181 setup.Animation = animation;
182 setup.PhysicsType = ObjectPhysicsType.Animated;
183 }
184
185 var writer = new DatWriter();
186 ObjectDatWriter.WriteAnimation(animation, writer);
187 writer.Write(outputDirPath);
188 }
189
190 if (setup.Animation == null && node.Animations.Length > 0)
191 {
192 setup.Animation = node.Animations[0];
193 }
194
195 if (setup.Animation != null)
196 {
197 var frame0 = setup.Animation.Keys[0];
198
199 setup.Scale = frame0.Scale.X;
200 setup.Orientation = frame0.Rotation;
201 setup.Position = frame0.Translation;
202 }
203
204 level.physics.Add(setup);
205 }
206 }
207
208 private IEnumerable<ObjectNode> ImportObjectGeometry(XmlReader xml, string basePath)
209 {
210 var filePath = xml.GetAttribute("Path");
211
212 if (filePath == null)
213 filePath = xml.GetAttribute("Url");
214
215 var scene = LoadScene(Path.Combine(basePath, filePath));
216 var animClips = new List<ObjectAnimationClip>();
217
218 if (!xml.SkipEmpty())
219 {
220 xml.ReadStartElement();
221
222 while (xml.IsStartElement())
223 {
224 switch (xml.LocalName)
225 {
226 case "Animation":
227 animClips.Add(ReadAnimationClip(xml));
228 break;
229
230 default:
231 error.WriteLine("Unknown element {0}", xml.LocalName);
232 xml.Skip();
233 break;
234 }
235 }
236
237 xml.ReadEndElement();
238 }
239
240 var importer = new ObjectDaeImporter(textureImporter, null);
241 importer.Import(scene);
242 return importer.Nodes;
243 }
244 }
245}
Note: See TracBrowser for help on using the repository browser.