1using System.Globalization;
9 public struct Vertex : IEquatable<Vertex> {
18 public Vertex(
byte[] data,
int start,
int count) {
23 for (
int i = 0; i <
Count; i++) {
30 ||
Data.Length != other.
Data.Length) {
33 for (
int i = 0; i <
Count; i++) {
47 public readonly
float Meter = 1f;
53 if (xElement !=
null) {
54 XAttribute xAttribute = xElement.Attribute(
"meter");
55 if (xAttribute !=
null) {
56 Meter =
float.Parse(xAttribute.Value, CultureInfo.InvariantCulture);
61 public void Save(XElement node) {
63 xElement.SetAttributeValue(
"name",
"meter");
64 xElement.SetAttributeValue(
"meter",
Meter.ToString(CultureInfo.InvariantCulture));
69 public static readonly XNamespace
Namespace =
"http://www.collada.org/2005/11/COLLADASchema";
71 public readonly Dictionary<string, ColladaNameId>
ObjectsById = [];
97 foreach (XElement item
in node.Elements(
Namespace +
"library_geometries")) {
100 foreach (XElement item2
in node.Elements(
Namespace +
"library_visual_scenes")) {
107 if (
Scene.VisualScene.ChildNodes.Count > 1) {
109 modelData.
Bones.Add(modelBoneData);
110 modelBoneData.ParentBoneIndex = -1;
111 modelBoneData.Name =
"EngineRoot";
127 public void Save(XElement node) {
128 node.SetAttributeValue(
"version",
"1.4.1");
154 XAttribute xAttribute = node.Attribute(
"id");
155 if (xAttribute !=
null) {
156 Id = xAttribute.Value + idPostfix;
159 XAttribute xAttribute2 = node.Attribute(
"name");
160 if (xAttribute2 !=
null) {
161 Name = xAttribute2.Value;
165 public virtual void Save(XElement node) {
166 node.SetAttributeValue(
"id",
Id);
167 node.SetAttributeValue(
"name",
Name);
182 public void Save(XElement node) {
200 public void Save(XElement node) {
217 public void Save(XElement node) {
229 ChildNodes.Add(new ColladaNode(collada, item));
233 public override void Save(XElement node) {
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));
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]);
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(
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;
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]))
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;
307 Children.Add(new ColladaNode(collada, item2));
310 Geometries.Add((ColladaGeometry)collada.ObjectsById[item3.Attribute(
"url").Value.Substring(1)]);
315 modelData.
Bones.Add(modelBoneData);
316 modelBoneData.ParentBoneIndex = parentModelBoneData !=
null ? modelData.
Bones.IndexOf(parentModelBoneData) : -1;
317 modelBoneData.Name =
Name;
318 modelBoneData.Transform =
Transform * transform;
327 public override void Save(XElement node) {
331 xElement.Value =
string.Join(
355 xElement2.SetAttributeValue(
"url", $
"#{geometry.Id}");
356 xElement2.SetAttributeValue(
"name",
Name);
365 $
"{modelMeshData.Name}-part{modelMeshData.MeshParts.IndexOf(modelMeshPartData).ToString(CultureInfo.InvariantCulture)}";
368 base(colladaRoot,
CreateId(modelMeshData, modelMeshPartData), null) =>
369 Mesh = new
ColladaMesh(colladaRoot, this, modelData, modelMeshPartData);
373 if (xElement !=
null) {
378 public override void Save(XElement node) {
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);
412 for (
int j = 0; j < vertexElements.
Count; j++) {
417 ColladaSource colladaSource =
new(colladaRoot, $
"{colladaGeometry.Id}-{item.Semantic}");
418 ColladaFloatArray colladaFloatArray =
new(colladaRoot, $
"{colladaSource.Id}-array");
419 ColladaAccessor colladaAccessor =
new() { Source = colladaFloatArray };
421 colladaSource.FloatArray = colladaFloatArray;
422 colladaSource.Accessor = colladaAccessor;
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);
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);
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);
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;
467 Semantic = item.SemanticName ==
"POSITION" ?
"VERTEX" : item.
SemanticName,
469 Offset = vertexElements.IndexOf(item),
470 Source = colladaSource,
493 modelData.
Meshes.Add(modelMeshData);
494 modelMeshData.Name = parentBone.
Name;
495 modelMeshData.ParentBoneIndex = modelData.
Bones.IndexOf(parentBone);
501 public void Save(XElement node) {
521 if (xElement !=
null) {
525 if (xElement2 !=
null) {
527 if (xElement3 !=
null) {
533 public override void Save(XElement node) {
551 Array = (from s in node.Value.Split((char[])null, StringSplitOptions.RemoveEmptyEntries)
552 select float.Parse(s, CultureInfo.InvariantCulture)).ToArray();
554 public override void Save(XElement node) {
556 node.SetAttributeValue(
"count",
Array.Length);
557 node.Value =
string.Join(
" ",
Array.Select(f => f.ToString(CultureInfo.InvariantCulture)));
572 XAttribute xAttribute = node.Attribute(
"offset");
573 if (xAttribute !=
null) {
574 Offset =
int.Parse(xAttribute.Value, CultureInfo.InvariantCulture);
576 XAttribute xAttribute2 = node.Attribute(
"stride");
577 if (xAttribute2 !=
null) {
578 Stride =
int.Parse(xAttribute2.Value, CultureInfo.InvariantCulture);
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++) {
602 Semantic = xElement.Attribute(
"semantic").Value;
606 public override void Save(XElement node) {
609 xElement.SetAttributeValue(
"semantic",
Semantic);
610 xElement.SetAttributeValue(
"source", $
"#{Source.Id}");
619 public List<int>
P = [];
629 from s in item2.Value.Split((
char[])
null, StringSplitOptions.RemoveEmptyEntries)
630 select
int.Parse(s, CultureInfo.InvariantCulture)
635 from s in item3.Value.Split((
char[])
null, StringSplitOptions.RemoveEmptyEntries)
636 select
int.Parse(s, CultureInfo.InvariantCulture)
643 Dictionary<VertexElement, ColladaInput> dictionary =
new();
645 string text = input.Set == 0 ? string.Empty : input.
Set.ToString(CultureInfo.InvariantCulture);
650 else if (input.
Semantic ==
"NORMAL") {
654 else if (input.
Semantic ==
"TEXCOORD") {
658 else if (input.
Semantic ==
"COLOR") {
664 ModelBuffersData modelBuffersData = modelData.Buffers.FirstOrDefault(vd => vd.VertexDeclaration == vertexDeclaration);
665 if (modelBuffersData ==
null) {
667 modelData.Buffers.Add(modelBuffersData);
668 modelBuffersData.VertexDeclaration = vertexDeclaration;
670 modelMeshPartData.BuffersDataIndex = modelData.Buffers.IndexOf(modelBuffersData);
671 int num2 = P.Count /
Inputs.Count;
672 List<int> list =
new();
675 for (
int i = 0; i < num2 / 3; i++) {
684 using List<
int>.Enumerator enumerator2 =
VCount.GetEnumerator();
685 while (enumerator2.MoveNext()) {
686 switch (enumerator2.Current) {
702 default:
throw new NotSupportedException(
"Collada polygons with less than 3 or more than 4 vertices are not supported.");
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))) {
711 foreach (KeyValuePair<VertexElement, ColladaInput> item
in dictionary) {
714 if (key.
Semantic.StartsWith(
"POSITION")) {
715 for (
int j = 0; j < list.Count; j++) {
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
726 :
new BoundingBox(num7, num8, num9, num7, num8, num9);
728 binaryWriter.Write(num7);
729 binaryWriter.Write(num8);
730 binaryWriter.Write(num9);
733 else if (key.
Semantic.StartsWith(
"NORMAL")) {
734 for (
int k = 0; k < list.Count; k++) {
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);
749 else if (key.
Semantic.StartsWith(
"TEXCOORD")) {
750 for (
int l = 0; l < list.Count; l++) {
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]);
761 if (!key.
Semantic.StartsWith(
"COLOR")) {
762 throw new Exception();
764 for (
int m = 0; m < list.Count; m++) {
768 int num16 =
P[list[m] * Inputs.Count + value.
Offset];
769 binaryWriter.BaseStream.Position = m * vertexStride + key.
Offset;
772 array4[offset4 + stride4 * num16],
773 array4[offset4 + stride4 * num16 + 1],
774 array4[offset4 + stride4 * num16 + 2],
775 array4[offset4 + stride4 * num16 + 3]
782 modelMeshPartData.StartIndex = num5 / vertexStride;
783 modelMeshPartData.IndicesCount = list.Count;
784 modelMeshData.
MeshParts.Add(modelMeshPartData);
785 modelMeshData.BoundingBox = modelMeshData.MeshParts.Count > 1
790 public void Save(XElement node) {
791 node.SetAttributeValue(
"count",
P.Count /
Inputs.Count / 3);
797 P.Select(n => n.ToString(CultureInfo.InvariantCulture)).ToArray()
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);
833 public void Save(XElement node) {
834 node.SetAttributeValue(
"semantic",
Semantic);
836 node.SetAttributeValue(
"set",
Set.ToString(CultureInfo.InvariantCulture));
839 node.SetAttributeValue(
"source", $
"#{Vertices.Id}");
842 node.SetAttributeValue(
"source", $
"#{Source.Id}");
844 node.SetAttributeValue(
"offset",
Offset.ToString(CultureInfo.InvariantCulture));
849 ArgumentNullException.ThrowIfNull(stream);
851 long position = stream.Position;
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") {
863 catch (XmlException) { }
864 stream.Position = position;
869 ColladaRoot colladaRoot =
new(XElement.Load(stream));
871 colladaRoot.
Save(modelData);
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);
885 XElement xElement =
new(name);
886 parent?.Add(xElement);
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);
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);
907 resultIndices[index++] = (byte)value;
908 resultIndices[index++] = (byte)(value >> 8);
909 resultIndices[index++] = (byte)(value >> 16);
910 resultIndices[index] = (byte)(value >> 24);
912 resultVertices =
new byte[dictionary.Count * vertexStride];
913 foreach (KeyValuePair<Vertex, int> item
in dictionary) {
915 int value2 = item.Value;
916 Array.Copy(key2.
Data, key2.
Start, resultVertices, value2 * vertexStride, key2.
Count);
ReadOnlyList< VertexElement > VertexElements
static BoundingBox Union(BoundingBox b1, BoundingBox b2)
static readonly Matrix Identity
static Matrix Transpose(Matrix m)
static Matrix CreateScale(float scale)