Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Collada.cs
浏览该文件的文档.
1using System.Globalization;
2using System.Text;
3using System.Xml;
4using System.Xml.Linq;
6
7namespace Engine.Media {
8 public static class Collada {
9 public struct Vertex : IEquatable<Vertex> {
10 public byte[] Data;
11
12 public int Start;
13
14 public int Count;
15
17
18 public Vertex(byte[] data, int start, int count) {
19 Data = data;
20 Start = start;
21 Count = count;
22 m_hashCode = 0;
23 for (int i = 0; i < Count; i++) {
24 m_hashCode += (7919 * i + 977) * Data[i + Start];
25 }
26 }
27
28 public bool Equals(Vertex other) {
29 if (m_hashCode != other.m_hashCode
30 || Data.Length != other.Data.Length) {
31 return false;
32 }
33 for (int i = 0; i < Count; i++) {
34 if (Data[i + Start] != other.Data[i + other.Start]) {
35 return false;
36 }
37 }
38 return true;
39 }
40
41 public override bool Equals(object obj) => obj is Color && Equals((Color)obj);
42
43 public override int GetHashCode() => m_hashCode;
44 }
45
46 public class ColladaAsset {
47 public readonly float Meter = 1f;
48
49 public ColladaAsset() { }
50
51 public ColladaAsset(XElement node) {
52 XElement xElement = node.Element(ColladaRoot.Namespace + "unit");
53 if (xElement != null) {
54 XAttribute xAttribute = xElement.Attribute("meter");
55 if (xAttribute != null) {
56 Meter = float.Parse(xAttribute.Value, CultureInfo.InvariantCulture);
57 }
58 }
59 }
60
61 public void Save(XElement node) {
62 XElement xElement = CreateElement(node, ColladaRoot.Namespace + "unit");
63 xElement.SetAttributeValue("name", "meter");
64 xElement.SetAttributeValue("meter", Meter.ToString(CultureInfo.InvariantCulture));
65 }
66 }
67
68 public class ColladaRoot {
69 public static readonly XNamespace Namespace = "http://www.collada.org/2005/11/COLLADASchema";
70
71 public readonly Dictionary<string, ColladaNameId> ObjectsById = [];
72
73 public readonly ColladaAsset Asset;
74
75 public readonly List<ColladaLibraryGeometries> LibraryGeometries = [];
76
77 public readonly List<ColladaLibraryVisualScenes> LibraryVisualScenes = [];
78
79 public readonly ColladaScene Scene;
80
81 public ColladaRoot(ModelData modelData) {
82 Asset = new ColladaAsset();
84 foreach (ModelMeshData mesh in modelData.Meshes) {
85 foreach (ModelMeshPartData meshPart in mesh.MeshParts) {
86 LibraryGeometries[0].Geometries.Add(new ColladaGeometry(this, modelData, mesh, meshPart));
87 }
88 }
90 ColladaVisualScene colladaVisualScene = new(this) { ChildNodes = { new ColladaNode(this, modelData, modelData.Bones[0]) } };
91 LibraryVisualScenes[0].VisualScenes.Add(colladaVisualScene);
92 Scene = new ColladaScene { VisualScene = colladaVisualScene };
93 }
94
95 public ColladaRoot(XElement node) {
96 Asset = new ColladaAsset(node.Element(Namespace + "asset"));
97 foreach (XElement item in node.Elements(Namespace + "library_geometries")) {
99 }
100 foreach (XElement item2 in node.Elements(Namespace + "library_visual_scenes")) {
102 }
103 Scene = new ColladaScene(this, node.Element(Namespace + "scene"));
104 }
105
106 public void Save(ModelData modelData) {
107 if (Scene.VisualScene.ChildNodes.Count > 1) {
108 ModelBoneData modelBoneData = new();
109 modelData.Bones.Add(modelBoneData);
110 modelBoneData.ParentBoneIndex = -1;
111 modelBoneData.Name = "EngineRoot";
112 modelBoneData.Transform = Matrix.Identity;
113 foreach (ColladaNode childNode in Scene.VisualScene.ChildNodes) {
114 childNode.Save(modelData, modelBoneData, Matrix.CreateScale(Asset.Meter), new ModelBoneData());
115 }
116 }
117 else {
118 foreach (ColladaNode childNode2 in Scene.VisualScene.ChildNodes) {
119 childNode2.Save(modelData, null, Matrix.CreateScale(Asset.Meter), new ModelBoneData());
120 }
121 }
122 foreach (ModelBuffersData buffer in modelData.Buffers) {
123 IndexVertices(buffer.VertexDeclaration.VertexStride, buffer.Vertices, out buffer.Vertices, out buffer.Indices);
124 }
125 }
126
127 public void Save(XElement node) {
128 node.SetAttributeValue("version", "1.4.1");
129 Asset.Save(CreateElement(node, Namespace + "asset"));
130 foreach (ColladaLibraryGeometries libraryGeometry in LibraryGeometries) {
131 libraryGeometry.Save(CreateElement(node, Namespace + "library_geometries"));
132 }
133 foreach (ColladaLibraryVisualScenes libraryVisualScene in LibraryVisualScenes) {
134 libraryVisualScene.Save(CreateElement(node, Namespace + "library_visual_scenes"));
135 }
136 Scene.Save(CreateElement(node, Namespace + "scene"));
137 }
138 }
139
140 public class ColladaNameId {
141 public string Id;
142
143 public string Name;
144
145 public ColladaNameId(ColladaRoot colladaRoot, string id, string name) {
146 Id = id;
147 Name = name;
148 colladaRoot.ObjectsById.Add(Id, this);
149 }
150
151 public ColladaNameId(ColladaRoot colladaRoot, string id) : this(colladaRoot, id, id) { }
152
153 public ColladaNameId(ColladaRoot collada, XElement node, string idPostfix = "") {
154 XAttribute xAttribute = node.Attribute("id");
155 if (xAttribute != null) {
156 Id = xAttribute.Value + idPostfix;
157 collada.ObjectsById.Add(Id, this);
158 }
159 XAttribute xAttribute2 = node.Attribute("name");
160 if (xAttribute2 != null) {
161 Name = xAttribute2.Value;
162 }
163 }
164
165 public virtual void Save(XElement node) {
166 node.SetAttributeValue("id", Id);
167 node.SetAttributeValue("name", Name);
168 }
169 }
170
172 public List<ColladaVisualScene> VisualScenes = [];
173
175
176 public ColladaLibraryVisualScenes(ColladaRoot collada, XElement node) {
177 foreach (XElement item in node.Elements(ColladaRoot.Namespace + "visual_scene")) {
178 VisualScenes.Add(new ColladaVisualScene(collada, item));
179 }
180 }
181
182 public void Save(XElement node) {
183 foreach (ColladaVisualScene visualScene in VisualScenes) {
184 visualScene.Save(CreateElement(node, ColladaRoot.Namespace + "visual_scene"));
185 }
186 }
187 }
188
190 public List<ColladaGeometry> Geometries = [];
191
193
194 public ColladaLibraryGeometries(ColladaRoot collada, XElement node) {
195 foreach (XElement item in node.Elements(ColladaRoot.Namespace + "geometry")) {
196 Geometries.Add(new ColladaGeometry(collada, item));
197 }
198 }
199
200 public void Save(XElement node) {
201 foreach (ColladaGeometry geometry in Geometries) {
202 geometry.Save(CreateElement(node, ColladaRoot.Namespace + "geometry"));
203 }
204 }
205 }
206
207 public class ColladaScene {
209
210 public ColladaScene() { }
211
212 public ColladaScene(ColladaRoot collada, XElement node) {
213 XElement xElement = node.Element(ColladaRoot.Namespace + "instance_visual_scene");
214 VisualScene = (ColladaVisualScene)collada.ObjectsById[$"{xElement.Attribute("url").Value.Substring(1)}-ColladaVisualScene"];
215 }
216
217 public void Save(XElement node) {
218 CreateElement(node, ColladaRoot.Namespace + "instance_visual_scene").SetAttributeValue("url", $"#{VisualScene.Id}");
219 }
220 }
221
223 public List<ColladaNode> ChildNodes = [];
224
225 public ColladaVisualScene(ColladaRoot colladaRoot) : base(colladaRoot, "Scene") { }
226
227 public ColladaVisualScene(ColladaRoot collada, XElement node) : base(collada, node, "-ColladaVisualScene") {
228 foreach (XElement item in node.Elements(ColladaRoot.Namespace + "node")) {
229 ChildNodes.Add(new ColladaNode(collada, item));
230 }
231 }
232
233 public override void Save(XElement node) {
234 base.Save(node);
235 foreach (ColladaNode childNode in ChildNodes) {
236 childNode.Save(CreateElement(node, ColladaRoot.Namespace + "node"));
237 }
238 }
239 }
240
241 public class ColladaNode : ColladaNameId {
243
244 public List<ColladaNode> Children = [];
245
246 public List<ColladaGeometry> Geometries = [];
247
248 public ColladaNode(ColladaRoot colladaRoot, ModelData modelData, ModelBoneData modelBoneData) : base(colladaRoot, modelBoneData.Name) {
249 Transform = modelBoneData.Transform;
250 int index = modelData.Bones.IndexOf(modelBoneData);
251 foreach (ModelBoneData item in modelData.Bones.Where(b => b.ParentBoneIndex == index)) {
252 Children.Add(new ColladaNode(colladaRoot, modelData, item));
253 }
254 foreach (ModelMeshData item2 in modelData.Meshes.Where(m => m.ParentBoneIndex == index)) {
255 foreach (ModelMeshPartData meshPart in item2.MeshParts) {
256 string key = ColladaGeometry.CreateId(item2, meshPart);
257 Geometries.Add((ColladaGeometry)colladaRoot.ObjectsById[key]);
258 }
259 }
260 }
261
262 public ColladaNode(ColladaRoot collada, XElement node) : base(collada, node) {
263 foreach (XElement item in node.Elements()) {
264 if (item.Name == ColladaRoot.Namespace + "matrix") {
265 float[] array = (from s in item.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
266 select float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
267 Transform = Matrix.Transpose(
268 new Matrix(
269 array[0],
270 array[1],
271 array[2],
272 array[3],
273 array[4],
274 array[5],
275 array[6],
276 array[7],
277 array[8],
278 array[9],
279 array[10],
280 array[11],
281 array[12],
282 array[13],
283 array[14],
284 array[15]
285 )
286 )
287 * Transform;
288 }
289 else if (item.Name == ColladaRoot.Namespace + "translate") {
290 float[] array2 = (from s in item.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
291 select float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
292 Transform = Matrix.CreateTranslation(array2[0], array2[1], array2[2]) * Transform;
293 }
294 else if (item.Name == ColladaRoot.Namespace + "rotate") {
295 float[] array3 = (from s in item.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
296 select float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
297 Transform = Matrix.CreateFromAxisAngle(new Vector3(array3[0], array3[1], array3[2]), MathUtils.DegToRad(array3[3]))
298 * Transform;
299 }
300 else if (item.Name == ColladaRoot.Namespace + "scale") {
301 float[] array4 = (from s in item.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
302 select float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
303 Transform = Matrix.CreateScale(array4[0], array4[1], array4[2]) * Transform;
304 }
305 }
306 foreach (XElement item2 in node.Elements(ColladaRoot.Namespace + "node")) {
307 Children.Add(new ColladaNode(collada, item2));
308 }
309 foreach (XElement item3 in node.Elements(ColladaRoot.Namespace + "instance_geometry")) {
310 Geometries.Add((ColladaGeometry)collada.ObjectsById[item3.Attribute("url").Value.Substring(1)]);
311 }
312 }
313
314 public void Save(ModelData modelData, ModelBoneData parentModelBoneData, Matrix transform, ModelBoneData modelBoneData) {
315 modelData.Bones.Add(modelBoneData);
316 modelBoneData.ParentBoneIndex = parentModelBoneData != null ? modelData.Bones.IndexOf(parentModelBoneData) : -1;
317 modelBoneData.Name = Name;
318 modelBoneData.Transform = Transform * transform;
319 foreach (ColladaNode child in Children) {
320 child.Save(modelData, modelBoneData, Matrix.Identity, new ModelBoneData());
321 }
322 foreach (ColladaGeometry geometry in Geometries) {
323 geometry.Mesh.Save(modelData, modelBoneData, new ModelMeshData());
324 }
325 }
326
327 public override void Save(XElement node) {
328 base.Save(node);
329 XElement xElement = CreateElement(node, ColladaRoot.Namespace + "matrix");
331 xElement.Value = string.Join(
332 " ",
333 matrix.M11,
334 matrix.M12,
335 matrix.M13,
336 matrix.M14,
337 matrix.M21,
338 matrix.M22,
339 matrix.M23,
340 matrix.M24,
341 matrix.M31,
342 matrix.M32,
343 matrix.M33,
344 matrix.M34,
345 matrix.M41,
346 matrix.M42,
347 matrix.M43,
348 matrix.M44
349 );
350 foreach (ColladaNode child in Children) {
351 child.Save(CreateElement(node, ColladaRoot.Namespace + "node"));
352 }
353 foreach (ColladaGeometry geometry in Geometries) {
354 XElement xElement2 = CreateElement(node, ColladaRoot.Namespace + "instance_geometry");
355 xElement2.SetAttributeValue("url", $"#{geometry.Id}");
356 xElement2.SetAttributeValue("name", Name);
357 }
358 }
359 }
360
363
364 public static string CreateId(ModelMeshData modelMeshData, ModelMeshPartData modelMeshPartData) =>
365 $"{modelMeshData.Name}-part{modelMeshData.MeshParts.IndexOf(modelMeshPartData).ToString(CultureInfo.InvariantCulture)}";
366
367 public ColladaGeometry(ColladaRoot colladaRoot, ModelData modelData, ModelMeshData modelMeshData, ModelMeshPartData modelMeshPartData) :
368 base(colladaRoot, CreateId(modelMeshData, modelMeshPartData), null) =>
369 Mesh = new ColladaMesh(colladaRoot, this, modelData, modelMeshPartData);
370
371 public ColladaGeometry(ColladaRoot collada, XElement node) : base(collada, node) {
372 XElement xElement = node.Element(ColladaRoot.Namespace + "mesh");
373 if (xElement != null) {
374 Mesh = new ColladaMesh(collada, xElement);
375 }
376 }
377
378 public override void Save(XElement node) {
379 base.Save(node);
380 if (Mesh != null) {
381 Mesh.Save(CreateElement(node, ColladaRoot.Namespace + "mesh"));
382 }
383 }
384 }
385
386 public class ColladaMesh {
387 public List<ColladaSource> Sources = [];
388
390
391 public List<ColladaPolygons> Polygons = [];
392
393 public unsafe ColladaMesh(ColladaRoot colladaRoot,
394 ColladaGeometry colladaGeometry,
395 ModelData modelData,
396 ModelMeshPartData modelMeshPartData) {
397 Polygons.Add(new ColladaPolygons());
398 ModelBuffersData modelBuffersData = modelData.Buffers[modelMeshPartData.BuffersDataIndex];
399 VertexDeclaration vertexDeclaration = modelBuffersData.VertexDeclaration;
400 ReadOnlyList<VertexElement> vertexElements = vertexDeclaration.VertexElements;
401 fixed (byte* ptr = &modelBuffersData.Indices[0]) {
402 fixed (byte* ptr2 = &modelBuffersData.Vertices[0]) {
403 Dictionary<ushort, ushort> dictionary = new();
404 for (int i = 0; i < modelMeshPartData.IndicesCount; i++) {
405 int num = i % 3 == 0 ? i :
406 i % 3 != 1 ? i - 1 : i + 1;
407 ushort key = *(ushort*)(ptr + (num + modelMeshPartData.StartIndex) * (nint)2);
408 if (!dictionary.TryGetValue(key, out ushort value)) {
409 value = (ushort)dictionary.Count;
410 dictionary.Add(key, value);
411 }
412 for (int j = 0; j < vertexElements.Count; j++) {
413 Polygons[0].P.Add(value);
414 }
415 }
416 foreach (VertexElement item in vertexElements) {
417 ColladaSource colladaSource = new(colladaRoot, $"{colladaGeometry.Id}-{item.Semantic}");
418 ColladaFloatArray colladaFloatArray = new(colladaRoot, $"{colladaSource.Id}-array");
419 ColladaAccessor colladaAccessor = new() { Source = colladaFloatArray };
420 Sources.Add(colladaSource);
421 colladaSource.FloatArray = colladaFloatArray;
422 colladaSource.Accessor = colladaAccessor;
423 if (item.SemanticName == "POSITION") {
424 colladaAccessor.Stride = 3;
425 colladaFloatArray.Array = new float[3 * dictionary.Count];
426 foreach (KeyValuePair<ushort, ushort> item2 in dictionary) {
427 int num2 = item2.Key * vertexDeclaration.VertexStride + item.Offset;
428 colladaFloatArray.Array[3 * item2.Value] = *(float*)(ptr2 + num2);
429 colladaFloatArray.Array[3 * item2.Value + 1] = *(float*)(ptr2 + num2 + 4);
430 colladaFloatArray.Array[3 * item2.Value + 2] = *(float*)(ptr2 + num2 + 2 * (nint)4);
431 }
432 Vertices = new ColladaVertices(colladaRoot, colladaSource) { Semantic = item.SemanticName, Source = colladaSource };
433 }
434 else if (item.SemanticName == "NORMAL") {
435 colladaAccessor.Stride = 3;
436 colladaFloatArray.Array = new float[3 * dictionary.Count];
437 foreach (KeyValuePair<ushort, ushort> item3 in dictionary) {
438 int num3 = item3.Key * vertexDeclaration.VertexStride + item.Offset;
439 colladaFloatArray.Array[3 * item3.Value] = *(float*)(ptr2 + num3);
440 colladaFloatArray.Array[3 * item3.Value + 1] = *(float*)(ptr2 + num3 + 4);
441 colladaFloatArray.Array[3 * item3.Value + 2] = *(float*)(ptr2 + num3 + 2 * (nint)4);
442 }
443 }
444 else if (item.SemanticName == "TEXCOORD") {
445 colladaAccessor.Stride = 2;
446 colladaFloatArray.Array = new float[2 * dictionary.Count];
447 foreach (KeyValuePair<ushort, ushort> item4 in dictionary) {
448 int num4 = item4.Key * vertexDeclaration.VertexStride + item.Offset;
449 colladaFloatArray.Array[2 * item4.Value] = *(float*)(ptr2 + num4);
450 colladaFloatArray.Array[2 * item4.Value + 1] = *(float*)(ptr2 + num4 + 4);
451 }
452 }
453 else if (item.SemanticName == "COLOR") {
454 colladaAccessor.Stride = 4;
455 colladaFloatArray.Array = new float[4 * dictionary.Count];
456 foreach (KeyValuePair<ushort, ushort> item5 in dictionary) {
457 int num5 = item5.Key * vertexDeclaration.VertexStride + item.Offset;
458 colladaFloatArray.Array[4 * item5.Value] = ptr2[num5] / 255f;
459 colladaFloatArray.Array[4 * item5.Value + 1] = (ptr2 + num5)[1] / 255f;
460 colladaFloatArray.Array[4 * item5.Value + 2] = (ptr2 + num5)[2] / 255f;
461 colladaFloatArray.Array[4 * item5.Value + 3] = (ptr2 + num5)[3] / 255f;
462 }
463 }
464 Polygons[0]
465 .Inputs.Add(
466 new ColladaInput {
467 Semantic = item.SemanticName == "POSITION" ? "VERTEX" : item.SemanticName,
468 Set = item.SemanticIndex,
469 Offset = vertexElements.IndexOf(item),
470 Source = colladaSource,
471 Vertices = item.SemanticName == "POSITION" ? Vertices : null
472 }
473 );
474 }
475 }
476 }
477 }
478
479 public ColladaMesh(ColladaRoot collada, XElement node) {
480 foreach (XElement item in node.Elements(ColladaRoot.Namespace + "source")) {
481 Sources.Add(new ColladaSource(collada, item));
482 }
483 XElement node2 = node.Element(ColladaRoot.Namespace + "vertices");
484 Vertices = new ColladaVertices(collada, node2);
485 foreach (XElement item2 in node.Elements(ColladaRoot.Namespace + "polygons")
486 .Concat(node.Elements(ColladaRoot.Namespace + "polylist"))
487 .Concat(node.Elements(ColladaRoot.Namespace + "triangles"))) {
488 Polygons.Add(new ColladaPolygons(collada, item2));
489 }
490 }
491
492 public void Save(ModelData modelData, ModelBoneData parentBone, ModelMeshData modelMeshData) {
493 modelData.Meshes.Add(modelMeshData);
494 modelMeshData.Name = parentBone.Name;
495 modelMeshData.ParentBoneIndex = modelData.Bones.IndexOf(parentBone);
496 foreach (ColladaPolygons polygon in Polygons) {
497 polygon.Save(modelData, modelMeshData, new ModelMeshPartData());
498 }
499 }
500
501 public void Save(XElement node) {
502 foreach (ColladaSource source in Sources) {
503 source.Save(CreateElement(node, ColladaRoot.Namespace + "source"));
504 }
505 Vertices.Save(CreateElement(node, ColladaRoot.Namespace + "vertices"));
506 foreach (ColladaPolygons polygon in Polygons) {
507 polygon.Save(CreateElement(node, ColladaRoot.Namespace + "triangles"));
508 }
509 }
510 }
511
514
516
517 public ColladaSource(ColladaRoot colladaRoot, string id) : base(colladaRoot, id, null) { }
518
519 public ColladaSource(ColladaRoot collada, XElement node) : base(collada, node) {
520 XElement xElement = node.Element(ColladaRoot.Namespace + "float_array");
521 if (xElement != null) {
522 FloatArray = new ColladaFloatArray(collada, xElement);
523 }
524 XElement xElement2 = node.Element(ColladaRoot.Namespace + "technique_common");
525 if (xElement2 != null) {
526 XElement xElement3 = xElement2.Element(ColladaRoot.Namespace + "accessor");
527 if (xElement3 != null) {
528 Accessor = new ColladaAccessor(collada, xElement3);
529 }
530 }
531 }
532
533 public override void Save(XElement node) {
534 base.Save(node);
535 if (FloatArray != null) {
536 FloatArray.Save(CreateElement(node, ColladaRoot.Namespace + "float_array"));
537 }
538 if (Accessor != null) {
539 XElement parent = CreateElement(node, ColladaRoot.Namespace + "technique_common");
540 Accessor.Save(CreateElement(parent, ColladaRoot.Namespace + "accessor"));
541 }
542 }
543 }
544
546 public float[] Array;
547
548 public ColladaFloatArray(ColladaRoot colladaRoot, string id) : base(colladaRoot, id, null) { }
549
550 public ColladaFloatArray(ColladaRoot collada, XElement node) : base(collada, node) =>
551 Array = (from s in node.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
552 select float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
553
554 public override void Save(XElement node) {
555 base.Save(node);
556 node.SetAttributeValue("count", Array.Length);
557 node.Value = string.Join(" ", Array.Select(f => f.ToString(CultureInfo.InvariantCulture)));
558 }
559 }
560
561 public class ColladaAccessor {
563
564 public int Offset;
565
566 public int Stride = 1;
567
568 public ColladaAccessor() { }
569
570 public ColladaAccessor(ColladaRoot collada, XElement node) {
571 Source = (ColladaFloatArray)collada.ObjectsById[node.Attribute("source").Value.Substring(1)];
572 XAttribute xAttribute = node.Attribute("offset");
573 if (xAttribute != null) {
574 Offset = int.Parse(xAttribute.Value, CultureInfo.InvariantCulture);
575 }
576 XAttribute xAttribute2 = node.Attribute("stride");
577 if (xAttribute2 != null) {
578 Stride = int.Parse(xAttribute2.Value, CultureInfo.InvariantCulture);
579 }
580 }
581
582 public void Save(XElement node) {
583 node.SetAttributeValue("source", $"#{Source.Id}");
584 node.SetAttributeValue("offset", Offset.ToString(CultureInfo.InvariantCulture));
585 node.SetAttributeValue("count", (Source.Array.Length / Stride).ToString(CultureInfo.InvariantCulture));
586 node.SetAttributeValue("stride", Stride.ToString(CultureInfo.InvariantCulture));
587 for (int i = 0; i < Stride; i++) {
588 CreateElement(node, ColladaRoot.Namespace + "param").SetAttributeValue("type", "float");
589 }
590 }
591 }
592
594 public string Semantic;
595
597
598 public ColladaVertices(ColladaRoot colladaRoot, ColladaSource colladaSource) : base(colladaRoot, $"{colladaSource.Id}-vertices", null) { }
599
600 public ColladaVertices(ColladaRoot collada, XElement node) : base(collada, node) {
601 XElement xElement = node.Element(ColladaRoot.Namespace + "input");
602 Semantic = xElement.Attribute("semantic").Value;
603 Source = (ColladaSource)collada.ObjectsById[xElement.Attribute("source").Value.Substring(1)];
604 }
605
606 public override void Save(XElement node) {
607 base.Save(node);
608 XElement xElement = CreateElement(node, ColladaRoot.Namespace + "input");
609 xElement.SetAttributeValue("semantic", Semantic);
610 xElement.SetAttributeValue("source", $"#{Source.Id}");
611 }
612 }
613
614 public class ColladaPolygons {
615 public List<ColladaInput> Inputs = [];
616
617 public List<int> VCount = [];
618
619 public List<int> P = [];
620
621 public ColladaPolygons() { }
622
623 public ColladaPolygons(ColladaRoot collada, XElement node) {
624 foreach (XElement item in node.Elements(ColladaRoot.Namespace + "input")) {
625 Inputs.Add(new ColladaInput(collada, item));
626 }
627 foreach (XElement item2 in node.Elements(ColladaRoot.Namespace + "vcount")) {
628 VCount.AddRange(
629 from s in item2.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
630 select int.Parse(s, CultureInfo.InvariantCulture)
631 );
632 }
633 foreach (XElement item3 in node.Elements(ColladaRoot.Namespace + "p")) {
634 P.AddRange(
635 from s in item3.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
636 select int.Parse(s, CultureInfo.InvariantCulture)
637 );
638 }
639 }
640
641 public void Save(ModelData modelData, ModelMeshData modelMeshData, ModelMeshPartData modelMeshPartData) {
642 int num = 0;
643 Dictionary<VertexElement, ColladaInput> dictionary = new();
644 foreach (ColladaInput input in Inputs) {
645 string text = input.Set == 0 ? string.Empty : input.Set.ToString(CultureInfo.InvariantCulture);
646 if (input.Semantic == "POSITION") {
647 dictionary[new VertexElement(num, VertexElementFormat.Vector3, $"POSITION{text}")] = input;
648 num += 12;
649 }
650 else if (input.Semantic == "NORMAL") {
651 dictionary[new VertexElement(num, VertexElementFormat.Vector3, $"NORMAL{text}")] = input;
652 num += 12;
653 }
654 else if (input.Semantic == "TEXCOORD") {
655 dictionary[new VertexElement(num, VertexElementFormat.Vector2, $"TEXCOORD{text}")] = input;
656 num += 8;
657 }
658 else if (input.Semantic == "COLOR") {
659 dictionary[new VertexElement(num, VertexElementFormat.NormalizedByte4, $"COLOR{text}")] = input;
660 num += 4;
661 }
662 }
663 VertexDeclaration vertexDeclaration = new(dictionary.Keys.ToArray());
664 ModelBuffersData modelBuffersData = modelData.Buffers.FirstOrDefault(vd => vd.VertexDeclaration == vertexDeclaration);
665 if (modelBuffersData == null) {
666 modelBuffersData = new ModelBuffersData();
667 modelData.Buffers.Add(modelBuffersData);
668 modelBuffersData.VertexDeclaration = vertexDeclaration;
669 }
670 modelMeshPartData.BuffersDataIndex = modelData.Buffers.IndexOf(modelBuffersData);
671 int num2 = P.Count / Inputs.Count;
672 List<int> list = new();
673 if (VCount.Count == 0) {
674 int num3 = 0;
675 for (int i = 0; i < num2 / 3; i++) {
676 list.Add(num3);
677 list.Add(num3 + 2);
678 list.Add(num3 + 1);
679 num3 += 3;
680 }
681 }
682 else {
683 int num4 = 0;
684 using List<int>.Enumerator enumerator2 = VCount.GetEnumerator();
685 while (enumerator2.MoveNext()) {
686 switch (enumerator2.Current) {
687 case 3:
688 list.Add(num4);
689 list.Add(num4 + 2);
690 list.Add(num4 + 1);
691 num4 += 3;
692 break;
693 case 4:
694 list.Add(num4);
695 list.Add(num4 + 2);
696 list.Add(num4 + 1);
697 list.Add(num4 + 2);
698 list.Add(num4);
699 list.Add(num4 + 3);
700 num4 += 4;
701 break;
702 default: throw new NotSupportedException("Collada polygons with less than 3 or more than 4 vertices are not supported.");
703 }
704 }
705 }
706 int vertexStride = modelBuffersData.VertexDeclaration.VertexStride;
707 int num5 = modelBuffersData.Vertices.Length;
708 modelBuffersData.Vertices = ExtendArray(modelBuffersData.Vertices, list.Count * vertexStride);
709 using (BinaryWriter binaryWriter = new(new MemoryStream(modelBuffersData.Vertices, num5, list.Count * vertexStride))) {
710 bool flag = false;
711 foreach (KeyValuePair<VertexElement, ColladaInput> item in dictionary) {
712 VertexElement key = item.Key;
713 ColladaInput value = item.Value;
714 if (key.Semantic.StartsWith("POSITION")) {
715 for (int j = 0; j < list.Count; j++) {
716 float[] array = value.Source.Accessor.Source.Array;
717 int offset = value.Source.Accessor.Offset;
718 int stride = value.Source.Accessor.Stride;
719 int num6 = P[list[j] * Inputs.Count + value.Offset];
720 binaryWriter.BaseStream.Position = j * vertexStride + key.Offset;
721 float num7 = array[offset + stride * num6];
722 float num8 = array[offset + stride * num6 + 1];
723 float num9 = array[offset + stride * num6 + 2];
724 modelMeshPartData.BoundingBox = flag
725 ? BoundingBox.Union(modelMeshPartData.BoundingBox, new Vector3(num7, num8, num9))
726 : new BoundingBox(num7, num8, num9, num7, num8, num9);
727 flag = true;
728 binaryWriter.Write(num7);
729 binaryWriter.Write(num8);
730 binaryWriter.Write(num9);
731 }
732 }
733 else if (key.Semantic.StartsWith("NORMAL")) {
734 for (int k = 0; k < list.Count; k++) {
735 float[] array2 = value.Source.Accessor.Source.Array;
736 int offset2 = value.Source.Accessor.Offset;
737 int stride2 = value.Source.Accessor.Stride;
738 int num10 = P[list[k] * Inputs.Count + value.Offset];
739 binaryWriter.BaseStream.Position = k * vertexStride + key.Offset;
740 float num11 = array2[offset2 + stride2 * num10];
741 float num12 = array2[offset2 + stride2 * num10 + 1];
742 float num13 = array2[offset2 + stride2 * num10 + 2];
743 float num14 = 1f / MathF.Sqrt(num11 * num11 + num12 * num12 + num13 * num13);
744 binaryWriter.Write(num14 * num11);
745 binaryWriter.Write(num14 * num12);
746 binaryWriter.Write(num14 * num13);
747 }
748 }
749 else if (key.Semantic.StartsWith("TEXCOORD")) {
750 for (int l = 0; l < list.Count; l++) {
751 float[] array3 = value.Source.Accessor.Source.Array;
752 int offset3 = value.Source.Accessor.Offset;
753 int stride3 = value.Source.Accessor.Stride;
754 int num15 = P[list[l] * Inputs.Count + value.Offset];
755 binaryWriter.BaseStream.Position = l * vertexStride + key.Offset;
756 binaryWriter.Write(array3[offset3 + stride3 * num15]);
757 binaryWriter.Write(1f - array3[offset3 + stride3 * num15 + 1]);
758 }
759 }
760 else {
761 if (!key.Semantic.StartsWith("COLOR")) {
762 throw new Exception();
763 }
764 for (int m = 0; m < list.Count; m++) {
765 float[] array4 = value.Source.Accessor.Source.Array;
766 int offset4 = value.Source.Accessor.Offset;
767 int stride4 = value.Source.Accessor.Stride;
768 int num16 = P[list[m] * Inputs.Count + value.Offset];
769 binaryWriter.BaseStream.Position = m * vertexStride + key.Offset;
770 binaryWriter.Write(
771 new Color(
772 array4[offset4 + stride4 * num16],
773 array4[offset4 + stride4 * num16 + 1],
774 array4[offset4 + stride4 * num16 + 2],
775 array4[offset4 + stride4 * num16 + 3]
776 ).PackedValue
777 );
778 }
779 }
780 }
781 }
782 modelMeshPartData.StartIndex = num5 / vertexStride;
783 modelMeshPartData.IndicesCount = list.Count;
784 modelMeshData.MeshParts.Add(modelMeshPartData);
785 modelMeshData.BoundingBox = modelMeshData.MeshParts.Count > 1
786 ? BoundingBox.Union(modelMeshData.BoundingBox, modelMeshPartData.BoundingBox)
787 : modelMeshPartData.BoundingBox;
788 }
789
790 public void Save(XElement node) {
791 node.SetAttributeValue("count", P.Count / Inputs.Count / 3);
792 foreach (ColladaInput input in Inputs) {
793 input.Save(CreateElement(node, ColladaRoot.Namespace + "input"));
794 }
795 CreateElement(node, ColladaRoot.Namespace + "p").Value = string.Join(
796 " ",
797 P.Select(n => n.ToString(CultureInfo.InvariantCulture)).ToArray()
798 );
799 }
800 }
801
802 public class ColladaInput {
803 public int Offset;
804
805 public string Semantic;
806
807 public int Set;
808
810
812
813 public ColladaInput() { }
814
815 public ColladaInput(ColladaRoot collada, XElement node) {
816 Offset = int.Parse(node.Attribute("offset").Value, CultureInfo.InvariantCulture);
817 Semantic = node.Attribute("semantic").Value;
818 XAttribute xAttribute = node.Attribute("set");
819 if (xAttribute != null) {
820 Set = int.Parse(xAttribute.Value, CultureInfo.InvariantCulture);
821 }
822 ColladaNameId colladaNameId = collada.ObjectsById[node.Attribute("source").Value.Substring(1)];
823 if (colladaNameId is ColladaVertices) {
824 ColladaVertices colladaVertices = (ColladaVertices)colladaNameId;
825 Source = colladaVertices.Source;
826 Semantic = colladaVertices.Semantic;
827 }
828 else {
829 Source = (ColladaSource)colladaNameId;
830 }
831 }
832
833 public void Save(XElement node) {
834 node.SetAttributeValue("semantic", Semantic);
835 if (Set != 0) {
836 node.SetAttributeValue("set", Set.ToString(CultureInfo.InvariantCulture));
837 }
838 if (Vertices != null) {
839 node.SetAttributeValue("source", $"#{Vertices.Id}");
840 }
841 else {
842 node.SetAttributeValue("source", $"#{Source.Id}");
843 }
844 node.SetAttributeValue("offset", Offset.ToString(CultureInfo.InvariantCulture));
845 }
846 }
847
848 public static bool IsColladaStream(Stream stream) {
849 ArgumentNullException.ThrowIfNull(stream);
850 bool result = false;
851 long position = stream.Position;
852 try {
853 XmlReader xmlReader = XmlReader.Create(stream, new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true });
854 while (xmlReader.Read()) {
855 if (xmlReader.NodeType == XmlNodeType.Element) {
856 if (xmlReader.LocalName == "COLLADA") {
857 result = true;
858 }
859 break;
860 }
861 }
862 }
863 catch (XmlException) { }
864 stream.Position = position;
865 return result;
866 }
867
868 public static ModelData Load(Stream stream) {
869 ColladaRoot colladaRoot = new(XElement.Load(stream));
870 ModelData modelData = new();
871 colladaRoot.Save(modelData);
872 return modelData;
873 }
874
875 public static void Save(ModelData modelData, Stream stream) {
876 ColladaRoot colladaRoot = new(modelData);
877 XElement xElement = CreateElement(null, ColladaRoot.Namespace + "COLLADA");
878 colladaRoot.Save(xElement);
879 XmlWriterSettings settings = new() { Indent = true, Encoding = new UTF8Encoding(false) };
880 using XmlWriter writer = XmlWriter.Create(stream, settings);
881 xElement.Save(writer);
882 }
883
884 public static XElement CreateElement(XElement parent, XName name) {
885 XElement xElement = new(name);
886 parent?.Add(xElement);
887 return xElement;
888 }
889
890 public static T[] ExtendArray<T>(T[] array, int extensionLength) {
891 T[] array2 = new T[array.Length + extensionLength];
892 Array.Copy(array, array2, array.Length);
893 return array2;
894 }
895
896 public static void IndexVertices(int vertexStride, byte[] vertices, out byte[] resultVertices, out byte[] resultIndices) {
897 int num = vertices.Length / vertexStride;
898 Dictionary<Vertex, int> dictionary = new();
899 resultIndices = new byte[4 * num];
900 for (int i = 0; i < num; i++) {
901 Vertex key = new(vertices, i * vertexStride, vertexStride);
902 if (!dictionary.TryGetValue(key, out int value)) {
903 value = dictionary.Count;
904 dictionary.Add(key, value);
905 }
906 int index = i * 4;
907 resultIndices[index++] = (byte)value;
908 resultIndices[index++] = (byte)(value >> 8);
909 resultIndices[index++] = (byte)(value >> 16);
910 resultIndices[index] = (byte)(value >> 24);
911 }
912 resultVertices = new byte[dictionary.Count * vertexStride];
913 foreach (KeyValuePair<Vertex, int> item in dictionary) {
914 Vertex key2 = item.Key;
915 int value2 = item.Value;
916 Array.Copy(key2.Data, key2.Start, resultVertices, value2 * vertexStride, key2.Count);
917 }
918 }
919 }
920}
Engine.Color Color
unsafe
定义 Main.cs:15
ReadOnlyList< VertexElement > VertexElements
ColladaAccessor(ColladaRoot collada, XElement node)
ColladaFloatArray(ColladaRoot colladaRoot, string id)
ColladaFloatArray(ColladaRoot collada, XElement node) override void Save(XElement node)
override void Save(XElement node)
static string CreateId(ModelMeshData modelMeshData, ModelMeshPartData modelMeshPartData)
ColladaGeometry(ColladaRoot colladaRoot, ModelData modelData, ModelMeshData modelMeshData, ModelMeshPartData modelMeshPartData) ColladaGeometry(ColladaRoot collada, XElement node)
ColladaInput(ColladaRoot collada, XElement node)
ColladaLibraryGeometries(ColladaRoot collada, XElement node)
ColladaLibraryVisualScenes(ColladaRoot collada, XElement node)
unsafe ColladaMesh(ColladaRoot colladaRoot, ColladaGeometry colladaGeometry, ModelData modelData, ModelMeshPartData modelMeshPartData)
List< ColladaSource > Sources
ColladaMesh(ColladaRoot collada, XElement node)
List< ColladaPolygons > Polygons
void Save(ModelData modelData, ModelBoneData parentBone, ModelMeshData modelMeshData)
ColladaNameId(ColladaRoot collada, XElement node, string idPostfix="")
ColladaNameId(ColladaRoot colladaRoot, string id, string name)
ColladaNameId(ColladaRoot colladaRoot, string id)
virtual void Save(XElement node)
ColladaNode(ColladaRoot collada, XElement node)
List< ColladaGeometry > Geometries
ColladaNode(ColladaRoot colladaRoot, ModelData modelData, ModelBoneData modelBoneData)
void Save(ModelData modelData, ModelBoneData parentModelBoneData, Matrix transform, ModelBoneData modelBoneData)
override void Save(XElement node)
void Save(ModelData modelData, ModelMeshData modelMeshData, ModelMeshPartData modelMeshPartData)
ColladaPolygons(ColladaRoot collada, XElement node)
readonly List< ColladaLibraryVisualScenes > LibraryVisualScenes
static readonly XNamespace Namespace
ColladaRoot(ModelData modelData)
void Save(ModelData modelData)
readonly List< ColladaLibraryGeometries > LibraryGeometries
readonly Dictionary< string, ColladaNameId > ObjectsById
readonly ColladaAsset Asset
readonly ColladaScene Scene
ColladaScene(ColladaRoot collada, XElement node)
override void Save(XElement node)
ColladaSource(ColladaRoot collada, XElement node)
ColladaSource(ColladaRoot colladaRoot, string id)
override void Save(XElement node)
ColladaVertices(ColladaRoot colladaRoot, ColladaSource colladaSource)
ColladaVertices(ColladaRoot collada, XElement node)
override void Save(XElement node)
ColladaVisualScene(ColladaRoot colladaRoot)
ColladaVisualScene(ColladaRoot collada, XElement node)
static void Save(ModelData modelData, Stream stream)
static ModelData Load(Stream stream)
static void IndexVertices(int vertexStride, byte[] vertices, out byte[] resultVertices, out byte[] resultIndices)
static bool IsColladaStream(Stream stream)
static XElement CreateElement(XElement parent, XName name)
List< ModelBuffersData > Buffers
List< ModelMeshData > Meshes
List< ModelBoneData > Bones
List< ModelMeshPartData > MeshParts
static BoundingBox Union(BoundingBox b1, BoundingBox b2)
static readonly Matrix Identity
static Matrix Transpose(Matrix m)
static Matrix CreateScale(float scale)
bool Equals(Vertex other)
override bool Equals(object obj)
Vertex(byte[] data, int start, int count)