Decompiled source of glTF Exporter v2.0.1

Mods/glTF-Exporter.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppRUMBLE.CharacterCreation;
using Il2CppRUMBLE.Managers;
using Il2CppRUMBLE.MeshGeneration;
using Il2CppRUMBLE.Players;
using Il2CppRUMBLE.Utilities;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Utils;
using SharpGLTF.Geometry;
using SharpGLTF.Geometry.VertexTypes;
using SharpGLTF.Materials;
using SharpGLTF.Memory;
using SharpGLTF.Schema2;
using SharpGLTF.Transforms;
using UnityEngine;
using glTF_Exporter;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Exporter), "glTF_Exporter", "2.0.1", "blankochan", null)]
[assembly: MelonGame("Buckethead Entertainment", "RUMBLE")]
[assembly: MelonColor(255, 255, 170, 238)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("glTF-Exporter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("glTF-Exporter")]
[assembly: AssemblyTitle("glTF-Exporter")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace glTF_Exporter;

public static class BuildInfo
{
	public const string Name = "glTF_Exporter";

	public const string Author = "blankochan";

	public const string Version = "2.0.1";
}
public static class GeneralExtensions
{
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Vector2 ToNumerics(this Vector2 vec)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		return new Vector2(vec.x, vec.y);
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Vector3 ToNumerics(this Vector3 vec)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(vec.x, vec.y, vec.z);
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Vector4 ToNumerics(this Vector4 vec)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return new Vector4(vec.x, vec.y, vec.z, vec.w);
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Vector4 ToNumerics(this Color32 color)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		return new Vector4((int)color.r, (int)color.g, (int)color.b, (int)color.a);
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public static Matrix4x4 ToNumerics(this Matrix4x4 unityMatrix)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		return new Matrix4x4(unityMatrix.m00, unityMatrix.m10, unityMatrix.m20, unityMatrix.m30, unityMatrix.m01, unityMatrix.m11, unityMatrix.m21, unityMatrix.m31, unityMatrix.m02, unityMatrix.m12, unityMatrix.m22, unityMatrix.m32, unityMatrix.m03, unityMatrix.m13, unityMatrix.m23, unityMatrix.m33);
	}
}
public sealed class Exporter : MelonMod
{
	private readonly WaitForEndOfFrame _frameEnd = new WaitForEndOfFrame();

	internal bool MeshGenerationLocked;

	public override void OnLateInitializeMelon()
	{
		Directory.CreateDirectory(MelonEnvironment.UserDataDirectory + "/glTF_Exporter/");
	}

	internal void StartExport(string username, PlayerVisualData data)
	{
		string text = GenerateFileName(username, data);
		if (File.Exists(MelonEnvironment.UserDataDirectory + "/glTF_Exporter/" + text + ".glb"))
		{
			((MelonBase)this).LoggerInstance.Msg($"Skipping: {username}, Already exists at {MelonEnvironment.UserDataDirectory}/glTF_Exporter/{text}.glb");
		}
		else
		{
			File.Create(MelonEnvironment.UserDataDirectory + "/glTF_Exporter/" + text + ".glb").Close();
			MelonCoroutines.Start(Export_glTF(username));
		}
	}

	private IEnumerator Export_glTF(string publicUsername)
	{
		yield return _frameEnd;
		if (MeshGenerationLocked)
		{
			yield return null;
		}
		MeshGenerationLocked = true;
		GeneratedPlayerVisuals val = ScriptableObjectSingleton<CharacterCreationLookupTable>.instance.GeneratedPlayerVisualsCache[publicUsername];
		MaterialBuilder val2 = new MaterialBuilder("Player Controller");
		ImageBuilder val3 = ImageBuilder.From(new MemoryImage(Il2CppArrayBase<byte>.op_Implicit((Il2CppArrayBase<byte>)(object)ImageConversion.EncodeToPNG(TexDownload(val.GeneratedTexture)))), (string)null);
		val2.WithChannelImage((KnownChannel)3, val3);
		Mesh generatedMesh = val.GeneratedMesh;
		List<Vector2> val4 = new List<Vector2>();
		generatedMesh.GetUVs(0, val4);
		((MelonBase)this).LoggerInstance.Msg("Exporting " + publicUsername);
		ModelRoot obj = ModelRoot.CreateModel();
		Scene val5 = obj.UseScene("Player Character");
		obj.Asset.Copyright = "Copyright 2026 © Buckethead Entertainment. All rights are reserved.";
		obj.Asset.Generator = "glTF_Exporter 2.0.1 Using SharpGLTF 1.0.4";
		MeshBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4> val6 = new MeshBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4>(val.Data.ToPlayfabDataString());
		PopulateMesh(generatedMesh.triangles, generatedMesh.vertices, generatedMesh.normals, generatedMesh.colors32, val6, val2, generatedMesh.boneWeights, Il2CppArrayBase<Vector2>.op_Implicit(val4.ToArray()));
		Mesh val7 = Toolkit.CreateMesh(obj, (IMeshBuilder<MaterialBuilder>)(object)val6);
		((MeshBuilder<MaterialBuilder, VertexPositionNormal, VertexColor1Texture1, VertexJoints4>)(object)val6).Validate();
		Node val8 = val5.CreateNode("CC_Result - Copyright 2026 © Buckethead Entertainment. All rights are reserved.");
		Toolkit.WithSkinnedMesh(val8, val7, ReconstructSkeleton(val8, generatedMesh));
		string text = GenerateFileName(publicUsername, val.Data);
		obj.SaveGLB(MelonEnvironment.UserDataDirectory + "/glTF_Exporter/" + text + ".glb", (WriteSettings)null);
		((MelonBase)this).LoggerInstance.Msg($"Saved model to {MelonEnvironment.UserDataDirectory}/glTF_Exporter/{text}.glb");
		MeshGenerationLocked = false;
	}

	private string GenerateFileName(string publicUsername, PlayerVisualData data)
	{
		return Regex.Replace(publicUsername, "<.*?>|\\(.*?\\)|[^a-zA-Z0-9_ ]", "").TrimStart().TrimEnd() + "-" + CreateCosmeticHash(data);
	}

	private string CreateCosmeticHash(PlayerVisualData data)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		SHA1 sHA = SHA1.Create();
		List<short> list = new List<short>();
		list.Add((short)data.Identity);
		list.AddRange((IEnumerable<short>)data.ColorationIndexes);
		list.AddRange((IEnumerable<short>)data.CustomizationPartIndexes);
		list.AddRange((IEnumerable<short>)data.TextureCustomizationIndexes);
		list.AddRange((IEnumerable<short>)data.TextureOpacityIndexes);
		list.AddRange((IEnumerable<short>)data.WeightAdjustementIndexes);
		byte[] array = new byte[list.Count * 2];
		Buffer.BlockCopy(list.ToArray(), 0, array, 0, list.Count * 2);
		return BitConverter.ToString(sHA.ComputeHash(array)).Replace("-", "").Substring(0, 8);
	}

	private Texture2D TexDownload(Texture2D gpuTex)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		if ((Object)(object)gpuTex == (Object)null)
		{
			((MelonBase)this).LoggerInstance.Msg("what the fuck");
		}
		RenderTexture temporary = RenderTexture.GetTemporary(((Texture)gpuTex).width, ((Texture)gpuTex).height, 0, ((Texture)gpuTex).graphicsFormat, 1);
		Texture2D val = new Texture2D(((Texture)gpuTex).width, ((Texture)gpuTex).height, (TextureFormat)4, false);
		Graphics.Blit((Texture)(object)gpuTex, temporary);
		RenderTexture.active = temporary;
		val.ReadPixels(new Rect(0f, 0f, (float)((Texture)gpuTex).width, (float)((Texture)gpuTex).height), 0, 0);
		RenderTexture.active = null;
		RenderTexture.ReleaseTemporary(temporary);
		return val;
	}

	private (Node Joint, Matrix4x4 IBM)[] ReconstructSkeleton(Node nodeRoot, Mesh mesh)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		List<(Node, Matrix4x4)> list = new List<(Node, Matrix4x4)>();
		Il2CppStructArray<Matrix4x4> bindposes = mesh.bindposes;
		foreach (var item4 in ((IEnumerable<Transform>)((Component)Singleton<PlayerManager>.Instance.LocalPlayer.Controller).GetComponentInChildren<SkinnedMeshRenderer>().bones).Zip((IEnumerable<Matrix4x4>)bindposes))
		{
			Transform item = item4.First;
			Matrix4x4 item2 = item4.Second;
			Matrix4x4 item3 = item2.ToNumerics();
			Node val = nodeRoot.CreateNode(((Object)item).name);
			Toolkit.WithLocalTransform(val, AffineTransform.CreateDecomposed(((Matrix4x4)(ref item2)).inverse.ToNumerics()));
			list.Add((val, item3));
		}
		return list.ToArray();
	}

	[MethodImpl(MethodImplOptions.AggressiveOptimization)]
	private void PopulateMesh(Il2CppStructArray<int> triangles, Il2CppStructArray<Vector3> vertices, Il2CppStructArray<Vector3> normals, Il2CppStructArray<Color32> vertexColors, MeshBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4> mesh, MaterialBuilder material, Il2CppStructArray<BoneWeight> weights, Vector2[] uv)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: Unknown result type (might be due to invalid IL or missing references)
		//IL_0335: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Unknown result type (might be due to invalid IL or missing references)
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		foreach (int[] item in ((IEnumerable<int>)triangles).Chunk(3))
		{
			Vector3 vector = ((Il2CppArrayBase<Vector3>)(object)vertices)[item[0]].ToNumerics();
			Vector3 vector2 = ((Il2CppArrayBase<Vector3>)(object)normals)[item[0]].ToNumerics();
			VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4> val = VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4>.Create(ref vector, ref vector2);
			vector = ((Il2CppArrayBase<Vector3>)(object)vertices)[item[1]].ToNumerics();
			vector2 = ((Il2CppArrayBase<Vector3>)(object)normals)[item[1]].ToNumerics();
			VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4> val2 = VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4>.Create(ref vector, ref vector2);
			vector = ((Il2CppArrayBase<Vector3>)(object)vertices)[item[2]].ToNumerics();
			vector2 = ((Il2CppArrayBase<Vector3>)(object)normals)[item[2]].ToNumerics();
			VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4> val3 = VertexBuilder<VertexPositionNormal, VertexColor1Texture1, VertexJoints4>.Create(ref vector, ref vector2);
			Vector2 texCoord = uv[item[0]].ToNumerics();
			Vector2 texCoord2 = uv[item[1]].ToNumerics();
			Vector2 texCoord3 = uv[item[2]].ToNumerics();
			texCoord.Y = texCoord.Y * -1f + 1f;
			texCoord2.Y = texCoord2.Y * -1f + 1f;
			texCoord3.Y = texCoord3.Y * -1f + 1f;
			val.Material.TexCoord = texCoord;
			val2.Material.TexCoord = texCoord2;
			val3.Material.TexCoord = texCoord3;
			val.Material.Color = ((Il2CppArrayBase<Color32>)(object)vertexColors)[item[0]].ToNumerics();
			val2.Material.Color = ((Il2CppArrayBase<Color32>)(object)vertexColors)[item[1]].ToNumerics();
			val3.Material.Color = ((Il2CppArrayBase<Color32>)(object)vertexColors)[item[2]].ToNumerics();
			ref VertexJoints4 skinning = ref val.Skinning;
			BoneWeight val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			float x = ((BoneWeight)(ref val4)).boneIndex0;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			float y = ((BoneWeight)(ref val4)).boneIndex1;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			float z = ((BoneWeight)(ref val4)).boneIndex2;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			skinning.Joints = new Vector4(x, y, z, ((BoneWeight)(ref val4)).boneIndex3);
			ref VertexJoints4 skinning2 = ref val.Skinning;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			float weight = ((BoneWeight)(ref val4)).weight0;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			float weight2 = ((BoneWeight)(ref val4)).weight1;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			float weight3 = ((BoneWeight)(ref val4)).weight2;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[0]];
			skinning2.Weights = new Vector4(weight, weight2, weight3, ((BoneWeight)(ref val4)).weight3);
			ref VertexJoints4 skinning3 = ref val2.Skinning;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			float x2 = ((BoneWeight)(ref val4)).boneIndex0;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			float y2 = ((BoneWeight)(ref val4)).boneIndex1;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			float z2 = ((BoneWeight)(ref val4)).boneIndex2;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			skinning3.Joints = new Vector4(x2, y2, z2, ((BoneWeight)(ref val4)).boneIndex3);
			ref VertexJoints4 skinning4 = ref val2.Skinning;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			float weight4 = ((BoneWeight)(ref val4)).weight0;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			float weight5 = ((BoneWeight)(ref val4)).weight1;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			float weight6 = ((BoneWeight)(ref val4)).weight2;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[1]];
			skinning4.Weights = new Vector4(weight4, weight5, weight6, ((BoneWeight)(ref val4)).weight3);
			ref VertexJoints4 skinning5 = ref val3.Skinning;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			float x3 = ((BoneWeight)(ref val4)).boneIndex0;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			float y3 = ((BoneWeight)(ref val4)).boneIndex1;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			float z3 = ((BoneWeight)(ref val4)).boneIndex2;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			skinning5.Joints = new Vector4(x3, y3, z3, ((BoneWeight)(ref val4)).boneIndex3);
			ref VertexJoints4 skinning6 = ref val3.Skinning;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			float weight7 = ((BoneWeight)(ref val4)).weight0;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			float weight8 = ((BoneWeight)(ref val4)).weight1;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			float weight9 = ((BoneWeight)(ref val4)).weight2;
			val4 = ((Il2CppArrayBase<BoneWeight>)(object)weights)[item[2]];
			skinning6.Weights = new Vector4(weight7, weight8, weight9, ((BoneWeight)(ref val4)).weight3);
			((MeshBuilder<MaterialBuilder, VertexPositionNormal, VertexColor1Texture1, VertexJoints4>)(object)mesh).UsePrimitive(material, 3).AddTriangle(val, val2, val3);
		}
	}
}
[HarmonyPatch(typeof(CharacterCreationLookupTable), "BakeApplyAndCachePlayerVisuals")]
public static class VisualGen_Patch
{
	private static void Postfix(CharacterCreationLookupTable __instance, string __0, PlayerVisualData __1, bool __2)
	{
		Melon<Exporter>.Instance.StartExport(__0, __1);
	}
}

UserLibs/SharpGLTF.Core.dll

Decompiled a day ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.CodeAnalysis;
using SharpGLTF.Animations;
using SharpGLTF.Collections;
using SharpGLTF.Diagnostics;
using SharpGLTF.IO;
using SharpGLTF.Memory;
using SharpGLTF.Reflection;
using SharpGLTF.Schema2;
using SharpGLTF.Transforms;
using SharpGLTF.Validation;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Vicente Penades")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2025 Vicente Penades")]
[assembly: AssemblyDescription("SharpGLTF is a C# library for reading and writing glTF2 3D models")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5c4bd9643aef7c600304eac85b1325bb249feb70")]
[assembly: AssemblyProduct("SharpGLTF.Core")]
[assembly: AssemblyTitle("SharpGLTF.Core")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/vpenades/SharpGLTF")]
[assembly: InternalsVisibleTo("SharpGLTF.Core.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100318e6698f4f41b26736d5881759c6afde44d17c06b63d2e383c915ca1fed6ec1b6eb2e1c38013feb2320224ace549b7701e22e6e0f7770e0d72b5c199f9e969bf2c2668c0ebeb035e539fb534d9ef24053aa9997d2d72534a6c1da8ab58e353ed6eb62ad9eb1f4a044893d7a50a226e4701d4e472a7dc1918caee6794d9c4cae")]
[assembly: InternalsVisibleTo("SharpGLTF.Toolkit.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100318e6698f4f41b26736d5881759c6afde44d17c06b63d2e383c915ca1fed6ec1b6eb2e1c38013feb2320224ace549b7701e22e6e0f7770e0d72b5c199f9e969bf2c2668c0ebeb035e539fb534d9ef24053aa9997d2d72534a6c1da8ab58e353ed6eb62ad9eb1f4a044893d7a50a226e4701d4e472a7dc1918caee6794d9c4cae")]
[assembly: InternalsVisibleTo("SharpGLTF.Ext.3DTiles.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100318e6698f4f41b26736d5881759c6afde44d17c06b63d2e383c915ca1fed6ec1b6eb2e1c38013feb2320224ace549b7701e22e6e0f7770e0d72b5c199f9e969bf2c2668c0ebeb035e539fb534d9ef24053aa9997d2d72534a6c1da8ab58e353ed6eb62ad9eb1f4a044893d7a50a226e4701d4e472a7dc1918caee6794d9c4cae")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
}
namespace SharpGLTF
{
	[DebuggerStepThrough]
	internal static class Guard
	{
		private static readonly IReadOnlyList<char> _InvalidRelativePathChars = (from c in Path.GetInvalidFileNameChars()
			where c != '/' && c != '\\'
			select c).ToArray();

		public static void NotNullOrEmpty(string target, string parameterName, string message = "")
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName, message);
			}
			if (!string.IsNullOrWhiteSpace(target))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = parameterName + " cannot be null or empty and cannot contain only blanks.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void FileNameMustBeValid(string fileName, string parameterName, string message = "")
		{
			NotNullOrEmpty(fileName, parameterName, message);
			char[] invalid = Path.GetInvalidFileNameChars();
			if (!fileName.Any((char c) => invalid.Contains(c)))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = fileName + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void FilePathMustBeValid(string filePath, string parameterName, string message = "")
		{
			NotNullOrEmpty(filePath, parameterName, message);
			filePath = Path.GetFullPath(filePath);
			bool flag = false;
			flag |= filePath.EndsWith(new string(Path.DirectorySeparatorChar, 1), StringComparison.Ordinal);
			if (!(flag | filePath.EndsWith(new string(Path.AltDirectorySeparatorChar, 1), StringComparison.Ordinal)))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = filePath + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void FilePathMustExist(string filePath, string parameterName, string message = "")
		{
			if (File.Exists(filePath))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = filePath + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void DirectoryPathMustExist(string dirPath, string parameterName, string message = "")
		{
			if (Directory.Exists(dirPath))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = dirPath + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void MustExist(FileInfo finfo, string parameterName, string message = "")
		{
			if (finfo == null)
			{
				throw new ArgumentNullException("finfo");
			}
			if (finfo.Exists)
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = finfo.FullName + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void MustExist(DirectoryInfo dinfo, string parameterName, string message = "")
		{
			if (dinfo == null)
			{
				throw new ArgumentNullException("dinfo");
			}
			if (dinfo.Exists)
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = dinfo.FullName + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void NotNull(object target, string parameterName)
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void NotNull(object target, string parameterName, string message)
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName, message);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void MustBeNull(object target, string parameterName, string message = "")
		{
			if (target == null)
			{
				return;
			}
			throw new ArgumentException(parameterName, message);
		}

		public static void NotNullOrEmpty<T>(IEnumerable<T> target, string parameterName, string message = "")
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName, message);
			}
			if (target.Any())
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = parameterName + " cannot be empty.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void MustBeEqualTo<TValue>(TValue value, TValue expected, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(expected) == 0)
			{
				return;
			}
			throw new ArgumentException(parameterName, $"{parameterName} {value} must be equal to {expected}.");
		}

		public static void MustBePositiveAndMultipleOf(int value, int padding, string parameterName, string message = "")
		{
			if (value < 0)
			{
				if (string.IsNullOrWhiteSpace(message))
				{
					message = parameterName + " must not be negative";
				}
				throw new ArgumentOutOfRangeException(message, parameterName);
			}
			if (value % padding != 0)
			{
				if (string.IsNullOrWhiteSpace(message))
				{
					message = $"{parameterName} is {value}; expected to be multiple of {padding}";
				}
				throw new ArgumentOutOfRangeException(message, parameterName);
			}
		}

		public static void MustBeLessThan<TValue>(TValue value, TValue max, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(max) < 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be less than {max}.");
		}

		public static void MustBeLessThanOrEqualTo<TValue>(TValue value, TValue max, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(max) > 0)
			{
				throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be less than or equal to {max}.");
			}
		}

		public static void MustBeGreaterThan<TValue>(TValue value, TValue min, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(min) > 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"Value {value} must be greater than {min}.");
		}

		public static void MustBeGreaterThanOrEqualTo<TValue>(TValue value, TValue min, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(min) >= 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be greater than or equal to {min}.");
		}

		public static void MustBeBetweenOrEqualTo<TValue>(TValue value, TValue minInclusive, TValue maxInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(minInclusive) >= 0 && value.CompareTo(maxInclusive) <= 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be greater than or equal to {minInclusive} and less than or equal to {maxInclusive}.");
		}

		public static void IsTrue(bool target, string parameterName, string message = "")
		{
			if (target)
			{
				return;
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void IsFalse(bool target, string parameterName, string message = "")
		{
			if (!target)
			{
				return;
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void IsValidURI(string parameterName, string gltfURI, params string[] validHeaders)
		{
			if (string.IsNullOrEmpty(gltfURI))
			{
				return;
			}
			foreach (string text in validHeaders)
			{
				if (gltfURI.StartsWith(text, StringComparison.OrdinalIgnoreCase))
				{
					string value = text + ",";
					if (gltfURI.StartsWith(value, StringComparison.OrdinalIgnoreCase) || gltfURI.StartsWith(text + ";base64,", StringComparison.OrdinalIgnoreCase))
					{
						return;
					}
					throw new ArgumentException(parameterName + " has invalid URI '" + gltfURI + "'.");
				}
			}
			if (gltfURI.Any((char c) => _InvalidRelativePathChars.Contains(c)))
			{
				throw new ArgumentException("Invalid URI '" + gltfURI + "'.");
			}
			if (gltfURI.Any((char chr) => char.IsWhiteSpace(chr)))
			{
				gltfURI = gltfURI._EscapeStringInternal();
			}
			if (Uri.TryCreate(gltfURI, UriKind.Relative, out Uri _))
			{
				return;
			}
			throw new ArgumentException("Invalid URI '" + gltfURI + "'.");
		}

		public static void MustShareLogicalParent(LogicalChildOfRoot a, LogicalChildOfRoot b, string parameterName)
		{
			MustShareLogicalParent(a?.LogicalParent, "LogicalParent", b, parameterName);
		}

		public static void MustShareLogicalParent(ModelRoot a, string aName, LogicalChildOfRoot b, string bName)
		{
			if (a == null)
			{
				throw new ArgumentNullException(aName);
			}
			if (b == null)
			{
				throw new ArgumentNullException(bName);
			}
			if (a != b.LogicalParent)
			{
				throw new ArgumentException("LogicalParent mismatch", bName);
			}
		}

		public static void HasDynamicallyAccessedMembers(Type t, bool hasConstructors, bool hasMethods, bool hasProperties, bool hasFields, string parameterName)
		{
			DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes = DynamicallyAccessedMemberTypes.None;
			if (hasConstructors)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
			}
			if (hasMethods)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicMethods;
			}
			if (hasProperties)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicProperties;
			}
			if (hasFields)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicFields;
			}
			DynamicallyAccessedMembersAttribute customAttribute = t.GetCustomAttribute<DynamicallyAccessedMembersAttribute>();
			if (customAttribute == null || (customAttribute.MemberTypes & dynamicallyAccessedMemberTypes) != dynamicallyAccessedMemberTypes)
			{
				throw new ArgumentException($"{parameterName} {t.Name} must define  #if NET6_0_OR_GREATER  [DynamicallyAccessedMembers({dynamicallyAccessedMemberTypes})] #endif");
			}
		}
	}
	[DebuggerStepThrough]
	internal static class GuardAll
	{
		public static void NotNull<T>(IEnumerable<T> collection, string parameterName, string message = "")
		{
			Guard.NotNull(collection, "collection");
			foreach (T item in collection)
			{
				Guard.NotNull(item, parameterName, message);
			}
		}

		public static void AreTrue(IEnumerable<bool> collection, string parameterName, Func<int, string> messageFunc = null)
		{
			Guard.NotNull(collection, "collection");
			int num = 0;
			foreach (bool item in collection)
			{
				Guard.IsTrue(item, parameterName, messageFunc?.Invoke(num) ?? string.Empty);
				num++;
			}
		}

		public static void MustBeEqualTo<TValue>(IEnumerable<TValue> collection, TValue expected, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeEqualTo(item, expected, parameterName);
			}
		}

		public static void MustBeGreaterThan<TValue>(IEnumerable<TValue> collection, TValue minExclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeGreaterThan(item, minExclusive, parameterName);
			}
		}

		public static void MustBeLessThan<TValue>(IEnumerable<TValue> collection, TValue maxExclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeLessThan(item, maxExclusive, parameterName);
			}
		}

		public static void MustBeLessThanOrEqualTo<TValue>(IEnumerable<TValue> collection, TValue maxInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeLessThanOrEqualTo(item, maxInclusive, parameterName);
			}
		}

		public static void MustBeGreaterThanOrEqualTo<TValue>(IEnumerable<TValue> collection, TValue minInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeGreaterThanOrEqualTo(item, minInclusive, parameterName);
			}
		}

		public static void MustBeBetweenOrEqualTo<TValue>(IEnumerable<TValue> collection, TValue minInclusive, TValue maxInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeBetweenOrEqualTo(item, minInclusive, maxInclusive, parameterName);
			}
		}
	}
	internal static class _Extensions
	{
		private readonly struct _ListSelect<TSource, TResult> : IReadOnlyList<TResult>, IEnumerable<TResult>, IEnumerable, IReadOnlyCollection<TResult>
		{
			[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
			private readonly IReadOnlyList<TSource> _List;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly Func<TSource, TResult> _Selector;

			public TResult this[int index] => _Selector(_List[index]);

			public int Count => _List.Count;

			public _ListSelect(IReadOnlyList<TSource> list, Func<TSource, TResult> selector)
			{
				_List = list;
				_Selector = selector;
			}

			public IEnumerator<TResult> GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}
		}

		private readonly struct _CollectionSelect<TSource, TResult> : IReadOnlyCollection<TResult>, IEnumerable<TResult>, IEnumerable
		{
			[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
			private readonly IReadOnlyCollection<TSource> _List;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly Func<TSource, TResult> _Selector;

			public int Count => _List.Count;

			public _CollectionSelect(IReadOnlyCollection<TSource> list, Func<TSource, TResult> selector)
			{
				_List = list;
				_Selector = selector;
			}

			public IEnumerator<TResult> GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}
		}

		private const float _UnitLengthThresholdVec3 = 0.00674f;

		private const float _UnitLengthThresholdVec4 = 0.00769f;

		private const float _UnitSumThresholdStep = 0.0039216f;

		internal static bool IsMultipleOf(this int value, int mult)
		{
			return value % mult == 0;
		}

		internal static int WordPadded(this int length)
		{
			int num = length & 3;
			return length + ((num != 0) ? (4 - num) : 0);
		}

		internal static bool _IsFinite(this float value)
		{
			return float.IsFinite(value);
		}

		internal static bool _IsFinite(this Vector2 v)
		{
			if (v.X._IsFinite())
			{
				return v.Y._IsFinite();
			}
			return false;
		}

		internal static bool _IsFinite(this Vector3 v)
		{
			if (v.X._IsFinite() && v.Y._IsFinite())
			{
				return v.Z._IsFinite();
			}
			return false;
		}

		internal static bool _IsFinite(this in Vector4 v)
		{
			if (v.X._IsFinite() && v.Y._IsFinite() && v.Z._IsFinite())
			{
				return v.W._IsFinite();
			}
			return false;
		}

		internal static bool _IsFinite(this in Matrix4x4 v)
		{
			if (!v.M11._IsFinite() || !v.M12._IsFinite() || !v.M13._IsFinite() || !v.M14._IsFinite())
			{
				return false;
			}
			if (!v.M21._IsFinite() || !v.M22._IsFinite() || !v.M23._IsFinite() || !v.M24._IsFinite())
			{
				return false;
			}
			if (!v.M31._IsFinite() || !v.M32._IsFinite() || !v.M33._IsFinite() || !v.M34._IsFinite())
			{
				return false;
			}
			if (!v.M41._IsFinite() || !v.M42._IsFinite() || !v.M43._IsFinite() || !v.M44._IsFinite())
			{
				return false;
			}
			return true;
		}

		internal static bool _IsFinite(this Quaternion v)
		{
			if (v.X._IsFinite() && v.Y._IsFinite() && v.Z._IsFinite())
			{
				return v.W._IsFinite();
			}
			return false;
		}

		internal static Vector3 WithLength(this Vector3 v, float len)
		{
			return Vector3.Normalize(v) * len;
		}

		internal static bool IsNormalized(this Vector3 normal)
		{
			if (!normal._IsFinite())
			{
				return false;
			}
			return Math.Abs(normal.Length() - 1f) <= 0.00674f;
		}

		internal static bool IsNormalized(this Quaternion rotation)
		{
			if (!rotation._IsFinite())
			{
				return false;
			}
			return Math.Abs(rotation.Length() - 1f) <= 0.00769f;
		}

		internal static Quaternion AsQuaternion(this Vector4 v)
		{
			return new Quaternion(v.X, v.Y, v.Z, v.W);
		}

		internal static Quaternion Sanitized(this Quaternion q)
		{
			if (!q.IsNormalized())
			{
				return Quaternion.Normalize(q);
			}
			return q;
		}

		internal static bool IsInRange(this Vector3 value, Vector3 min, Vector3 max)
		{
			if (value.X < min.X || value.X > max.X)
			{
				return false;
			}
			if (value.Y < min.Y || value.Y > max.Y)
			{
				return false;
			}
			if (value.Z < min.Z || value.Z > max.Z)
			{
				return false;
			}
			return true;
		}

		internal static bool IsInRange(this Vector4 value, Vector4 min, Vector4 max)
		{
			if (value.X < min.X || value.X > max.X)
			{
				return false;
			}
			if (value.Y < min.Y || value.Y > max.Y)
			{
				return false;
			}
			if (value.Z < min.Z || value.Z > max.Z)
			{
				return false;
			}
			if (value.W < min.W || value.W > max.W)
			{
				return false;
			}
			return true;
		}

		internal static bool IsRound(this Vector4 value)
		{
			Vector4 vector = new Vector4((int)value.X, (int)value.Y, (int)value.Z, (int)value.W);
			return value - vector == Vector4.Zero;
		}

		internal static void ValidateNormal(this Vector3 normal, string msg)
		{
			if (!normal._IsFinite())
			{
				throw new NotFiniteNumberException(msg + " is invalid.");
			}
			if (!normal.IsNormalized())
			{
				throw new ArithmeticException(msg + " is not unit length.");
			}
		}

		internal static void ValidateTangent(this Vector4 tangent, string msg)
		{
			if (tangent.W != 1f && tangent.W != -1f)
			{
				throw new ArithmeticException(msg);
			}
			new Vector3(tangent.X, tangent.Y, tangent.Z).ValidateNormal(msg);
		}

		internal static Vector3 SanitizeNormal(this Vector3 normal)
		{
			if (normal == Vector3.Zero)
			{
				return Vector3.UnitX;
			}
			if (!normal.IsNormalized())
			{
				return Vector3.Normalize(normal);
			}
			return normal;
		}

		internal static bool IsValidTangent(this Vector4 tangent)
		{
			if (tangent.W != 1f && tangent.W != -1f)
			{
				return false;
			}
			return new Vector3(tangent.X, tangent.Y, tangent.Z).IsNormalized();
		}

		internal static Vector4 SanitizeTangent(this Vector4 tangent)
		{
			Vector3 value = new Vector3(tangent.X, tangent.Y, tangent.Z).SanitizeNormal();
			float num = (float.IsNaN(tangent.W) ? 1f : tangent.W);
			return new Vector4(value, (num > 0f) ? 1 : (-1));
		}

		internal static Matrix4x4 Inverse(this in Matrix4x4 src)
		{
			if (!Matrix4x4.Invert(src, out var result))
			{
				Guard.IsTrue(target: false, "src", "Matrix cannot be inverted.");
			}
			if (src.M44 == 1f)
			{
				result.M44 = 1f;
			}
			return result;
		}

		internal static bool IsValid(this in Matrix4x4 matrix, Matrix4x4Factory.MatrixCheck check, float tolerance = 0f)
		{
			return Matrix4x4Factory.IsValid(in matrix, check, tolerance);
		}

		public static bool AreSameReference<T>(this (T x, T y) refs, out bool result) where T : class
		{
			if (refs.x == refs.y)
			{
				result = true;
				return true;
			}
			if (refs.x == null)
			{
				result = false;
				return true;
			}
			if (refs.y == null)
			{
				result = false;
				return true;
			}
			result = false;
			return false;
		}

		internal static int GetContentHashCode<T>(this IEnumerable<T> collection, int count = int.MaxValue)
		{
			if (collection == null)
			{
				return 0;
			}
			int num = 0;
			if (collection is IReadOnlyList<T> readOnlyList)
			{
				count = Math.Min(count, readOnlyList.Count);
				for (int i = 0; i < count; i++)
				{
					num ^= readOnlyList[i]?.GetHashCode() ?? 0;
					num *= 17;
				}
				return num;
			}
			foreach (T item in collection.Take(count))
			{
				num ^= item?.GetHashCode() ?? 0;
				num *= 17;
			}
			return num;
		}

		internal static ArraySegment<T> Slice<T>(this T[] array, int offset)
		{
			return new ArraySegment<T>(array, offset, array.Length - offset);
		}

		internal static T[] CloneArray<T>(this T[] srcArray)
		{
			if (srcArray == null)
			{
				return null;
			}
			T[] array = new T[srcArray.Length];
			srcArray.CopyTo(array, 0);
			return array;
		}

		internal static void Fill<T>(this IList<T> collection, T value)
		{
			for (int i = 0; i < collection.Count; i++)
			{
				collection[i] = value;
			}
		}

		internal static void Fill<T>(this T[] array, T value)
		{
			array.AsSpan().Fill(value);
		}

		internal static IReadOnlyList<T> EnsureList<T>(this IEnumerable<T> collection)
		{
			if (!(collection is IReadOnlyList<T> result))
			{
				return collection.ToList();
			}
			return result;
		}

		internal static bool IsEmpty<T>(this IReadOnlyList<T> list)
		{
			return list.Count == 0;
		}

		internal static int IndexOf<T>(this IReadOnlyList<T> collection, T value)
		{
			int count = collection.Count;
			for (int i = 0; i < count; i++)
			{
				if (object.Equals(collection[i], value))
				{
					return i;
				}
			}
			return -1;
		}

		internal static int IndexOf<T>(this IReadOnlyList<T> collection, Predicate<T> predicate)
		{
			int count = collection.Count;
			for (int i = 0; i < count; i++)
			{
				if (predicate(collection[i]))
				{
					return i;
				}
			}
			return -1;
		}

		internal static int IndexOf<T>(this IReadOnlyList<T> collection, T[] subset) where T : IEquatable<T>
		{
			int num = collection.Count - subset.Length;
			for (int i = 0; i < num; i++)
			{
				bool flag = false;
				for (int j = 0; j < subset.Length && collection[i + j].Equals(subset[j]); j++)
				{
					flag = true;
				}
				if (flag)
				{
					return i;
				}
			}
			return -1;
		}

		internal static void CopyTo<T>(this T[] src, int srcOffset, IList<T> dst, int dstOffset, int count)
		{
			ArraySegment<T> src2 = new ArraySegment<T>(src);
			src2.CopyTo(srcOffset, dst, dstOffset, count);
		}

		internal static void CopyTo<T>(this ArraySegment<T> src, int srcOffset, IList<T> dst, int dstOffset, int count)
		{
			if (dst is T[] destinationArray)
			{
				Array.Copy(src.Array, src.Offset + srcOffset, destinationArray, dstOffset, count);
				return;
			}
			for (int i = 0; i < count; i++)
			{
				dst[dstOffset + i] = src.Array[src.Offset + srcOffset + i];
			}
		}

		internal static void AddRange<Tin, Tout>(this IList<Tout> dst, IEnumerable<Tin> src, Converter<Tin, Tout> cvt)
		{
			foreach (Tin item in src)
			{
				dst.Add(cvt(item));
			}
		}

		internal static IEnumerable<T> ConcatElements<T>(this IEnumerable<T> collection, params T[] elements)
		{
			return collection.Concat(elements.Where((T item) => item != null));
		}

		public static void SanitizeNormals(this IList<Vector3> normals)
		{
			for (int i = 0; i < normals.Count; i++)
			{
				if (!normals[i].IsNormalized())
				{
					normals[i] = normals[i].SanitizeNormal();
				}
			}
		}

		public static void SanitizeTangents(this IList<Vector4> tangents)
		{
			for (int i = 0; i < tangents.Count; i++)
			{
				if (!tangents[i].IsValidTangent())
				{
					tangents[i] = tangents[i].SanitizeTangent();
				}
			}
		}

		public static IReadOnlyList<TResult> SelectList<TSource, TResult>(this IReadOnlyList<TSource> collection, Func<TSource, TResult> selector)
		{
			return new _ListSelect<TSource, TResult>(collection, selector);
		}

		public static IReadOnlyCollection<TResult> SelectCollection<TSource, TResult>(this IReadOnlyCollection<TSource> collection, Func<TSource, TResult> selector)
		{
			return new _CollectionSelect<TSource, TResult>(collection, selector);
		}

		public static string ToDebugString(this EncodingType encoding, DimensionType dimensions, bool normalized)
		{
			string text = string.Empty;
			switch (encoding)
			{
			case EncodingType.BYTE:
				text += "SByte";
				break;
			case EncodingType.FLOAT:
				text += "Float";
				break;
			case EncodingType.SHORT:
				text += "SShort";
				break;
			case EncodingType.UNSIGNED_BYTE:
				text += "UByte";
				break;
			case EncodingType.UNSIGNED_INT:
				text += "UInt";
				break;
			case EncodingType.UNSIGNED_SHORT:
				text += "UShort";
				break;
			}
			switch (dimensions)
			{
			case DimensionType.VEC2:
				text += "2";
				break;
			case DimensionType.VEC3:
				text += "3";
				break;
			case DimensionType.VEC4:
				text += "4";
				break;
			case DimensionType.MAT2:
				text += "2x2";
				break;
			case DimensionType.MAT3:
				text += "3x3";
				break;
			case DimensionType.MAT4:
				text += "4x4";
				break;
			}
			if (normalized)
			{
				text = "Norm" + text;
			}
			return text;
		}

		public static int ByteLength(this IndexEncodingType encoding)
		{
			return encoding switch
			{
				IndexEncodingType.UNSIGNED_BYTE => 1, 
				IndexEncodingType.UNSIGNED_SHORT => 2, 
				IndexEncodingType.UNSIGNED_INT => 4, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static int ByteLength(this EncodingType encoding)
		{
			return encoding switch
			{
				EncodingType.BYTE => 1, 
				EncodingType.SHORT => 2, 
				EncodingType.FLOAT => 4, 
				EncodingType.UNSIGNED_BYTE => 1, 
				EncodingType.UNSIGNED_SHORT => 2, 
				EncodingType.UNSIGNED_INT => 4, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static EncodingType ToComponent(this IndexEncodingType t)
		{
			return t switch
			{
				IndexEncodingType.UNSIGNED_BYTE => EncodingType.UNSIGNED_BYTE, 
				IndexEncodingType.UNSIGNED_SHORT => EncodingType.UNSIGNED_SHORT, 
				IndexEncodingType.UNSIGNED_INT => EncodingType.UNSIGNED_INT, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static IndexEncodingType ToIndex(this EncodingType t)
		{
			return t switch
			{
				EncodingType.UNSIGNED_BYTE => IndexEncodingType.UNSIGNED_BYTE, 
				EncodingType.UNSIGNED_SHORT => IndexEncodingType.UNSIGNED_SHORT, 
				EncodingType.UNSIGNED_INT => IndexEncodingType.UNSIGNED_INT, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static int DimCount(this DimensionType dimension)
		{
			return dimension switch
			{
				DimensionType.SCALAR => 1, 
				DimensionType.VEC2 => 2, 
				DimensionType.VEC3 => 3, 
				DimensionType.VEC4 => 4, 
				DimensionType.MAT2 => 4, 
				DimensionType.MAT3 => 9, 
				DimensionType.MAT4 => 16, 
				_ => throw new NotImplementedException(), 
			};
		}

		internal static DimensionType ToDimension(this int l)
		{
			return l switch
			{
				1 => DimensionType.SCALAR, 
				2 => DimensionType.VEC2, 
				3 => DimensionType.VEC3, 
				4 => DimensionType.VEC4, 
				9 => DimensionType.MAT3, 
				16 => DimensionType.MAT4, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static int GetPrimitiveVertexSize(this PrimitiveType ptype)
		{
			return ptype switch
			{
				PrimitiveType.POINTS => 1, 
				PrimitiveType.LINES => 2, 
				PrimitiveType.LINE_LOOP => 2, 
				PrimitiveType.LINE_STRIP => 2, 
				PrimitiveType.TRIANGLES => 3, 
				PrimitiveType.TRIANGLE_FAN => 3, 
				PrimitiveType.TRIANGLE_STRIP => 3, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static IEnumerable<(int A, int B)> GetLinesIndices(this PrimitiveType ptype, int vertexCount)
		{
			return ptype.GetLinesIndices(from item in Enumerable.Range(0, vertexCount)
				select (uint)item);
		}

		public static IEnumerable<(int A, int B, int C)> GetTrianglesIndices(this PrimitiveType ptype, int vertexCount)
		{
			return ptype.GetTrianglesIndices(from item in Enumerable.Range(0, vertexCount)
				select (uint)item);
		}

		public static IEnumerable<(int A, int B)> GetLinesIndices(this PrimitiveType ptype, IEnumerable<uint> sourceIndices)
		{
			if (ptype == PrimitiveType.LINES)
			{
				using (IEnumerator<uint> ptr = sourceIndices.GetEnumerator())
				{
					while (ptr.MoveNext())
					{
						uint current = ptr.Current;
						if (!ptr.MoveNext())
						{
							break;
						}
						uint current2 = ptr.Current;
						if (!_IsDegeneratedSegment(current, current2))
						{
							yield return ((int)current, (int)current2);
						}
					}
				}
				yield break;
			}
			throw new NotImplementedException();
		}

		public static IEnumerable<(int A, int B, int C)> GetTrianglesIndices(this PrimitiveType ptype, IEnumerable<uint> sourceIndices)
		{
			switch (ptype)
			{
			case PrimitiveType.TRIANGLES:
			{
				using (IEnumerator<uint> enumerator = sourceIndices.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						uint current = enumerator.Current;
						if (!enumerator.MoveNext())
						{
							break;
						}
						uint current2 = enumerator.Current;
						if (!enumerator.MoveNext())
						{
							break;
						}
						uint current3 = enumerator.Current;
						if (!_IsDegeneratedTriangle(current, current2, current3))
						{
							yield return ((int)current, (int)current2, (int)current3);
						}
					}
				}
				break;
			}
			case PrimitiveType.TRIANGLE_FAN:
			{
				using IEnumerator<uint> enumerator = sourceIndices.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint a2 = enumerator.Current;
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint num2 = enumerator.Current;
				while (enumerator.MoveNext())
				{
					uint c2 = enumerator.Current;
					if (!_IsDegeneratedTriangle(a2, num2, c2))
					{
						yield return ((int)a2, (int)num2, (int)c2);
					}
					num2 = c2;
				}
				break;
			}
			case PrimitiveType.TRIANGLE_STRIP:
			{
				using IEnumerator<uint> enumerator = sourceIndices.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint num = enumerator.Current;
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint a2 = enumerator.Current;
				bool reversed = false;
				while (enumerator.MoveNext())
				{
					uint c2 = enumerator.Current;
					if (!_IsDegeneratedTriangle(num, a2, c2))
					{
						if (reversed)
						{
							yield return ((int)a2, (int)num, (int)c2);
						}
						else
						{
							yield return ((int)num, (int)a2, (int)c2);
						}
					}
					num = a2;
					a2 = c2;
					reversed = !reversed;
				}
				break;
			}
			default:
				throw new NotImplementedException();
			}
		}

		private static bool _IsDegeneratedSegment(uint a, uint b)
		{
			return a == b;
		}

		private static bool _IsDegeneratedTriangle(uint a, uint b, uint c)
		{
			if (a == b)
			{
				return true;
			}
			if (a == c)
			{
				return true;
			}
			if (b == c)
			{
				return true;
			}
			return false;
		}

		public static byte[] ToUnderlayingArray(this ArraySegment<byte> segment)
		{
			if (segment.Offset == 0 && segment.Count == segment.Array.Length)
			{
				return segment.Array;
			}
			return segment.ToArray();
		}

		public static ArraySegment<byte> ToArraySegment(this MemoryStream m)
		{
			if (m.TryGetBuffer(out var buffer))
			{
				return buffer;
			}
			return new ArraySegment<byte>(m.ToArray());
		}

		public static byte[] GetPaddedContent(this byte[] content)
		{
			if (content == null)
			{
				return null;
			}
			if (content.Length.IsMultipleOf(4))
			{
				return content;
			}
			int num = content.Length % 4;
			num = ((num != 0) ? (4 - num) : 0);
			byte[] array = new byte[content.Length + num];
			content.CopyTo(array, 0);
			return array;
		}

		public static byte[] TryParseBase64Unchecked(this string uri, params string[] prefixes)
		{
			if (uri == null)
			{
				return null;
			}
			if (!uri.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			foreach (string prefix in prefixes)
			{
				byte[] array = _TryParseBase64Unchecked(uri, prefix);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		private static byte[] _TryParseBase64Unchecked(string uri, string prefix)
		{
			if (!uri.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			string text = uri.Substring(prefix.Length);
			if (text.StartsWith(";base64,", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(";base64,".Length);
				return Convert.FromBase64String(text);
			}
			if (text.StartsWith(','))
			{
				text = text.Substring(1);
				if (text.Length == 1)
				{
					return new byte[1] { byte.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture) };
				}
				throw new NotImplementedException();
			}
			throw new NotImplementedException();
		}

		public static string _EscapeStringInternal(this string uri)
		{
			return Uri.EscapeUriString(uri);
		}

		[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(JsonValue))]
		[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(JsonArray))]
		[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(JsonObject))]
		public static JsonNode DeepClone(this JsonNode node)
		{
			if (node == null)
			{
				throw new ArgumentNullException("node");
			}
			JsonNode jsonNode = null;
			if (!(node is JsonValue node2))
			{
				if (!(node is JsonArray node3))
				{
					if (node is JsonObject node4)
					{
						jsonNode = node4.Deserialize<JsonObject>();
					}
				}
				else
				{
					jsonNode = node3.Deserialize<JsonArray>();
				}
			}
			else
			{
				jsonNode = node2.Deserialize<JsonValue>();
			}
			if (jsonNode == null)
			{
				throw new NotImplementedException();
			}
			return jsonNode;
		}

		public static bool DeepEquals(this JsonNode x, JsonNode y, double precission)
		{
			if (x == y)
			{
				return true;
			}
			if (x == null)
			{
				return false;
			}
			if (y == null)
			{
				return false;
			}
			if (x is JsonValue jsonValue && y is JsonValue jsonValue2)
			{
				if (jsonValue.TryGetValue<int>(out var value) && jsonValue2.TryGetValue<int>(out var value2))
				{
					return value == value2;
				}
				if (jsonValue.TryGetValue<long>(out var value3) && jsonValue2.TryGetValue<long>(out var value4))
				{
					return value3 == value4;
				}
				if (jsonValue.TryGetValue<float>(out var value5) && jsonValue2.TryGetValue<float>(out var value6))
				{
					return (double)Math.Abs(value5 - value6) <= precission;
				}
				if (jsonValue.TryGetValue<double>(out var value7) && jsonValue2.TryGetValue<double>(out var value8))
				{
					return Math.Abs(value7 - value8) <= precission;
				}
				return jsonValue.ToJsonString() == jsonValue2.ToJsonString();
			}
			if (x is JsonArray jsonArray && y is JsonArray jsonArray2)
			{
				if (jsonArray.Count != jsonArray2.Count)
				{
					return false;
				}
				for (int i = 0; i < jsonArray.Count; i++)
				{
					if (!jsonArray[i].DeepEquals(jsonArray2[i], precission))
					{
						return false;
					}
				}
				return true;
			}
			if (x is JsonObject jsonObject && y is JsonObject jsonObject2)
			{
				if (jsonObject.Count != jsonObject2.Count)
				{
					return false;
				}
				foreach (KeyValuePair<string, JsonNode> item in jsonObject)
				{
					if (!jsonObject2.TryGetPropertyValue(item.Key, out JsonNode jsonNode))
					{
						return false;
					}
					if (!item.Value.DeepEquals(jsonNode, precission))
					{
						return false;
					}
				}
				return true;
			}
			return false;
		}
	}
}
namespace SharpGLTF.Validation
{
	public class ModelException : Exception
	{
		private readonly JsonSerializable _Target;

		internal string MessageSuffix { get; set; }

		public override string Message
		{
			get
			{
				if (string.IsNullOrWhiteSpace(MessageSuffix))
				{
					return base.Message;
				}
				return base.Message + MessageSuffix;
			}
		}

		private string _Generator
		{
			get
			{
				ModelRoot modelRoot = null;
				if (_Target is ModelRoot modelRoot2)
				{
					modelRoot = modelRoot2;
				}
				if (_Target is LogicalChildOfRoot logicalChildOfRoot)
				{
					modelRoot = logicalChildOfRoot.LogicalParent;
				}
				return modelRoot?.Asset?.Generator ?? string.Empty;
			}
		}

		internal ModelException(JsonSerializable target, string message)
			: base(_CreateBaseMessage(target, message))
		{
			_Target = target;
		}

		internal ModelException(JsonSerializable target, Exception ex)
			: base(_CreateBaseMessage(target, ex.Message), ex)
		{
			_Target = target;
		}

		private static string _CreateBaseMessage(JsonSerializable target, string message)
		{
			if (target == null)
			{
				return message;
			}
			TypeInfo typeInfo = target.GetType().GetTypeInfo();
			PropertyInfo property = typeInfo.GetProperty("LogicalIndex");
			int num = ((property != null) ? ((int)property.GetValue(target)) : (-1));
			if (num >= 0)
			{
				return $"{typeInfo.Name}[{num}] {message}";
			}
			return typeInfo.Name + " " + message;
		}

		internal static void _Decorate(Exception ex)
		{
			if (ex is ModelException ex2)
			{
				string generator = ex2._Generator;
				if (generator.Contains("SHARPGLTF", StringComparison.InvariantCultureIgnoreCase))
				{
					ex2.MessageSuffix = "Model generated by <" + generator + "> seems to be malformed.";
				}
				else
				{
					ex2.MessageSuffix = "Model generated by <" + generator + "> seems to be malformed; Please, check the file at https://github.khronos.org/glTF-Validator/";
				}
			}
		}
	}
	public class SchemaException : ModelException
	{
		internal SchemaException(JsonSerializable target, string message)
			: base(target, message)
		{
		}

		internal SchemaException(JsonSerializable target, JsonException rex)
			: base(target, rex)
		{
		}
	}
	public class SemanticException : ModelException
	{
		internal SemanticException(JsonSerializable target, string message)
			: base(target, message)
		{
		}
	}
	public class LinkException : ModelException
	{
		internal LinkException(JsonSerializable target, string message)
			: base(target, message)
		{
		}
	}
	public class DataException : ModelException
	{
		internal DataException(JsonSerializable target, string message)
			: base(target, message)
		{
		}
	}
	[StructLayout(LayoutKind.Auto)]
	[DebuggerDisplay("{_Current}")]
	[DebuggerStepThrough]
	public readonly struct ValidationContext
	{
		private readonly ModelRoot _Root;

		private readonly ValidationMode _Mode;

		private readonly JsonSerializable _Current;

		public ModelRoot Root => _Root;

		public bool TryFix => _Mode == ValidationMode.TryFix;

		public ValidationContext(ValidationResult result)
		{
			Guard.NotNull(result, "result");
			_Root = result.Root;
			_Mode = result.Mode;
			_Current = null;
		}

		internal ValidationContext(ValidationContext context, JsonSerializable target)
		{
			_Root = context._Root;
			_Mode = context._Mode;
			_Current = target;
		}

		public ValidationContext GetContext(JsonSerializable target)
		{
			return new ValidationContext(this, target);
		}

		[DebuggerStepThrough]
		internal void _SchemaThrow(ValueLocation pname, string msg)
		{
			throw new SchemaException(_Current, $"{pname}: {msg}");
		}

		public ValidationContext IsTrue(ValueLocation parameterName, bool value, string msg)
		{
			if (!value)
			{
				_SchemaThrow(parameterName, msg);
			}
			return this;
		}

		public ValidationContext NotNull(ValueLocation parameterName, object target)
		{
			if (target == null)
			{
				_SchemaThrow(parameterName, "must not be null.");
			}
			return this;
		}

		public ValidationContext MustBeNull(ValueLocation parameterName, object target)
		{
			if (target != null)
			{
				_SchemaThrow(parameterName, "must be null.");
			}
			return this;
		}

		public ValidationContext IsDefined<T>(ValueLocation parameterName, T value) where T : class
		{
			if (value == null)
			{
				_SchemaThrow(parameterName, "must be defined.");
			}
			return this;
		}

		public ValidationContext IsDefined<T>(ValueLocation parameterName, T? value) where T : struct
		{
			if (!value.HasValue)
			{
				_SchemaThrow(parameterName, "must be defined.");
			}
			return this;
		}

		public ValidationContext IsUndefined<T>(ValueLocation parameterName, T value) where T : class
		{
			if (value != null)
			{
				_SchemaThrow(parameterName, "must NOT be defined.");
			}
			return this;
		}

		public ValidationContext IsUndefined<T>(ValueLocation parameterName, T? value) where T : struct
		{
			if (value.HasValue)
			{
				_SchemaThrow(parameterName, "must NOT be defined.");
			}
			return this;
		}

		public ValidationContext AreSameReference<TRef>(ValueLocation parameterName, TRef value, TRef expected) where TRef : class
		{
			if (value != expected)
			{
				_SchemaThrow(parameterName, $"{value} and {expected} must be the same.");
			}
			return this;
		}

		public ValidationContext AreEqual<TValue>(ValueLocation parameterName, TValue value, TValue expected) where TValue : IEquatable<TValue>
		{
			if (!value.Equals(expected))
			{
				_SchemaThrow(parameterName, $"{value} must be equal to {expected}.");
			}
			return this;
		}

		public ValidationContext IsLess<TValue>(ValueLocation parameterName, TValue value, TValue max) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(max) >= 0)
			{
				_SchemaThrow(parameterName, $"{value} must be less than {max}.");
			}
			return this;
		}

		public ValidationContext IsLessOrEqual<TValue>(ValueLocation parameterName, TValue value, TValue max) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(max) > 0)
			{
				_SchemaThrow(parameterName, $"{value} must be less or equal to {max}.");
			}
			return this;
		}

		public ValidationContext IsGreater<TValue>(ValueLocation parameterName, TValue value, TValue min) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(min) <= 0)
			{
				_SchemaThrow(parameterName, $"{value} must be greater than {min}.");
			}
			return this;
		}

		public ValidationContext IsDefaultOrWithin<TValue>(ValueLocation parameterName, TValue? value, TValue minInclusive, TValue maxInclusive) where TValue : unmanaged, IComparable<TValue>
		{
			if (!value.HasValue)
			{
				return this;
			}
			if (value.Value.CompareTo(minInclusive) < 0)
			{
				_SchemaThrow(parameterName, $"{value} must be greater or equal to {minInclusive}.");
			}
			if (value.Value.CompareTo(maxInclusive) > 0)
			{
				_SchemaThrow(parameterName, $"{value} must be less or equal to {maxInclusive}.");
			}
			return this;
		}

		public ValidationContext IsGreaterOrEqual<TValue>(ValueLocation parameterName, TValue value, TValue min) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(min) < 0)
			{
				_SchemaThrow(parameterName, $"{value} must be greater or equal to {min}.");
			}
			return this;
		}

		public ValidationContext IsMultipleOf(ValueLocation parameterName, int value, int multiple)
		{
			if (value % multiple != 0)
			{
				_SchemaThrow(parameterName, $"Value {value} is not a multiple of {multiple}.");
			}
			return this;
		}

		public ValidationContext NonNegative(ValueLocation parameterName, int? value)
		{
			if (value.GetValueOrDefault() < 0)
			{
				_SchemaThrow(parameterName, "must be a non-negative integer.");
			}
			return this;
		}

		public ValidationContext IsNullOrValidURI(ValueLocation parameterName, string gltfURI, params string[] validHeaders)
		{
			if (gltfURI == null)
			{
				return this;
			}
			return IsValidURI(parameterName, gltfURI, validHeaders);
		}

		public ValidationContext IsValidURI(ValueLocation parameterName, string gltfURI, params string[] validHeaders)
		{
			Guard.NotNull(validHeaders, "validHeaders");
			try
			{
				Guard.IsValidURI(parameterName, gltfURI, validHeaders);
				return this;
			}
			catch (ArgumentException ex)
			{
				_SchemaThrow(parameterName, ex.Message);
			}
			return this;
		}

		[DebuggerStepThrough]
		internal void _LinkThrow(ValueLocation pname, string msg)
		{
			throw new LinkException(_Current, $"{pname}: {msg}");
		}

		public ValidationContext EnumsAreEqual<TValue>(ValueLocation parameterName, TValue value, TValue expected) where TValue : Enum
		{
			if (!value.Equals(expected))
			{
				_LinkThrow(parameterName, $"{value} must be equal to {expected}.");
			}
			return this;
		}

		public ValidationContext IsNullOrIndex<T>(ValueLocation parameterName, int? index, IReadOnlyList<T> array)
		{
			return IsNullOrInRange(parameterName, index, 1, array);
		}

		public ValidationContext IsNullOrInRange<T>(ValueLocation parameterName, int? offset, int length, IReadOnlyList<T> array)
		{
			if (!offset.HasValue)
			{
				return this;
			}
			NonNegative($"{parameterName}.offset", offset.Value);
			IsGreater($"{parameterName}.length", length, 0);
			if (array == null)
			{
				_LinkThrow(parameterName, $".{offset} exceeds the number of available items (null).");
				return this;
			}
			if (offset > array.Count - length)
			{
				if (length == 1)
				{
					_LinkThrow(parameterName, $".{offset} exceeds the number of available items ({array.Count}).");
				}
				else
				{
					_LinkThrow(parameterName, $".{offset}+{length} exceeds the number of available items ({array.Count}).");
				}
			}
			return this;
		}

		public ValidationContext IsAnyOf<T>(ValueLocation parameterName, T value, params T[] values)
		{
			string separator = " ";
			if (!values.Contains(value))
			{
				_LinkThrow(parameterName, $"value {value} is not one of [{string.Join(separator, values)}].");
			}
			return this;
		}

		public ValidationContext IsAnyOf(ValueLocation parameterName, AttributeFormat value, params AttributeFormat[] values)
		{
			string separator = " ";
			if (!values.Contains(value))
			{
				_LinkThrow(parameterName, $"value {value._GetDebuggerDisplay()} is not one of [{string.Join(separator, values.Select((AttributeFormat item) => item._GetDebuggerDisplay()))}].");
			}
			return this;
		}

		public ValidationContext IsSetCollection<T>(ValueLocation parameterName, IEnumerable<T> collection) where T : class
		{
			int num = 0;
			if (collection == null)
			{
				_LinkThrow(parameterName, "must not be null.");
				return this;
			}
			HashSet<T> hashSet = new HashSet<T>();
			foreach (T item in collection)
			{
				if (item == null)
				{
					_LinkThrow((parameterName, num), "Is NULL.");
				}
				if (hashSet.Contains(item))
				{
					_LinkThrow((parameterName, num), "Is duplicated.");
				}
				hashSet.Add(item);
				num++;
			}
			return this;
		}

		[DebuggerStepThrough]
		private void _DataThrow(ValueLocation pname, string msg)
		{
			throw new DataException(_Current, $"{pname}: {msg}");
		}

		public ValidationContext IsInRange<T>(ValueLocation pname, T value, T minInclusive, T maxInclusive) where T : IComparable<T>
		{
			if (value.CompareTo(minInclusive) == -1)
			{
				_DataThrow(pname, $"is below minimum {minInclusive} value: {value}");
			}
			if (value.CompareTo(maxInclusive) == 1)
			{
				_DataThrow(pname, $"is above maximum {maxInclusive} value: {value}");
			}
			return this;
		}

		public ValidationContext IsNullOrMatrix(ValueLocation pname, Matrix4x4? matrix, bool mustInvert = true, bool mustDecompose = true)
		{
			if (!matrix.HasValue)
			{
				return this;
			}
			Matrix4x4 matrix2 = matrix.Value;
			return IsMatrix(pname, in matrix2, mustInvert, mustDecompose);
		}

		public ValidationContext IsNullOrMatrix4x3(ValueLocation pname, Matrix4x4? matrix, bool mustInvert = true, bool mustDecompose = true)
		{
			if (!matrix.HasValue)
			{
				return this;
			}
			Matrix4x4 matrix2 = matrix.Value;
			return IsMatrix4x3(pname, in matrix2, mustInvert, mustDecompose);
		}

		public ValidationContext IsPosition(ValueLocation pname, in Vector3 position)
		{
			if (!position._IsFinite())
			{
				_DataThrow(pname, "Invalid Position");
			}
			return this;
		}

		public ValidationContext IsNormal(ValueLocation pname, in Vector3 normal)
		{
			if (!normal.IsNormalized())
			{
				_DataThrow(pname, "Invalid Normal");
			}
			return this;
		}

		public ValidationContext IsRotation(ValueLocation pname, in Quaternion rotation)
		{
			if (!rotation.IsNormalized())
			{
				_DataThrow(pname, "Invalid Rotation");
			}
			return this;
		}

		public ValidationContext IsMatrix(ValueLocation pname, in Matrix4x4 matrix, bool mustInvert = true, bool mustDecompose = true)
		{
			Matrix4x4Factory.MatrixCheck matrixCheck = Matrix4x4Factory.MatrixCheck.NonZero;
			if (mustInvert)
			{
				matrixCheck |= Matrix4x4Factory.MatrixCheck.Invertible;
			}
			if (mustDecompose)
			{
				matrixCheck |= Matrix4x4Factory.MatrixCheck.Decomposable;
			}
			if (!matrix.IsValid(matrixCheck))
			{
				_DataThrow(pname, "Invalid Matrix");
			}
			return this;
		}

		public ValidationContext IsMatrix4x3(ValueLocation pname, in Matrix4x4 matrix, bool mustInvert = true, bool mustDecompose = true)
		{
			Matrix4x4Factory.MatrixCheck matrixCheck = Matrix4x4Factory.MatrixCheck.IdentityColumn4;
			if (mustInvert)
			{
				matrixCheck |= Matrix4x4Factory.MatrixCheck.Invertible;
			}
			if (mustDecompose)
			{
				matrixCheck |= Matrix4x4Factory.MatrixCheck.Decomposable;
			}
			if (!matrix.IsValid(matrixCheck))
			{
				_DataThrow(pname, "Invalid Matrix");
			}
			return this;
		}

		public ValidationContext ArePositions(ValueLocation pname, IList<Vector3> positions)
		{
			Guard.NotNull(positions, "positions");
			for (int i = 0; i < positions.Count; i++)
			{
				ValueLocation pname2 = (pname, i);
				Vector3 position = positions[i];
				IsPosition(pname2, in position);
			}
			return this;
		}

		public ValidationContext AreNormals(ValueLocation pname, IList<Vector3> normals)
		{
			Guard.NotNull(normals, "normals");
			for (int i = 0; i < normals.Count; i++)
			{
				ValueLocation pname2 = (pname, i);
				Vector3 normal = normals[i];
				IsNormal(pname2, in normal);
			}
			return this;
		}

		public ValidationContext AreTangents(ValueLocation pname, IList<Vector4> tangents)
		{
			Guard.NotNull(tangents, "tangents");
			for (int i = 0; i < tangents.Count; i++)
			{
				if (!tangents[i].IsValidTangent())
				{
					_DataThrow((pname, i), "Invalid Tangent");
				}
			}
			return this;
		}

		public ValidationContext AreRotations(ValueLocation pname, IList<Quaternion> rotations)
		{
			Guard.NotNull(rotations, "rotations");
			for (int i = 0; i < rotations.Count; i++)
			{
				if (!rotations[i].IsNormalized())
				{
					_DataThrow((pname, i), "Invalid Rotation");
				}
			}
			return this;
		}

		public ValidationContext AreJoints(ValueLocation pname, IList<Vector4> joints, int skinsMaxJointCount)
		{
			Guard.NotNull(joints, "joints");
			for (int i = 0; i < joints.Count; i++)
			{
				Vector4 v = joints[i];
				if (!v._IsFinite())
				{
					_DataThrow((pname, i), "Is not finite");
				}
				if (v.X < 0f || v.X >= (float)skinsMaxJointCount)
				{
					_DataThrow((pname, i), "Is out of bounds");
				}
				if (v.Y < 0f || v.Y >= (float)skinsMaxJointCount)
				{
					_DataThrow((pname, i), "Is out of bounds");
				}
				if (v.Z < 0f || v.Z >= (float)skinsMaxJointCount)
				{
					_DataThrow((pname, i), "Is out of bounds");
				}
				if (v.W < 0f || v.W >= (float)skinsMaxJointCount)
				{
					_DataThrow((pname, i), "Is out of bounds");
				}
			}
			return this;
		}

		public ValidationContext That(Action action)
		{
			Guard.NotNull(action, "action");
			try
			{
				action();
			}
			catch (ArgumentException ex)
			{
				_DataThrow(ex.ParamName, ex.Message);
			}
			return this;
		}
	}
	public readonly struct ValueLocation
	{
		private readonly string _Name;

		private readonly int _Index;

		public static implicit operator ValueLocation(int index)
		{
			return new ValueLocation(string.Empty, index);
		}

		public static implicit operator ValueLocation(int? index)
		{
			return new ValueLocation(string.Empty, index.GetValueOrDefault());
		}

		public static implicit operator ValueLocation(string name)
		{
			return new ValueLocation(name);
		}

		public static implicit operator ValueLocation((string name, int index) tuple)
		{
			return new ValueLocation(tuple.name, tuple.index);
		}

		public static implicit operator ValueLocation((string name, int? index) tuple)
		{
			return new ValueLocation(tuple.name, tuple.index.GetValueOrDefault());
		}

		public static implicit operator string(ValueLocation location)
		{
			return location.ToString();
		}

		private ValueLocation(string name, int idx1 = -1)
		{
			_Name = name;
			_Index = idx1;
		}

		public override string ToString()
		{
			if (_Index >= 0)
			{
				return $"{_Name}[{_Index}]";
			}
			return _Name;
		}

		public string ToString(JsonSerializable target, string message)
		{
			return ToString(target) + " " + message;
		}

		public string ToString(JsonSerializable target)
		{
			if (target == null)
			{
				return ToString();
			}
			string text = target.GetType().Name;
			PropertyInfo property = target.GetType().GetProperty("LogicalIndex");
			if (property != null)
			{
				object value = property.GetValue(target);
				text += $"[{value}]";
			}
			return text + ToString();
		}
	}
	public enum ValidationMode
	{
		Skip,
		TryFix,
		Strict
	}
	[DebuggerStepThrough]
	public sealed class ValidationResult
	{
		private readonly ModelRoot _Root;

		private readonly ValidationMode _Mode;

		private readonly bool _InstantThrow;

		private readonly List<Exception> _Errors = new List<Exception>();

		public ModelRoot Root => _Root;

		public ValidationMode Mode => _Mode;

		public IEnumerable<Exception> Errors => _Errors;

		public bool HasErrors => _Errors.Count > 0;

		public ValidationResult(ModelRoot root, ValidationMode mode, bool instantThrow = false)
		{
			_Root = root;
			_Mode = mode;
			_InstantThrow = instantThrow;
		}

		public ValidationContext GetContext()
		{
			return new ValidationContext(this);
		}

		public void SetSchemaError(EndOfStreamException ex)
		{
			Guard.NotNull(ex, "ex");
			SetError(new SchemaException(null, ex.Message));
		}

		public void SetSchemaError(ModelRoot model, string error)
		{
			SetError(new SchemaException(model, error));
		}

		public void SetSchemaError(ModelRoot model, JsonException ex)
		{
			SetError(new SchemaException(model, ex));
		}

		public void SetModelError(FormatException ex)
		{
			SetError(new ModelException(null, ex));
		}

		public void SetModelError(ModelRoot model, ArgumentException ex)
		{
			SetError(new ModelException(model, ex));
		}

		public void SetError(ModelException ex)
		{
			if (_InstantThrow)
			{
				throw ex;
			}
			_Errors.Add(ex);
		}
	}
}
namespace SharpGLTF.Transforms
{
	[DebuggerDisplay("AffineTransform {ToDebuggerDisplayString(),nq}")]
	public readonly struct AffineTransform : IEquatable<AffineTransform>
	{
		private const string _CannotDecomposeError = "Matrix is invalid or skewed.";

		private const string _RequiresSRTError = "Needs to be in SRT representation. Call GetDecomposed() first.";

		public static readonly AffineTransform Identity = new AffineTransform(null, null, null);

		private const int DATA_UNDEFINED = 0;

		private const int DATA_SRT = 1;

		private const int DATA_MAT = 2;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly int _Representation;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M11;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M12;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M13;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M21;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M22;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M23;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M31;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M32;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly float _M33;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private readonly Vector3 _Translation;

		public bool IsValid
		{
			get
			{
				if (_Representation == 0)
				{
					return false;
				}
				if (!Translation._IsFinite())
				{
					return false;
				}
				if (!_M11._IsFinite())
				{
					return false;
				}
				if (!_M12._IsFinite())
				{
					return false;
				}
				if (!_M13._IsFinite())
				{
					return false;
				}
				if (!_M21._IsFinite())
				{
					return false;
				}
				if (!_M22._IsFinite())
				{
					return false;
				}
				if (!_M23._IsFinite())
				{
					return false;
				}
				if (!_M31._IsFinite())
				{
					return false;
				}
				if (!_M32._IsFinite())
				{
					return false;
				}
				if (!_M33._IsFinite())
				{
					return false;
				}
				return true;
			}
		}

		public bool IsMatrix => _Representation == 2;

		public bool IsSRT => _Representation == 1;

		public Vector3 Scale => _GetScale();

		public Quaternion Rotation => _GetRotation();

		public Vector3 Translation => _Translation;

		public Matrix4x4 Matrix => _GetMatrix();

		public bool IsLosslessDecomposable
		{
			get
			{
				_VerifyDefined();
				if (IsSRT)
				{
					return true;
				}
				if (_M11 != 0f)
				{
					return false;
				}
				if (_M12 == 0f)
				{
					return false;
				}
				if (_M13 == 0f)
				{
					return false;
				}
				if (_M21 == 0f)
				{
					return false;
				}
				if (_M22 != 0f)
				{
					return false;
				}
				if (_M23 == 0f)
				{
					return false;
				}
				if (_M31 == 0f)
				{
					return false;
				}
				if (_M32 == 0f)
				{
					return false;
				}
				if (_M33 != 0f)
				{
					return false;
				}
				return true;
			}
		}

		public bool IsIdentity
		{
			get
			{
				if (IsSRT)
				{
					if (Translation != Vector3.Zero)
					{
						return false;
					}
					if (_M11 != 1f)
					{
						return false;
					}
					if (_M12 != 1f)
					{
						return false;
					}
					if (_M13 != 1f)
					{
						return false;
					}
					if (_M21 != 0f)
					{
						return false;
					}
					if (_M22 != 0f)
					{
						return false;
					}
					if (_M23 != 0f)
					{
						return false;
					}
					if (_M31 != 1f)
					{
						return false;
					}
				}
				else if (IsMatrix)
				{
					if (Translation != Vector3.Zero)
					{
						return false;
					}
					if (_M11 != 1f)
					{
						return false;
					}
					if (_M12 != 0f)
					{
						return false;
					}
					if (_M13 != 0f)
					{
						return false;
					}
					if (_M21 != 0f)
					{
						return false;
					}
					if (_M22 != 1f)
					{
						return false;
					}
					if (_M23 != 0f)
					{
						return false;
					}
					if (_M31 != 0f)
					{
						return false;
					}
					if (_M32 != 0f)
					{
						return false;
					}
					if (_M33 != 1f)
					{
						return false;
					}
				}
				else
				{
					_VerifyDefined();
				}
				return true;
			}
		}

		internal string ToDebuggerDisplayString()
		{
			if (!IsValid)
			{
				return "INVALID";
			}
			if (IsIdentity)
			{
				return "IDENTITY";
			}
			if (TryDecompose(out var transform))
			{
				Vector3 vector = transform._GetScale();
				Quaternion quaternion = transform._GetRotation();
				string text = string.Empty;
				Vector3 vector2 = Vector3.Max(Vector3.Zero, vector - Vector3.One);
				if (vector2.X > 1E-06f || vector2.Y > 1E-06f || vector2.Z > 1E-06f)
				{
					text += $"\ud835\udc12:{vector} ";
				}
				if (quaternion != Quaternion.Identity)
				{
					text += $"\ud835\udc11:{quaternion} ";
				}
				if (transform.Translation != Vector3.Zero)
				{
					text += $"\ud835\udebb:{transform.Translation} ";
				}
				return text;
			}
			return "Skewed Matrix ";
		}

		public static implicit operator AffineTransform((Quaternion r, Vector3 t) xform)
		{
			return new AffineTransform(null, xform.r, xform.t);
		}

		public static implicit operator AffineTransform(Matrix4x4 matrix)
		{
			return new AffineTransform(matrix);
		}

		public static implicit operator AffineTransform(Quaternion rotation)
		{
			return new AffineTransform(rotation);
		}

		public static AffineTransform CreateDecomposed(Matrix4x4 matrix)
		{
			if (!Matrix4x4.Decompose(matrix, out var scale, out var rotation, out var translation))
			{
				throw new ArgumentException("Can't decompose", "matrix");
			}
			return new AffineTransform(scale, rotation, translation);
		}

		public static AffineTransform CreateFromAny(Matrix4x4? matrix, Vector3? scale, Quaternion? rotation, Vector3? translation)
		{
			if (matrix.HasValue)
			{
				Guard.MustBeNull(scale, "scale");
				Guard.MustBeNull(scale, "rotation");
				Guard.MustBeNull(scale, "translation");
				return new AffineTransform(matrix.Value);
			}
			return new AffineTransform(scale, rotation, translation);
		}

		public AffineTransform WithScale(Vector3 scale)
		{
			if (_Representation == 0)
			{
				return new AffineTransform(scale, null, null);
			}
			AffineTransform affineTransform = this;
			if (affineTransform.IsMatrix)
			{
				affineTransform = affineTransform.GetDecomposed();
			}
			return new AffineTransform(scale, affineTransform.Rotation, affineTransform.Translation);
		}

		public AffineTransform WithRotation(Quaternion rotation)
		{
			if (_Representation == 0)
			{
				return new AffineTransform(null, rotation, null);
			}
			AffineTransform affineTransform = this;
			if (affineTransform.IsMatrix)
			{
				affineTransform = affineTransform.GetDecomposed();
			}
			return new AffineTransform(affineTransform.Scale, rotation, affineTransform.Translation);
		}

		public AffineTransform WithTranslation(Vector3 translation)
		{
			if (_Representation == 0)
			{
				return new AffineTransform(null, null, translation);
			}
			if (IsSRT)
			{
				return new AffineTransform(Scale, Rotation, translation);
			}
			Matrix4x4 matrix = Matrix;
			matrix.Translation = translation;
			return matrix;
		}

		public AffineTransform(Vector3? scale, Quaternion? rotation, Vector3? translation)
			: this(scale ?? Vector3.One, rotation ?? Quaternion.Identity, translation ?? Vector3.Zero)
		{
		}

		public AffineTransform(Quaternion rotation)
			: this(Vector3.One, rotation, Vector3.Zero)
		{
		}

		public AffineTransform(Quaternion rotation, Vector3 translation)
			: this(Vector3.One, rotation, translation)
		{
		}

		public AffineTransform(Vector3 scale, Quaternion rotation, Vector3 translation)
		{
			rotation = rotation.Sanitized();
			Guard.IsTrue(scale._IsFinite(), "scale");
			Guard.IsTrue(rotation._IsFinite(), "rotation");
			Guard.IsTrue(translation._IsFinite(), "translation");
			_Representation = 1;
			_M11 = scale.X;
			_M12 = scale.Y;
			_M13 = scale.Z;
			_M21 = rotation.X;
			_M22 = rotation.Y;
			_M23 = rotation.Z;
			_M31 = rotation.W;
			_M32 = 0f;
			_M33 = 0f;
			_Translation = translation;
		}

		public AffineTransform(Matrix4x4 matrix)
		{
			Matrix4x4Factory.GuardMatrix("matrix", matrix, Matrix4x4Factory.MatrixCheck.WorldTransform);
			_Representation = 2;
			_M11 = matrix.M11;
			_M12 = matrix.M12;
			_M13 = matrix.M13;
			_M21 = matrix.M21;
			_M22 = matrix.M22;
			_M23 = matrix.M23;
			_M31 = matrix.M31;
			_M32 = matrix.M32;
			_M33 = matrix.M33;
			_Translation = matrix.Translation;
		}

		public override int GetHashCode()
		{
			return _Translation.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (obj is AffineTransform other)
			{
				return Equals(other);
			}
			return false;
		}

		public bool Equals(AffineTransform other)
		{
			if (_Representation != other._Representation)
			{
				return false;
			}
			if (_Translation != other._Translation)
			{
				return false;
			}
			if (_M11 != other._M11)
			{
				return false;
			}
			if (_M12 != other._M12)
			{
				return false;
			}
			if (_M13 != other._M13)
			{
				return false;
			}
			if (_M21 != other._M21)
			{
				return false;
			}
			if (_M22 != other._M22)
			{
				return false;
			}
			if (_M23 != other._M23)
			{
				return false;
			}
			if (_M31 != other._M31)
			{
				return false;
			}
			if (IsMatrix && other.IsMatrix)
			{
				if (_M32 != other._M32)
				{
					return false;
				}
				if (_M33 != other._M33)
				{
					return false;
				}
			}
			return true;
		}

		public static bool operator ==(in AffineTransform a, in AffineTransform b)
		{
			return a.Equals(b);
		}

		public static bool operator !=(in AffineTransform a, in AffineTransform b)
		{
			return !a.Equals(b);
		}

		public static bool AreGeometricallyEquivalent(in AffineTransform a, in AffineTransform b, float tolerance = 1E-05f)
		{
			Vector3 value = Transform(Vector3.UnitX, in a);
			Vector3 value2 = Transform(Vector3.UnitY, in a);
			Vector3 value3 = Transform(Vector3.UnitZ, in a);
			Vector3 value4 = Transform(Vector3.UnitX, in b);
			Vector3 value5 = Transform(Vector3.UnitY, in b);
			Vector3 value6 = Transform(Vector3.UnitZ, in b);
			if (Vector3.Distance(value, value4) > tolerance)
			{
				return false;
			}
			if (Vector3.Distance(value2, value5) > tolerance)
			{
				return false;
			}
			if (Vector3.Distance(value3, value6) > tolerance)
			{
				return false;
			}
			return true;
		}

		public AffineTransform GetDecomposed()
		{
			if (!TryDecompose(out var transform))
			{
				throw new InvalidOperationException("Matrix is invalid or skewed.");
			}
			return transform;
		}

		public bool TryDecompose(out AffineTransform transform)
		{
			if (IsSRT)
			{
				transform = this;
				return true;
			}
			if (IsLosslessDecomposable)
			{
				transform = new AffineTransform(new Vector3(_M11, _M22, _M33), Quaternion.Identity, Translation);
				return true;
			}
			Vector3 scale;
			Quaternion rotation;
			Vector3 translation;
			bool flag = Matrix4x4.Decompose(Matrix, out scale, out rotation, out translation);
			transform = (flag ? new AffineTransform(scale, rotation, translation) : this);
			return flag;
		}

		public bool TryDecompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation)
		{
			if (IsSRT)
			{
				scale = _GetScale();
				rotation = _GetRotation();
				translation = _Translation;
				return true;
			}
			if (IsLosslessDecomposable)
			{
				scale = new Vector3(_M11, _M22, _M33);
				rotation = Quaternion.Identity;
				translation = _Translation;
				return true;
			}
			return Matrix4x4.Decompose(Matrix, out scale, out rotation, out translation);
		}

		public static AffineTransform Blend(ReadOnlySpan<AffineTransform> transforms, ReadOnlySpan<float> weights)
		{
			if (transforms.Length == 0)
			{
				return Identity;
			}
			if (transforms.Length == 1)
			{
				return transforms[0];
			}
			Vector3 zero = Vector3.Zero;
			Quaternion quaternion = default(Quaternion);
			Vector3 zero2 = Vector3.Zero;
			float num = 0f;
			for (int i = 0; i < transforms.Length; i++)
			{
				Guard.IsTrue(transforms[i].IsValid, "transforms");
				Guard.IsTrue(transforms[i].TryDecompose(out var scale, out var rotation, out var translation), $"Can't decompose [{i}]");
				float num2 = weights[i];
				zero += scale * num2;
				zero2 += translation * num2;
				num += num2;
				quaternion = ((i != 0) ? Quaternion.Slerp(rotation, quaternion, num2 / num) : rotation);
			}
			quaternion = Quaternion.Normalize(quaternion);
			return new AffineTransform(zero, quaternion, zero2);
		}

		public static AffineTransform operator *(in AffineTransform a, in AffineTransform b)
		{
			return Multiply(in a, in b);
		}

		public static AffineTransform Multiply(in AffineTransform a, in AffineTransform b)
		{
			Guard.IsFalse(a._Representation == 0, "a");
			Guard.IsFalse(b._Representation == 0, "b");
			if (a.IsMatrix || b.IsMatrix)
			{
				return new AffineTransform(a.Matrix * b.Matrix);
			}
			Vector3 scale = b.Scale;
			if (scale.X != scale.Y || scale.X != scale.Z)
			{
				return new AffineTransform(a.Matrix * b.Matrix);
			}
			Vector3 scale2 = scale * a.Scale;
			Quaternion rotation = b.Rotation;
			Quaternion rotation2 = Quaternion.Multiply(rotation, a.Rotation);
			Vector3 translation = b.Translation + _Vector3Transform(a.Translation * scale, rotation);
			return new AffineTransform(scale2, rotation2, translation);
		}

		public static bool TryInvert(in AffineTransform xform, out AffineTransform inverse)
		{
			if (xform.IsMatrix)
			{
				if (Matrix4x4.Invert(xform.Matrix, out var result))
				{
					result.M44 = 1f;
					inverse = result;
					return true;
				}
				inverse = default(AffineTransform);
				return false;
			}
			if (xform.IsSRT)
			{
				if (xform.Rotation.IsIdentity)
				{
					Vector3 vector = Vector3.One / xform.Scale;
					Vector3 translation = -vector * xform.Translation;
					inverse = new AffineTransform(vector, Quaternion.Identity, translation);
				}
				else
				{
					if (xform.Scale.X != xform.Scale.Y || xform.Scale.Y != xform.Scale.Z)
					{
						AffineTransform xform2 = xform.Matrix;
						return TryInvert(in xform2, out inverse);
					}
					float num = 1f / xform.Scale.X;
					Quaternion quaternion = Quaternion.Normalize(Quaternion.Conjugate(xform.Rotation));
					Vector3 translation2 = (0f - num) * _Vector3Transform(xform.Translation, quaternion);
					inverse = new AffineTransform(new Vector3(num), quaternion, translation2);
				}
				return true;
			}
			inverse = default(AffineTransform);
			return false;
		}

		private static Vector3 Transform(Vector3 vector, in AffineTransform xform)
		{
			if (xform.IsMatrix)
			{
				return Vector3.Transform(vector, xform.Matrix);
			}
			if (xform.IsSRT)
			{
				vector *= xform.Scale;
				vector = _Vector3Transform(vector, xform.Rotation);
				vector += xform.Translation;
				return vector;
			}
			throw new ArgumentException("Undefined transform", "xform");
		}

		public static Vector3 TransformNormal(Vector3 vector, in AffineTransform xform)
		{
			if (xform.IsMatrix)
			{
				return Vector3.TransformNormal(vector, xform.Matrix);
			}
			if (xform.IsSRT)
			{
				vector *= xform.Scale;
				vector = _Vector3Transform(vector, xform.Rotation);
				return vector;
			}
			throw new ArgumentException("Undefined transform", "xform");
		}

		private void _VerifyDefined()
		{
			if (_Representation == 0)
			{
				throw new InvalidOperationException("Undefined");
			}
		}

		private Matrix4x4 _GetMatrix()
		{
			if (IsMatrix)
			{
				return new Matrix4x4(_M11, _M12, _M13, 0f, _M21, _M22, _M23, 0f, _M31, _M32, _M33, 0f, _Translation.X, _Translation.Y, _Translation.Z, 1f);
			}
			if (IsSRT)
			{
				Matrix4x4 result = Matrix4x4.CreateScale(Scale) * Matrix4x4.CreateFromQuaternion(Rotation);
				result.Translation = Translation;
				return result;
			}
			_VerifyDefined();
			return default(Matrix4x4);
		}

		private Vector3 _GetScale()
		{
			if (IsSRT)
			{
				return new Vector3(_M11, _M12, _M13);
			}
			throw new InvalidOperationException("Needs to be in SRT representation. Call GetDecomposed() first.");
		}

		private Quaternion _GetRotation()
		{
			if (IsSRT)
			{
				return new Quaternion(_M21, _M22, _M23, _M31);
			}
			throw new InvalidOperationException("Needs to be in SRT representation. Call GetDecomposed() first.");
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static Vector3 _Vector3Transform(Vector3 v, Quaternion q)
		{
			Vector3 vector = new Vector3(q.X, q.Y, q.Z);
			float w = q.W;
			return 2f * Vector3.Dot(vector, v) * vector + (w * w - Vector3.Dot(vector, vector)) * v + 2f * w * Vector3.Cross(vector, v);
		}
	}
	[DebuggerDisplay("{Index} = {Weight}")]
	internal readonly struct IndexWeight : IEquatable<IndexWeight>
	{
		public readonly int Index;

		public readonly float Weight;

		public static implicit operator IndexWeight((int Index, float Weight) pair)
		{
			return new IndexWeight(pair.Index, pair.Weight);
		}

		public static implicit operator IndexWeight(KeyValuePair<int, float> pair)
		{
			return new IndexWeight(pair.Key, pair.Value);
		}

		public IndexWeight((int Index, float Weight) pair)
		{
			(Index, Weight) = pair;
		}

		public IndexWeight(KeyValuePair<int, float> pair)
		{
			Index = pair.Key;
			Weight = pair.Value;
		}

		public IndexWeight(int i, float w)
		{
			Index = i;
			Weight = w;
		}

		public override int GetHashCode()
		{
			return Index.GetHashCode() ^ Weight.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (obj is IndexWeight other)
			{
				return Equals(other);
			}
			return false;
		}

		public bool Equals(IndexWeight other)
		{
			if (Index == other.Index)
			{
				return Weight == other.Weight;
			}
			return false;
		}

		public bool IsGreaterThan(in IndexWeight other)
		{
			float num = Math.Abs(Weight);
			float num2 = Math.Abs(other.Weight);
			if (num > num2)
			{
				return true;
			}
			if (num == num2 && Index < other.Index)
			{
				return true;
			}
			return false;
		}

		public static IndexWeight operator +(IndexWeight a, IndexWeight b)
		{
			if (a.Index != b.Index)
			{
				throw new InvalidOperationException("b");
			}
			return new IndexWeight(a.Index, a.Weight + b.Weight);
		}

		public static IndexWeight operator +(IndexWeight a, float w)
		{
			return new IndexWeight(a.Index, a.Weight + w);
		}

		public static bool IsWellFormed(ReadOnlySpan<IndexWeight> iw, out string err)
		{
			for (int i = 0; i < iw.Length; i++)
			{
				IndexWeight indexWeight = iw[i];
				if (indexWeight.Weight == 0f)
				{
					if (indexWeight.Index != 0)
					{
						err = "weightless items must have index 0.";
						return false;
					}
					continue;
				}
				for (int j = 0; j < i; j++)
				{
					IndexWeight indexWeight2 = iw[j];
					if (indexWeight2.Weight != 0f && indexWeight.Index == indexWeight2.Index)
					{
						err = "indices must be unique.";
						return false;
					}
				}
			}
			err = null;
			return true;
		}

		public static int InsertSorted(Span<IndexWeight> buffer, int length, IndexWeight item)
		{
			if (item.Weight == 0f)
			{
				return length;
			}
			for (int i = 0; i < length; i++)
			{
				if (buffer[i].Index != item.Index)
				{
					continue;
				}
				buffer[i] += item;
				IndexWeight indexWeight;
				for (; i > 1; indexWeight = buffer[i - 1], buffer[i - 1] = buffer[i], buffer[i] = indexWeight, i--)
				{
					switch (Math.Abs(buffer[i - 1].Weight).CompareTo(buffer[i].Weight))
					{
					case 0:
						if (buffer[i - 1].Index >= item.Index)
						{
							continue;
						}
						break;
					default:
						continue;
					case 1:
						break;
					}
					break;
				}
				return length;
			}
			int num = length;
			float value = Math.Abs(item.Weight);
			for (int j = 0; j < length; j++)
			{
				int num2 = Math.Abs(buffer[j].Weight).CompareTo(value);
				if (num2 != 1 && (num2 != 0 || buffer[j].Index >= item.Index))
				{
					num = j;
					break;
				}
			}
			if (num >= buffer.Length)
			{
				return buffer.Length;
			}
			length = Math.Min(length + 1, buffer.Length);
			for (int num3 = length - 1; num3 > num; num3--)
			{
				buffer[num3] = buffer[num3 - 1];
			}
			buffer[num] = item;
			return length;
		}

		public static int InsertUnsorted(Span<IndexWeight> sparse, in Vector4 idx0123, in Vector4 wgt0123)
		{
			int num = 0;
			if (wgt0123.X != 0f)
			{
				sparse[0] = ((int)idx0123.X, wgt0123.X);
				num++;
			}
			if (wgt0123.Y != 0f)
			{
				int num2 = (int)idx0123.Y;
				if (num == 1 && sparse[0].Index == num2)
				{
					sparse[0] += (IndexWeight)(num2, wgt0123.Y);
				}
				else
				{
					sparse[num++] = (num2, wgt0123.Y);
				}
			}
			if (wgt0123.Z != 0f)
			{
				int num3 = (int)idx0123.Z;
				if (num > 0 && sparse[0].Index == num3)
				{
					sparse[0] += (IndexWeight)(num3, wgt0123.Z);
				}
				else if (num > 1 && sparse[1].Index == num3)
				{
					sparse[1] += (IndexWeight)(num3, wgt0123.Z);
				}
				else
				{
					sparse[num++] = (num3, wgt0123.Z);
				}
			}
			if (wgt0123.W != 0f)
			{
				int num4 = (int)idx0123.W;
				if (num > 0 && sparse[0].Index == num4)
				{
					sparse[0] += (IndexWeight)(num4, wgt0123.W);
				}
				else if (num > 1 && sparse[1].Index == num4)
				{
					sparse[1] += (IndexWeight)(num4, wgt0123.W);
				}
				else if (num > 2 && sparse[2].Index == num4)
				{
					sparse[2] += (IndexWeight)(num4, wgt0123.W);
				}
				else
				{
					sparse[num++] = (num4, wgt0123.W);
				}
			}
			return num;
		}

		public static int InsertUnsorted(Span<IndexWeight> buffer, int length, IndexWeight item)
		{
			if (item.Weight == 0f)
			{
				return length;
			}
			for (int i = 0; i < length; i++)
			{
				if (buffer[i].Index == item.Index)
				{
					float num = buffer[i].Weight + item.Weight;
					buffer[i] = ((num == 0f) ? default(IndexWeight) : new IndexWeight(item.Index, num));
					return length;
				}
			}
			if (length < buffer.Length)
			{
				buffer[length] = item;
				return length + 1;
			}
			int num2 = -1;
			IndexWeight other = item;
			for (int j = 0; j < buffer.Length; j++)
			{
				if (!buffer[j].IsGreaterThan(in other))
				{
					num2 = j;
					other = buffer[j];
				}
			}
			if (num2 >= 0)
			{
				buffer[num2] = item;
			}
			return length;
		}

		public static int CopyTo(in SparseWeight8 src, Span<int> dstIndices, Span<float> dstWeights, int dstLength)
		{
			foreach (IndexWeight item in src._GetPairs())
			{
				int num = dstIndices.Slice(0, dstLength).IndexOf(item.Index);
				if (num < 0)
				{
					dstIndices[dstLength] = item.Index;
					dstWeights[dstLength] = item.Weight;
					dstLength++;
				}
				else
				{
					dstWeights[num] += item.Weight;
				}
			}
			return dstLength;
		}

		public static void BubbleSortByWeight(Span<IndexWeight> pairs)
		{
			for (int i = 0; i < pairs.Length - 1; i++)
			{
				bool flag = true;
				for (int j = 1; j < pairs.Length; j++)
				{
					int index = j - 1;
					IndexWeight indexWeight = pairs[index];
					IndexWeight other = pairs[j];
					if (!indexWeight.IsGreaterThan(in other))
					{
						pairs[index] = other;
						pairs[j] = indexWeight;
						flag = false;
					}
				}
				if (flag)
				{
					break;
				}
			}
		}

		public static void BubbleSortByIndex(Span<IndexWeight> pairs)
		{
			for (int i = 0; i < pairs.Length - 1; i++)
			{
				bool flag = true;
				for (int j = 1; j < pairs.Length; j++)
				{
					int index = j - 1;
					IndexWeight indexWeight = pairs[index];
					IndexWeight indexWeight2 = pairs[j];
					if (indexWeight.Index >= indexWeight2.Index && (indexWeight.Index != indexWeight2.Index || !(indexWeight.Weight > indexWeight2.Weight)))
					{
						pairs[index] = indexWeight2;
						pairs[j] = indexWeight;
						flag = false;
					}
				}
				if (flag)
				{
					break;
				}
			}
		}
	}
	[DebuggerTypeProxy(typeof(_Matrix4x4DoubleProxy))]
	public struct Matrix4x4Double : IEquatable<Matrix4x4Double>
	{
		private static readonly Matrix4x4Double _identity = new Matrix4x4Double(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);

		public double M11;

		public double M12;

		public double M13;

		public double M14;

		public double M21;

		public double M22;

		public double M23;

		public double M24;

		public double M31;

		public double M32;

		public double M33;

		public double M34;

		public double M41;

		public double M42;

		public double M43;

		public double M44;

		public static Matrix4x4Double Identity => _identity;

		public (double x, double y, double z) Translation
		{
			get
			{
				return (M41, M42, M43);
			}
			set
			{
				(M41, M42, M43) = value;
			}
		}

		public Matrix4x4Double(double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44)
		{
			M11 = m11;
			M12 = m12;
			M13 = m13;
			M14 = m14;
			M21 = m21;
			M22 = m22;
			M23 = m23;
			M24 = m24;
			M31 = m31;
			M32 = m32;
			M33 = m33;
			M34 = m34;
			M41 = m41;
			M42 = m42;
			M43 = m43;
			M44 = m44;
		}

		public Matrix4x4Double(Matrix4x4 other)
		{
			M11 = other.M11;
			M12 = other.M12;
			M13 = other.M13;
			M14 = other.M14;
			M21 = other.M21;
			M22 = other.M22;
			M23 = other.M23;
			M24 = other.M24;
			M31 = other.M31;
			M32 = other.M32;
			M33 = other.M33;
			M34 = other.M34;
			M41 = other.M41;
			M42 = other.M42;
			M43 = other.M43;
			M44 = other.M44;
		}

		public static Matrix4x4Double CreateTranslation(double xPosition, double yPosition, double zPosition)
		{
			Matrix4x4Double result = default(Matrix4x4Double);
			result.M11 = 1.0;
			result.M12 = 0.0;
			result.M13 = 0.0;
			result.M14 = 0.0;
			result.M21 = 0.0;
			result.M22 = 1.0;
			result.M23 = 0.0;
			result.M24 = 0.0;
			result.M31 = 0.0;
			result.M32 = 0.0;
			result.M33 = 1.0;
			result.M34 = 0.0;
			result.M41 = xPosition;
			result.M42 = yPosition;
			result.M43 = zPosition;
			result.M44 = 1.0;
			return result;
		}

		public static Matrix4x4Double CreateScale(double xScale, double yScale, double zScale)
		{
			Matrix4x4Double result = default(Matrix4x4Double);
			result.M11 = xScale;
			result.M12 = 0.0;
			result.M13 = 0.0;
			result.M14 = 0.0;
			result.M21 = 0.0;
			result.M22 = yScale;
			result.M23 = 0.0;
			result.M24 = 0.0;
			result.M31 = 0.0;
			result.M32 = 0.0;
			result.M33 = zScale;
			result.M34 = 0.0;
			result.M41 = 0.0;
			result.M42 = 0.0;
			result.M43 = 0.0;
			result.M44 = 1.0;
			return result;
		}

		public static Matrix4x4Double CreateFromQuaternion(Quaternion quaternion)
		{
			double num = quaternion.X;
			double num2 = quaternion.Y;
			double num3 = quaternion.Z;
			double num4 = quaternion.W;
			double num5 = num * num;
			double num6 = num2 * num2;
			double num7 = num3 * num3;
			double num8 = num * num2;
			double num9 = num3 * num4;
			double num10 = num3 * num;
			double num11 = num2 * num4;
			double num12 = num2 * num3;
			double num13 = num * num4;
			Matrix4x4Double result = default(Matrix4x4Double);
			result.M11 = 1.0 - 2.0 * (num6 + num7);
			result.M12 = 2.0 * (num8 + num9);
			result.M13 = 2.0 * (num10 - num11);
			result.M14 = 0.0;
			result.M21 = 2.0 * (num8 - num9);
			result.M22 = 1.0 - 2.0 * (num7 + num5);
			result.M23 = 2.0 * (num12 + num13);
			result.M24 = 0.0;
			result.M31 = 2.0 * (num10 + num11);
			result.M32 = 2.0 * (num12 - num13);
			result.M33 = 1.0 - 2.0 * (num6 + num5);
			result.M34 = 0.0;
			result.M41 = 0.0;
			result.M42 = 0.0;
			result.M43 = 0.0;
			result.M44 = 1.0;
			return result;
		}

		public static explicit operator Matrix4x4(Matrix4x4Double mat)
		{
			return new Matrix4x4((float)mat.M11, (float)mat.M12, (float)mat.M13, (float)mat.M14, (float)mat.M21, (float)mat.M22, (float)mat.M23, (float)mat.M24, (float)mat.M31, (float)mat.M32, (float)mat.M33, (float)mat.M34, (float)mat.M41, (float)mat.M42, (float)mat.M43, (float)mat.M44);
		}

		public static implicit operator Matrix4x4Double(Matrix4x4 mat)
		{
			return new Matrix4x4Double(mat.M11, mat.M12, mat.M13, mat.M14, mat.M21, mat.M22, mat.M23, mat.M24, mat.M31, mat.M32, mat.M33, mat.M34, mat.M41, mat.M42, mat.M43, mat.M44);
		}

		public override readonly int GetHashCode()
		{
			return M11.GetHashCode() + M12.GetHashCode() + M13.GetHashCode() + M14.GetHashCode() + M21.GetHashCode() + M22.GetHashCode() + M23.GetHashCode() + M24.GetHashCode() + M31.GetHashCode() + M32.GetHashCode() + M33.GetHashCode() + M34.GetHashCode() + M41.GetHashCode() + M42.GetHashCode() + M43.GetHashCode() + M44.GetHashCode();
		}

		public static bool operator ==(Matrix4x4Double value1, Matrix4x4Double value2)
		{
			if (value1.M11 == value2.M11 && value1.M22 == value2.M22 && value1.M33 == value2.M33 && value1.M44 == value2.M44 && value1.M12 == value2.M12 && value1.M13 == value2.M13 && value1.M14 == value2.M14 && value1.M21 == value2.M21 && value1.M23 == value2.M23 && value1.M24 == value2.M24 && value1.M31 == value2.M31 && value1.M32 == value2.M32 && value1.M34 == value2.M34 && value1.M41 == value2.M41 && value1.M42 == value2.M42)
			{
				return value1.M43 == value2.M43;
			}
			return false;
		}

		public static bool operator !=(Matrix4x4Double value1, Matrix4x4Double value2)
		{
			if (value1.M11 == value2.M11 && value1.M12 == value2.M12 && value1.M13 == value2.M13 && value1.M14 == value2.M14 && value1.M21 == value2.M21 && value1.M22 == value2.M22 && value1.M23 == value2.M23 && value1.M24 == value2.M24 && value1.M31 == value2.M31 && value1.M32 == value2.M32 && value1.M33 == value2.M33 && value1.M34 == value2.M34 && value1.M41 == value2.M41 && value1.M42 == value2.M42 && value1.M43 == value2.M43)
			{
				return value1.M44 != value2.M44;
			}
			return true;
		}

		public readonly bool Equals(Matrix4x4Double other)
		{
			return this == other;
		}

		public override readonly bool Equals(object obj)
		{
			if (obj is Matrix4x4Double matrix4x4Double)
			{
				return this == matrix4x4Double;
			}
			return false;
		}

		public static bool Invert(Matrix4x4Double matrix, out Matrix4x4Double result)
		{
			double m = matrix.M11;
			double m2 = matrix.M12;
			double m3 = matrix.M13;
			double m4 = matrix.M14;
			double m5 = matrix.M21;
			double m6 = matrix.M22;
			double m7 = matrix.M23;
			double m8 = matrix.M24;
			double m9 = matrix.M31;
			double m10 = matrix.M32;
			double m11 = matrix.M33;
			double m12 = matrix.M34;
			double m13 = matrix.M41;
			double m14 = matrix.M42;
			double m15 = matrix.M43;
			double m16 = matrix.M44;
			double num = m11 * m16 - m12 * m15;
			double num2 = m10 * m16 - m12 * m14;
			double num3 = m10 * m15 - m11 * m14;
			double num4 = m9 * m16 - m12 * m13;
			double num5 = m9 * m15 - m11 * m13;
			double num6 = m9 * m14 - m10 * m13;
			double num7 = m6 * num - m7 * num2 + m8 * num3;
			double num8 = 0.0 - (m5 * num - m7 * num4 + m8 * num5);
			double num9 = m5 * num2 - m6 * num4 + m8 * num6;
			double num10 = 0.0 - (m5 * num3 - m6 * num5 + m7 * num6);
			double num11 = m * num7 + m2 * num8 + m3 * num9 + m4 * num10;
			if (Math.Abs(num11) < double.Epsilon)
			{
				result = new Matrix4x4Double(double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN, double.NaN);
				return false;
			}
			double num12 = 1.0 / num11;
			result.M11 = num7 * num12;
			result.M21 = num8 * num12;
			result.M31 = num9 * num12;
			result.M41 = num10 * num12;
			result.M12 = (0.0 - (m2 * num - m3 * num2 + m4 * num3)) * num12;
			result.M22 = (m * num - m3 * num4 + m4 * num5) * num12;
			result.M32 = (0.0 - (m * num2 - m2 * num4 + m4 * num6)) * num12;
			result.M42 = (m * num3 - m2 * num5 + m3 * num6) * num12;
			double num13 = m7 * m16 - m8 * m15;
			double num14 = m6 * m16 - m8 * m14;
			double num15 = m6 * m15 - m7 * m14;
			double num16 = m5 * m16 - m8 * m13;
			double num17 = m5 * m15 - m7 * m13;
			double num18 = m5 * m14 - m6 * m13;
			result.M13 = (m2 * num13 - m3 * num14 + m4 * num15) * num12;
			result.M23 = (0.0 - (m * num13 - m3 * num16 + m4 * num17)) * num12;
			result.M33 = (m * num14 - m2 * num16 + m4 * num18) * num12;
			result.M43 = (0.0 - (m * num15 - m2 * num17 + m3 * num18)) * num12;
			double num19 = m7 * m12 - m8 * m11;
			double num20 = m6 * m12 - m8 * m10;
			double num21 = m6 * m11 - m7 * m10;
			double num22 = m5 * m12 - m8 * m9;
			double num23 = m5 * m11 - m7 * m9;
			double num24 = m5 * m10 - m6 * m9;
			result.M14 = (0.0 - (m2 * num19 - m3 * num20 + m4 * num21)) * num12;
			result.M24 = (m * num19 - m3 * num22 + m4 * num23) * num12;
			result.M34 = (0.0 - (m * num20 - m2 * num22 + m4 * num24)) * num12;
			result.M44 = (m * num21 - m2 * num23 + m3 * num24) * num12;
			return true;
		}

		public static Matrix4x4Double Multiply(Matrix4x4Double value1, Matrix4x4Double value2)
		{
			return value1 * value2;
		}

		public static Matrix4x4Double operator *(Matrix4x4Double value1, Matrix4x4Double value2)
		{
			Matrix4x4Double result = default(Matrix4x4Double);
			result.M11 = value1.M11 * value2.M11 + value1.M12 * value2.M21 + value1.M13 * value2.M31 + value1.M14 * value2.M41;
			result.M12 = value1.M11 * value2.M12 + value1.M12 * value2.M22 + value1.M13 * value2.M32 + value1.M14 * value2.M42;
			result.M13 = value1.M11 * value2.M13 + value1.M12 * value2.M23 + value1.M13 * value2.M33 + value1.M14 * value2.M43;
			result.M14 = value1.M11 * value2.M14 + value1.M12 * value2.M24 + value1.M13 * value2.M34 + value1.M14 * value2.M44;
			result.M21 = value1.M21 * value2.M11 + value1.M22 * value2.M21 + value1.M23 * value2.M31 + value1.M24 * value2.M41;
			result.M22 = value1.M21 * value2.M12 + value1.M22 * value2.M22 + value1.M23 * value2.M32 + value1.M24 * value2.M42;
			result.M23 = value1.M21 * value2.M13 + value1.M22 * value2.M23 + value1.M23 * value2.M33 + value1.M24 * value2.M43;
			result.M24 = value1.M21 * value2.M14 + value1.M22 * value2.M24 + value1.M23 * value2.M34 + value1.M24 * value2.M44;
			result.M31 = value1.M31 * value2.M11 + value1.M32 * value2.M21 + value1.M33 * value2.M31 + value1.M34 * value2.M41;
			result.M32 = value1.M31 * value2.M12 + value1.M32 * value2.M22 + value1.M33 * value2.M32 + value1.M34 * value2.M42;
			result.M33 = value1.M31 * value2.M13 + value1.M32 * value2.M23 + value1.M33 * value2.M33 + value1.M34 * value2.M43;
			result.M34 = value1.M31 * value2.M14 + value1.M32 * value2.M24 + value1.M33 * value2.M34 + value1.M34 * value2.M44;
			result.M41 = value1.M41 * value2.M11 + value1.M42 * value2.M21 + value1.M43 * value2.M31 + value1.M44 * value2.M41;
			result.M42 = value1.M41 * value2.M12 + value1.M42 * value2.M22 + value1.M43 * value2.M32 + value1.M44 * value2.M42;
			result.M43 = value1.M41 * value2.M13 + value1.M42 * value2.M23 + value1.M43 * value2.M33 + value1.M44 * value2.M43;
			result.M44 = value1.M41 * value2.M14 + value1.M42 * value2.M24 + value1.M43 * value2.M34 + value1.M44 * value2.M44;
			return result;
		}
	}
	public static class Matrix4x4Factory
	{
		[Flags]
		public enum MatrixCheck
		{
			None = 0,
			Finite = 1,
			NonZero = 2,
			Identity = 4,
			IdentityColumn4 = 8,
			Invertible = 0x10,
			Decomposable = 0x20,
			PositiveDeterminant = 0x40,
			LocalTransform = 0x3A,
			WorldTransform = 0x1A,
			InverseBindMatrix = 0x1A
		}

		private static MatrixCheck _Validate(in Matrix4x4 matrix, MatrixCheck check, float tolerance = 0f)
		{
			if (!matrix._IsFinite())
			{
				return MatrixCheck.Finite;
			}
			Matrix4x4 result;
			if (check.HasFlag(MatrixCheck.NonZero))
			{
				Matrix4x4 matrix4x = matrix;
				result = default(Matrix4x4);
				if (matrix4x == result)
				{
					return MatrixCheck.NonZero;
				}
			}
			if (check.HasFlag(MatrixCheck.Identity) && matrix != Matrix4x4.Identity)
			{
				return MatrixCheck.Identity;
			}
			if (check.HasFlag(MatrixCheck.IdentityColumn4))
			{
				if (matrix.M14 != 0f)
				{
					return MatrixCheck.IdentityColumn4;
				}
				if (matrix.M24 != 0f)
				{
					return MatrixCheck.IdentityColumn4;
				}
				if (matrix.M34 != 0f)
				{
					return MatrixCheck.IdentityColumn4;
				}
				if (tolerance == 0f)
				{
					if (matrix.M44 != 1f)
					{
						return MatrixCheck.IdentityColumn4;
					}
				}
				else if (Math.Abs(matrix.M44 - 1f) > tolerance)
				{
					return MatrixCheck.IdentityColumn4;
				}
			}
			if (check.HasFlag(MatrixCheck.Invertible) && !Matrix4x4.Invert(matrix, out result))
			{
				return MatrixCheck.Invertible;
			}
			if (check.HasFlag(MatrixCheck.Decomposable) && !Matrix4x4.Decompose(matrix, out var _, out var _, out var _))
			{
				return MatrixCheck.Decomposable;
			}
			if (check.HasFlag(MatrixCheck.PositiveDeterminant) && matrix.GetDeterminant() <= 0f)
			{
				return MatrixCheck.PositiveDeterminant;
			}
			return MatrixCheck.None;
		}

		public static bool IsValid(in Matrix4x4 matrix, MatrixCheck check, float tolerance = 0f)
		{
			return _Validate(in matrix, check, tolerance) == MatrixCheck.None;
		}

		[DebuggerStepThrough]
		public static void GuardMatrix(string argName, Matrix4x4 matrix, MatrixCheck check, float tolerance = 0f)
		{
			MatrixCheck matrixCheck = _Validate(in matrix, check, tolerance);
			if (matrixCheck != 0)
			{
				throw new ArgumentException($"Invalid Matrix. Fail: {matrixCheck}", argName);
			}
		}

		public static Matrix4x4 CreateFromRows(Vector3 rowX, Vector3 rowY, Vector3 rowZ)
		{
			return new Matrix4x4(rowX.X, rowX.Y, rowX.Z, 0f, rowY.X, rowY.Y, rowY.Z, 0f, rowZ.X, rowZ.Y, rowZ.Z, 0f, 0f, 0f, 0f, 1f);
		}

		public static Matrix4x4 CreateFromRows(Vector3 rowX, Vector3 rowY, Vector3 rowZ, Vector3 translation)
		{
			return new Matrix4x4(rowX.X, rowX.Y, rowX.Z, 0f, rowY.X, rowY.Y, rowY.Z, 0f, rowZ.X, rowZ.Y, rowZ.Z, 0f, translation.X, translation.Y, translation.Z, 1f);
		}

		public static Matrix4x4 CreateFrom(Matrix4x4? transform, Vector3? scale, Quaternion? rotation, Vector3? translation)
		{
			if (transform.HasValue)
			{
				return transform.Value;
			}
			return new AffineTransform(scale, rotation, translation).Matrix;
		}

		public static Matrix4x4 LocalToWorld(in Matrix4x4 parentWorld, in Matrix4x4 childLocal)
		{
			GuardMatrix("parentWorld", parentWorld, MatrixCheck.WorldTransform);
			GuardMatrix("childLocal", childLocal, MatrixCheck.LocalTransform);
			return childLocal * parentWorld;
		}

		public static Matrix4x4 WorldToLocal(in Matrix4x4 parentWorld, in Matrix4x4 childWorld)
		{
			GuardMatrix("parentWorld", parentWorld, MatrixCheck.WorldTransform);
			GuardMatrix("childWorld", childWorld, MatrixCheck.WorldTransform);
			return childWorld * parentWorld.Inverse();
		}

		public static void NormalizeMatrix(ref Matrix4x4 xform)
		{
			Vector3 vector = new Vector3(xform.M11, xform.M12, xform.M13);
			Vector3 vector2 = new Vector3(xform.M21, xform.M22, xform.M23);
			Vector3 vector3 = new Vector3(xform.M31, xform.M32, xform.M33);
			float num = vector.Length();
			float num2 = vector2.Length();
			float num3 = vector3.Length();
			vector /= num;
			vector2 /= num2;
			vector3 /= num3;
			float num4 = Math.Abs(Vector3.Dot(vector, vector2));
			float num5 = Math.Abs(Vector3.Dot(vector, vector3));
			float num6 = Math.Abs(Vector3.Dot(vector2, vector3));
			float num7 = num4 + num5;
			float num8 = num4 + num6;
			float num9 = num5 + num6;
			if (num7 < num8 && num7 < num9)
			{
				if (num8 < num9)
				{
					vector3 = Vector3.Cross(vector, vector2);
					vector2 = Vector3.Cross(vector3, vector);
				}
				else
				{
					vector2 = Vector3.Cross(vector3, vector);
					vector3 = Vector3.Cross(vector, vector2);
				}
			}
			else if (num8 < num7 && num8 < num9)
			{
				if (num7 < num9)
				{
					vector3 = Vector3.Cross(vector, vector2);
					vector = Vector3.Cross(vector2, vector3);
				}
				else
				{
					vector = Vector3.Cross(vector2, vector3);
					vector3 = Vector3.Cross(vector, vector2);
				}
			}
			else if (num7 < num8)
			{
				vector2 = Vector3.Cross(vector3, vector);
				vector = Vector3.Cross(vector2, vector3);
			}
			else
			{
				vector = Vector3.Cross(vector2, vector3);
				vector2 = Vector3.Cross(vector3, vector);
			}
			vector *= num;
			vector2 *= num2;
			vector3 *= num3;
			xform.M11 = vector.X;
			xform.M12 = vector.Y;
			xform.M13 = vector.Z;
			xform.M21 = vector2.X;
			xform.M22 = vector2.Y;
			xform.M23 = vector2.Z;
			xform.M31 = vector3.X;
			xform.M32 = vector3.Y;
			xform.M33 = vector3.Z;
		}
	}
	public interface IMaterialTransform
	{
		Vector2 MorphTexCoord(Vector2 texCoord, IReadOnlyList<Vector2> morphTargets);

		Vector4 MorphColors(Vector4 color, IReadOnlyList<Vector4> morphTargets);
	}
	public interface IGeometryTransform
	{
		bool Visible { get; }

		bool FlipFaces { get; }

		Vector3 TransformPosition(Vector3 localPosition, IReadOnlyList<Vector3> positionDeltas, in SparseWeight8 skinWeights);

		Vector3 TransformNormal(Vector3 localNormal, IReadOnlyList<Vector3> normalDeltas, in SparseWeight8 skinWeights);

		Vector4 TransformTangent(Vector4 tangent, IReadOnlyList<Vector3> tangentDeltas, in SparseWeight8 skinWeights);
	}
	public interface IGeometryInstancing
	{
		int InstancesCount { get; }

		IReadOnlyList<RigidTransform> WorldTransforms { get; }
	}
	public abstract class MorphTransform : IMaterialTransform
	{
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private SparseWeight8 _Weights;

		public const int COMPLEMENT_INDEX = 65536;

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		private bool _AbsoluteMorphTargets;

		public SparseWeight8 MorphWeights => _Weights;

		public bool AbsoluteMorphTargets => _AbsoluteMorphTargets;

		protected MorphTransform()
		{
			SparseWeight8 morphWeights = default(SparseWeight8);
			Update(in morphWeights);
		}

		protected MorphTransform(SparseWeight8 morphWeights, bool useAbsoluteMorphTargets)
		{
			Update(in morphWeights, useAbsoluteMorphTargets);
		}

		public void Update(in SparseWeight8 morphWeights, bool useAbsoluteMorphTargets = false)
		{
			_AbsoluteMorphTargets = useAbsoluteMorphTargets;
			if (morphWeights.IsWeightless)
			{
				_Weights = SparseWeight8.Create((65536, 1f));
			}
			else
			{
				_Weights = morphWeights.GetNormalizedWithComplement(65536);
			}
		}

		protected Vector2 MorphVectors(Vector2 value, IReadOnlyList<Vector2> morphTargets)
		{
			if (morphTargets == null || morphTargets.Count == 0)
			{
				return value;
			}
			if (_Weights.Index0 == 65536 && _Weights.Weight0 == 1f)
			{
				return value;
			}
			Vector2 zero = Vector2.Zero;
			if (_AbsoluteMorphTargets)
			{
				foreach (var nonZeroWeight in _Weights.GetNonZeroWeights())
				{
					int item = nonZeroWeight.Index;
					float item2 = nonZeroWeight.Weight;
					Vector2 vector = ((item == 65536) ? value : morphTargets[item]);
					zero += vector * item2;
				}
			}
			else
			{
				foreach (var nonZeroWeight2 in _Weights.GetNonZeroWeights())
				{
					int item3 = nonZeroWeight2.Index;
					float item4 = nonZeroWeight2.Weight;
					Vector2 vector2 = ((item3 == 65536) ? value : (value + morphTargets[item3]));
					zero += vector2 * item4;
				}
			}
			return zero;
		}

		protected Vector3 MorphVectors(Vector3 value, IReadOnlyList<Vector3> morphTargets)
		{
			if (morphTargets == null || morphTargets.Count == 0)
			{
				return value;
			}
			if (_Weights.Index0 == 65536 && _Weights.Weight0 == 1f)
			{
				return value;
			}
			Vector3 zero = Vector3.Zero;
			if (_AbsoluteMorphTargets)
			{
				foreach (var nonZeroWeight in _Weights.GetNonZeroWeights())
				{
					int item = nonZeroWeight.Index;
					float item2 = nonZeroWeight.Weight;
					Vector3 vector = ((item == 65536) ? value : morphTargets[item]);
					zero += vector * item2;
				}
			}
			else
			{
				foreach (var nonZeroWeight2 in _Weights.GetNonZeroWeights())
				{
					int item3 = nonZeroWeight2.Index;
					float item4 = nonZeroWeight2.Weight;
					Vector3 vector2 = ((item3 == 65536) ? value : (value + morphTargets[item3]));
					zer

UserLibs/SharpGLTF.Toolkit.dll

Decompiled a day ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using Microsoft.CodeAnalysis;
using SharpGLTF.Animations;
using SharpGLTF.Collections;
using SharpGLTF.Diagnostics;
using SharpGLTF.Geometry;
using SharpGLTF.Geometry.VertexTypes;
using SharpGLTF.IO;
using SharpGLTF.Materials;
using SharpGLTF.Memory;
using SharpGLTF.Runtime;
using SharpGLTF.Scenes;
using SharpGLTF.Schema2;
using SharpGLTF.Transforms;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyMetadata("IsTrimmable", "True")]
[assembly: AssemblyCompany("Vicente Penades")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2025 Vicente Penades")]
[assembly: AssemblyDescription("SharpGLTF is a C# library for reading and writing glTF2 3D models")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5c4bd9643aef7c600304eac85b1325bb249feb70")]
[assembly: AssemblyProduct("SharpGLTF.Toolkit")]
[assembly: AssemblyTitle("SharpGLTF.Toolkit")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/vpenades/SharpGLTF")]
[assembly: InternalsVisibleTo("SharpGLTF.Core.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100318e6698f4f41b26736d5881759c6afde44d17c06b63d2e383c915ca1fed6ec1b6eb2e1c38013feb2320224ace549b7701e22e6e0f7770e0d72b5c199f9e969bf2c2668c0ebeb035e539fb534d9ef24053aa9997d2d72534a6c1da8ab58e353ed6eb62ad9eb1f4a044893d7a50a226e4701d4e472a7dc1918caee6794d9c4cae")]
[assembly: InternalsVisibleTo("SharpGLTF.Toolkit.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100318e6698f4f41b26736d5881759c6afde44d17c06b63d2e383c915ca1fed6ec1b6eb2e1c38013feb2320224ace549b7701e22e6e0f7770e0d72b5c199f9e969bf2c2668c0ebeb035e539fb534d9ef24053aa9997d2d72534a6c1da8ab58e353ed6eb62ad9eb1f4a044893d7a50a226e4701d4e472a7dc1918caee6794d9c4cae")]
[assembly: InternalsVisibleTo("SharpGLTF.Ext.3DTiles.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100318e6698f4f41b26736d5881759c6afde44d17c06b63d2e383c915ca1fed6ec1b6eb2e1c38013feb2320224ace549b7701e22e6e0f7770e0d72b5c199f9e969bf2c2668c0ebeb035e539fb534d9ef24053aa9997d2d72534a6c1da8ab58e353ed6eb62ad9eb1f4a044893d7a50a226e4701d4e472a7dc1918caee6794d9c4cae")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
}
namespace SharpGLTF
{
	public abstract class BaseBuilder
	{
		public string Name { get; set; }

		public JsonNode Extras { get; set; }

		protected BaseBuilder()
		{
		}

		protected BaseBuilder(string name)
		{
			Name = name;
		}

		protected BaseBuilder(string name, JsonNode extras)
		{
			Name = name;
			Extras = extras;
		}

		protected BaseBuilder(BaseBuilder other)
		{
			Guard.NotNull(other, "other");
			Name = other.Name;
			Extras = other.Extras?.DeepClone();
		}

		protected static int GetContentHashCode(BaseBuilder x)
		{
			return (x?.Name?.GetHashCode(StringComparison.InvariantCulture)).GetValueOrDefault();
		}

		protected static bool AreEqualByContent(BaseBuilder x, BaseBuilder y)
		{
			if ((x, y).AreSameReference(out var result))
			{
				return result;
			}
			if (x.Name != y.Name)
			{
				return false;
			}
			if (x.Extras == null && y.Extras == null)
			{
				return true;
			}
			if (x.Extras == null)
			{
				return false;
			}
			if (y.Extras == null)
			{
				return false;
			}
			return x.Extras.DeepEquals(y.Extras, 9.999999747378752E-05);
		}

		internal void SetNameAndExtrasFrom(BaseBuilder source)
		{
			Name = source?.Name;
			Extras = source?.Extras?.DeepClone();
		}

		internal void SetNameAndExtrasFrom(LogicalChildOfRoot source)
		{
			Name = ((source != null) ? source.Name : null);
			Extras = ((source == null) ? null : ((ExtraProperties)source).Extras?.DeepClone());
		}

		internal void TryCopyNameAndExtrasTo(LogicalChildOfRoot target)
		{
			target.Name = Name;
			((ExtraProperties)target).Extras = Extras?.DeepClone();
		}
	}
	[DebuggerStepThrough]
	internal static class Guard
	{
		private static readonly IReadOnlyList<char> _InvalidRelativePathChars = (from c in Path.GetInvalidFileNameChars()
			where c != '/' && c != '\\'
			select c).ToArray();

		public static void NotNullOrEmpty(string target, string parameterName, string message = "")
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName, message);
			}
			if (!string.IsNullOrWhiteSpace(target))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = parameterName + " cannot be null or empty and cannot contain only blanks.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void FileNameMustBeValid(string fileName, string parameterName, string message = "")
		{
			NotNullOrEmpty(fileName, parameterName, message);
			char[] invalid = Path.GetInvalidFileNameChars();
			if (!fileName.Any((char c) => invalid.Contains(c)))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = fileName + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void FilePathMustBeValid(string filePath, string parameterName, string message = "")
		{
			NotNullOrEmpty(filePath, parameterName, message);
			filePath = Path.GetFullPath(filePath);
			bool flag = false;
			flag |= filePath.EndsWith(new string(Path.DirectorySeparatorChar, 1), StringComparison.Ordinal);
			if (!(flag | filePath.EndsWith(new string(Path.AltDirectorySeparatorChar, 1), StringComparison.Ordinal)))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = filePath + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void FilePathMustExist(string filePath, string parameterName, string message = "")
		{
			if (File.Exists(filePath))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = filePath + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void DirectoryPathMustExist(string dirPath, string parameterName, string message = "")
		{
			if (Directory.Exists(dirPath))
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = dirPath + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void MustExist(FileInfo finfo, string parameterName, string message = "")
		{
			if (finfo == null)
			{
				throw new ArgumentNullException("finfo");
			}
			if (finfo.Exists)
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = finfo.FullName + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void MustExist(DirectoryInfo dinfo, string parameterName, string message = "")
		{
			if (dinfo == null)
			{
				throw new ArgumentNullException("dinfo");
			}
			if (dinfo.Exists)
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = dinfo.FullName + " is invalid or does not exist.";
			}
			throw new ArgumentException(message, parameterName);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void NotNull(object target, string parameterName)
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void NotNull(object target, string parameterName, string message)
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName, message);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void MustBeNull(object target, string parameterName, string message = "")
		{
			if (target == null)
			{
				return;
			}
			throw new ArgumentException(parameterName, message);
		}

		public static void NotNullOrEmpty<T>(IEnumerable<T> target, string parameterName, string message = "")
		{
			if (target == null)
			{
				throw new ArgumentNullException(parameterName, message);
			}
			if (target.Any())
			{
				return;
			}
			if (string.IsNullOrWhiteSpace(message))
			{
				message = parameterName + " cannot be empty.";
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void MustBeEqualTo<TValue>(TValue value, TValue expected, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(expected) == 0)
			{
				return;
			}
			throw new ArgumentException(parameterName, $"{parameterName} {value} must be equal to {expected}.");
		}

		public static void MustBePositiveAndMultipleOf(int value, int padding, string parameterName, string message = "")
		{
			if (value < 0)
			{
				if (string.IsNullOrWhiteSpace(message))
				{
					message = parameterName + " must not be negative";
				}
				throw new ArgumentOutOfRangeException(message, parameterName);
			}
			if (value % padding != 0)
			{
				if (string.IsNullOrWhiteSpace(message))
				{
					message = $"{parameterName} is {value}; expected to be multiple of {padding}";
				}
				throw new ArgumentOutOfRangeException(message, parameterName);
			}
		}

		public static void MustBeLessThan<TValue>(TValue value, TValue max, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(max) < 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be less than {max}.");
		}

		public static void MustBeLessThanOrEqualTo<TValue>(TValue value, TValue max, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(max) > 0)
			{
				throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be less than or equal to {max}.");
			}
		}

		public static void MustBeGreaterThan<TValue>(TValue value, TValue min, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(min) > 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"Value {value} must be greater than {min}.");
		}

		public static void MustBeGreaterThanOrEqualTo<TValue>(TValue value, TValue min, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(min) >= 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be greater than or equal to {min}.");
		}

		public static void MustBeBetweenOrEqualTo<TValue>(TValue value, TValue minInclusive, TValue maxInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			if (value.CompareTo(minInclusive) >= 0 && value.CompareTo(maxInclusive) <= 0)
			{
				return;
			}
			throw new ArgumentOutOfRangeException(parameterName, $"{parameterName} {value} must be greater than or equal to {minInclusive} and less than or equal to {maxInclusive}.");
		}

		public static void IsTrue(bool target, string parameterName, string message = "")
		{
			if (target)
			{
				return;
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void IsFalse(bool target, string parameterName, string message = "")
		{
			if (!target)
			{
				return;
			}
			throw new ArgumentException(message, parameterName);
		}

		public static void IsValidURI(string parameterName, string gltfURI, params string[] validHeaders)
		{
			if (string.IsNullOrEmpty(gltfURI))
			{
				return;
			}
			foreach (string text in validHeaders)
			{
				if (gltfURI.StartsWith(text, StringComparison.OrdinalIgnoreCase))
				{
					string value = text + ",";
					if (gltfURI.StartsWith(value, StringComparison.OrdinalIgnoreCase) || gltfURI.StartsWith(text + ";base64,", StringComparison.OrdinalIgnoreCase))
					{
						return;
					}
					throw new ArgumentException(parameterName + " has invalid URI '" + gltfURI + "'.");
				}
			}
			if (gltfURI.Any((char c) => _InvalidRelativePathChars.Contains(c)))
			{
				throw new ArgumentException("Invalid URI '" + gltfURI + "'.");
			}
			if (gltfURI.Any((char chr) => char.IsWhiteSpace(chr)))
			{
				gltfURI = gltfURI._EscapeStringInternal();
			}
			if (Uri.TryCreate(gltfURI, UriKind.Relative, out Uri _))
			{
				return;
			}
			throw new ArgumentException("Invalid URI '" + gltfURI + "'.");
		}

		public static void MustShareLogicalParent(LogicalChildOfRoot a, LogicalChildOfRoot b, string parameterName)
		{
			MustShareLogicalParent((a != null) ? a.LogicalParent : null, "LogicalParent", b, parameterName);
		}

		public static void MustShareLogicalParent(ModelRoot a, string aName, LogicalChildOfRoot b, string bName)
		{
			if (a == null)
			{
				throw new ArgumentNullException(aName);
			}
			if (b == null)
			{
				throw new ArgumentNullException(bName);
			}
			if (a != b.LogicalParent)
			{
				throw new ArgumentException("LogicalParent mismatch", bName);
			}
		}

		public static void HasDynamicallyAccessedMembers(Type t, bool hasConstructors, bool hasMethods, bool hasProperties, bool hasFields, string parameterName)
		{
			DynamicallyAccessedMemberTypes dynamicallyAccessedMemberTypes = DynamicallyAccessedMemberTypes.None;
			if (hasConstructors)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
			}
			if (hasMethods)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicMethods;
			}
			if (hasProperties)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicProperties;
			}
			if (hasFields)
			{
				dynamicallyAccessedMemberTypes |= DynamicallyAccessedMemberTypes.PublicFields;
			}
			DynamicallyAccessedMembersAttribute customAttribute = t.GetCustomAttribute<DynamicallyAccessedMembersAttribute>();
			if (customAttribute == null || (customAttribute.MemberTypes & dynamicallyAccessedMemberTypes) != dynamicallyAccessedMemberTypes)
			{
				throw new ArgumentException($"{parameterName} {t.Name} must define  #if NET6_0_OR_GREATER  [DynamicallyAccessedMembers({dynamicallyAccessedMemberTypes})] #endif");
			}
		}
	}
	[DebuggerStepThrough]
	internal static class GuardAll
	{
		public static void NotNull<T>(IEnumerable<T> collection, string parameterName, string message = "")
		{
			Guard.NotNull(collection, "collection");
			foreach (T item in collection)
			{
				Guard.NotNull(item, parameterName, message);
			}
		}

		public static void AreTrue(IEnumerable<bool> collection, string parameterName, Func<int, string> messageFunc = null)
		{
			Guard.NotNull(collection, "collection");
			int num = 0;
			foreach (bool item in collection)
			{
				Guard.IsTrue(item, parameterName, messageFunc?.Invoke(num) ?? string.Empty);
				num++;
			}
		}

		public static void MustBeEqualTo<TValue>(IEnumerable<TValue> collection, TValue expected, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeEqualTo(item, expected, parameterName);
			}
		}

		public static void MustBeGreaterThan<TValue>(IEnumerable<TValue> collection, TValue minExclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeGreaterThan(item, minExclusive, parameterName);
			}
		}

		public static void MustBeLessThan<TValue>(IEnumerable<TValue> collection, TValue maxExclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeLessThan(item, maxExclusive, parameterName);
			}
		}

		public static void MustBeLessThanOrEqualTo<TValue>(IEnumerable<TValue> collection, TValue maxInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeLessThanOrEqualTo(item, maxInclusive, parameterName);
			}
		}

		public static void MustBeGreaterThanOrEqualTo<TValue>(IEnumerable<TValue> collection, TValue minInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeGreaterThanOrEqualTo(item, minInclusive, parameterName);
			}
		}

		public static void MustBeBetweenOrEqualTo<TValue>(IEnumerable<TValue> collection, TValue minInclusive, TValue maxInclusive, string parameterName) where TValue : IComparable<TValue>
		{
			Guard.NotNull(collection, "collection");
			foreach (TValue item in collection)
			{
				Guard.MustBeBetweenOrEqualTo(item, minInclusive, maxInclusive, parameterName);
			}
		}
	}
	internal static class _Extensions
	{
		private readonly struct _ListSelect<TSource, TResult> : IReadOnlyList<TResult>, IEnumerable<TResult>, IEnumerable, IReadOnlyCollection<TResult>
		{
			[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
			private readonly IReadOnlyList<TSource> _List;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly Func<TSource, TResult> _Selector;

			public TResult this[int index] => _Selector(_List[index]);

			public int Count => _List.Count;

			public _ListSelect(IReadOnlyList<TSource> list, Func<TSource, TResult> selector)
			{
				_List = list;
				_Selector = selector;
			}

			public IEnumerator<TResult> GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}
		}

		private readonly struct _CollectionSelect<TSource, TResult> : IReadOnlyCollection<TResult>, IEnumerable<TResult>, IEnumerable
		{
			[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
			private readonly IReadOnlyCollection<TSource> _List;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			private readonly Func<TSource, TResult> _Selector;

			public int Count => _List.Count;

			public _CollectionSelect(IReadOnlyCollection<TSource> list, Func<TSource, TResult> selector)
			{
				_List = list;
				_Selector = selector;
			}

			public IEnumerator<TResult> GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				foreach (TSource item in _List)
				{
					yield return _Selector(item);
				}
			}
		}

		private const float _UnitLengthThresholdVec3 = 0.00674f;

		private const float _UnitLengthThresholdVec4 = 0.00769f;

		private const float _UnitSumThresholdStep = 0.0039216f;

		internal static bool IsMultipleOf(this int value, int mult)
		{
			return value % mult == 0;
		}

		internal static int WordPadded(this int length)
		{
			int num = length & 3;
			return length + ((num != 0) ? (4 - num) : 0);
		}

		internal static bool _IsFinite(this float value)
		{
			return float.IsFinite(value);
		}

		internal static bool _IsFinite(this Vector2 v)
		{
			if (v.X._IsFinite())
			{
				return v.Y._IsFinite();
			}
			return false;
		}

		internal static bool _IsFinite(this Vector3 v)
		{
			if (v.X._IsFinite() && v.Y._IsFinite())
			{
				return v.Z._IsFinite();
			}
			return false;
		}

		internal static bool _IsFinite(this in Vector4 v)
		{
			if (v.X._IsFinite() && v.Y._IsFinite() && v.Z._IsFinite())
			{
				return v.W._IsFinite();
			}
			return false;
		}

		internal static bool _IsFinite(this in Matrix4x4 v)
		{
			if (!v.M11._IsFinite() || !v.M12._IsFinite() || !v.M13._IsFinite() || !v.M14._IsFinite())
			{
				return false;
			}
			if (!v.M21._IsFinite() || !v.M22._IsFinite() || !v.M23._IsFinite() || !v.M24._IsFinite())
			{
				return false;
			}
			if (!v.M31._IsFinite() || !v.M32._IsFinite() || !v.M33._IsFinite() || !v.M34._IsFinite())
			{
				return false;
			}
			if (!v.M41._IsFinite() || !v.M42._IsFinite() || !v.M43._IsFinite() || !v.M44._IsFinite())
			{
				return false;
			}
			return true;
		}

		internal static bool _IsFinite(this Quaternion v)
		{
			if (v.X._IsFinite() && v.Y._IsFinite() && v.Z._IsFinite())
			{
				return v.W._IsFinite();
			}
			return false;
		}

		internal static Vector3 WithLength(this Vector3 v, float len)
		{
			return Vector3.Normalize(v) * len;
		}

		internal static bool IsNormalized(this Vector3 normal)
		{
			if (!normal._IsFinite())
			{
				return false;
			}
			return Math.Abs(normal.Length() - 1f) <= 0.00674f;
		}

		internal static bool IsNormalized(this Quaternion rotation)
		{
			if (!rotation._IsFinite())
			{
				return false;
			}
			return Math.Abs(rotation.Length() - 1f) <= 0.00769f;
		}

		internal static Quaternion AsQuaternion(this Vector4 v)
		{
			return new Quaternion(v.X, v.Y, v.Z, v.W);
		}

		internal static Quaternion Sanitized(this Quaternion q)
		{
			if (!q.IsNormalized())
			{
				return Quaternion.Normalize(q);
			}
			return q;
		}

		internal static bool IsInRange(this Vector3 value, Vector3 min, Vector3 max)
		{
			if (value.X < min.X || value.X > max.X)
			{
				return false;
			}
			if (value.Y < min.Y || value.Y > max.Y)
			{
				return false;
			}
			if (value.Z < min.Z || value.Z > max.Z)
			{
				return false;
			}
			return true;
		}

		internal static bool IsInRange(this Vector4 value, Vector4 min, Vector4 max)
		{
			if (value.X < min.X || value.X > max.X)
			{
				return false;
			}
			if (value.Y < min.Y || value.Y > max.Y)
			{
				return false;
			}
			if (value.Z < min.Z || value.Z > max.Z)
			{
				return false;
			}
			if (value.W < min.W || value.W > max.W)
			{
				return false;
			}
			return true;
		}

		internal static bool IsRound(this Vector4 value)
		{
			Vector4 vector = new Vector4((int)value.X, (int)value.Y, (int)value.Z, (int)value.W);
			return value - vector == Vector4.Zero;
		}

		internal static void ValidateNormal(this Vector3 normal, string msg)
		{
			if (!normal._IsFinite())
			{
				throw new NotFiniteNumberException(msg + " is invalid.");
			}
			if (!normal.IsNormalized())
			{
				throw new ArithmeticException(msg + " is not unit length.");
			}
		}

		internal static void ValidateTangent(this Vector4 tangent, string msg)
		{
			if (tangent.W != 1f && tangent.W != -1f)
			{
				throw new ArithmeticException(msg);
			}
			new Vector3(tangent.X, tangent.Y, tangent.Z).ValidateNormal(msg);
		}

		internal static Vector3 SanitizeNormal(this Vector3 normal)
		{
			if (normal == Vector3.Zero)
			{
				return Vector3.UnitX;
			}
			if (!normal.IsNormalized())
			{
				return Vector3.Normalize(normal);
			}
			return normal;
		}

		internal static bool IsValidTangent(this Vector4 tangent)
		{
			if (tangent.W != 1f && tangent.W != -1f)
			{
				return false;
			}
			return new Vector3(tangent.X, tangent.Y, tangent.Z).IsNormalized();
		}

		internal static Vector4 SanitizeTangent(this Vector4 tangent)
		{
			Vector3 value = new Vector3(tangent.X, tangent.Y, tangent.Z).SanitizeNormal();
			float num = (float.IsNaN(tangent.W) ? 1f : tangent.W);
			return new Vector4(value, (num > 0f) ? 1 : (-1));
		}

		internal static Matrix4x4 Inverse(this in Matrix4x4 src)
		{
			if (!Matrix4x4.Invert(src, out var result))
			{
				Guard.IsTrue(target: false, "src", "Matrix cannot be inverted.");
			}
			if (src.M44 == 1f)
			{
				result.M44 = 1f;
			}
			return result;
		}

		internal static bool IsValid(this in Matrix4x4 matrix, MatrixCheck check, float tolerance = 0f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Matrix4x4Factory.IsValid(ref matrix, check, tolerance);
		}

		public static bool AreSameReference<T>(this (T x, T y) refs, out bool result) where T : class
		{
			if (refs.x == refs.y)
			{
				result = true;
				return true;
			}
			if (refs.x == null)
			{
				result = false;
				return true;
			}
			if (refs.y == null)
			{
				result = false;
				return true;
			}
			result = false;
			return false;
		}

		internal static int GetContentHashCode<T>(this IEnumerable<T> collection, int count = int.MaxValue)
		{
			if (collection == null)
			{
				return 0;
			}
			int num = 0;
			if (collection is IReadOnlyList<T> readOnlyList)
			{
				count = Math.Min(count, readOnlyList.Count);
				for (int i = 0; i < count; i++)
				{
					num ^= readOnlyList[i]?.GetHashCode() ?? 0;
					num *= 17;
				}
				return num;
			}
			foreach (T item in collection.Take(count))
			{
				num ^= item?.GetHashCode() ?? 0;
				num *= 17;
			}
			return num;
		}

		internal static ArraySegment<T> Slice<T>(this T[] array, int offset)
		{
			return new ArraySegment<T>(array, offset, array.Length - offset);
		}

		internal static T[] CloneArray<T>(this T[] srcArray)
		{
			if (srcArray == null)
			{
				return null;
			}
			T[] array = new T[srcArray.Length];
			srcArray.CopyTo(array, 0);
			return array;
		}

		internal static void Fill<T>(this IList<T> collection, T value)
		{
			for (int i = 0; i < collection.Count; i++)
			{
				collection[i] = value;
			}
		}

		internal static void Fill<T>(this T[] array, T value)
		{
			array.AsSpan().Fill(value);
		}

		internal static IReadOnlyList<T> EnsureList<T>(this IEnumerable<T> collection)
		{
			if (!(collection is IReadOnlyList<T> result))
			{
				return collection.ToList();
			}
			return result;
		}

		internal static bool IsEmpty<T>(this IReadOnlyList<T> list)
		{
			return list.Count == 0;
		}

		internal static int IndexOf<T>(this IReadOnlyList<T> collection, T value)
		{
			int count = collection.Count;
			for (int i = 0; i < count; i++)
			{
				if (object.Equals(collection[i], value))
				{
					return i;
				}
			}
			return -1;
		}

		internal static int IndexOf<T>(this IReadOnlyList<T> collection, Predicate<T> predicate)
		{
			int count = collection.Count;
			for (int i = 0; i < count; i++)
			{
				if (predicate(collection[i]))
				{
					return i;
				}
			}
			return -1;
		}

		internal static int IndexOf<T>(this IReadOnlyList<T> collection, T[] subset) where T : IEquatable<T>
		{
			int num = collection.Count - subset.Length;
			for (int i = 0; i < num; i++)
			{
				bool flag = false;
				for (int j = 0; j < subset.Length && collection[i + j].Equals(subset[j]); j++)
				{
					flag = true;
				}
				if (flag)
				{
					return i;
				}
			}
			return -1;
		}

		internal static void CopyTo<T>(this T[] src, int srcOffset, IList<T> dst, int dstOffset, int count)
		{
			ArraySegment<T> src2 = new ArraySegment<T>(src);
			src2.CopyTo(srcOffset, dst, dstOffset, count);
		}

		internal static void CopyTo<T>(this ArraySegment<T> src, int srcOffset, IList<T> dst, int dstOffset, int count)
		{
			if (dst is T[] destinationArray)
			{
				Array.Copy(src.Array, src.Offset + srcOffset, destinationArray, dstOffset, count);
				return;
			}
			for (int i = 0; i < count; i++)
			{
				dst[dstOffset + i] = src.Array[src.Offset + srcOffset + i];
			}
		}

		internal static void AddRange<Tin, Tout>(this IList<Tout> dst, IEnumerable<Tin> src, Converter<Tin, Tout> cvt)
		{
			foreach (Tin item in src)
			{
				dst.Add(cvt(item));
			}
		}

		internal static IEnumerable<T> ConcatElements<T>(this IEnumerable<T> collection, params T[] elements)
		{
			return collection.Concat(elements.Where((T item) => item != null));
		}

		public static void SanitizeNormals(this IList<Vector3> normals)
		{
			for (int i = 0; i < normals.Count; i++)
			{
				if (!normals[i].IsNormalized())
				{
					normals[i] = normals[i].SanitizeNormal();
				}
			}
		}

		public static void SanitizeTangents(this IList<Vector4> tangents)
		{
			for (int i = 0; i < tangents.Count; i++)
			{
				if (!tangents[i].IsValidTangent())
				{
					tangents[i] = tangents[i].SanitizeTangent();
				}
			}
		}

		public static IReadOnlyList<TResult> SelectList<TSource, TResult>(this IReadOnlyList<TSource> collection, Func<TSource, TResult> selector)
		{
			return new _ListSelect<TSource, TResult>(collection, selector);
		}

		public static IReadOnlyCollection<TResult> SelectCollection<TSource, TResult>(this IReadOnlyCollection<TSource> collection, Func<TSource, TResult> selector)
		{
			return new _CollectionSelect<TSource, TResult>(collection, selector);
		}

		public static string ToDebugString(this EncodingType encoding, DimensionType dimensions, bool normalized)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected I4, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected I4, but got Unknown
			string text = string.Empty;
			switch (encoding - 5120)
			{
			case 0:
				text += "SByte";
				break;
			case 6:
				text += "Float";
				break;
			case 2:
				text += "SShort";
				break;
			case 1:
				text += "UByte";
				break;
			case 5:
				text += "UInt";
				break;
			case 3:
				text += "UShort";
				break;
			}
			switch ((int)dimensions)
			{
			case 1:
				text += "2";
				break;
			case 2:
				text += "3";
				break;
			case 3:
				text += "4";
				break;
			case 4:
				text += "2x2";
				break;
			case 5:
				text += "3x3";
				break;
			case 6:
				text += "4x4";
				break;
			}
			if (normalized)
			{
				text = "Norm" + text;
			}
			return text;
		}

		public static int ByteLength(this IndexEncodingType encoding)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			return (encoding - 5121) switch
			{
				0 => 1, 
				2 => 2, 
				4 => 4, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static int ByteLength(this EncodingType encoding)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected I4, but got Unknown
			return (encoding - 5120) switch
			{
				0 => 1, 
				2 => 2, 
				6 => 4, 
				1 => 1, 
				3 => 2, 
				5 => 4, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static EncodingType ToComponent(this IndexEncodingType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			return (EncodingType)((t - 5121) switch
			{
				0 => 5121, 
				2 => 5123, 
				4 => 5125, 
				_ => throw new NotImplementedException(), 
			});
		}

		public static IndexEncodingType ToIndex(this EncodingType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			return (IndexEncodingType)((t - 5121) switch
			{
				0 => 5121, 
				2 => 5123, 
				4 => 5125, 
				_ => throw new NotImplementedException(), 
			});
		}

		public static int DimCount(this DimensionType dimension)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			return (int)dimension switch
			{
				0 => 1, 
				1 => 2, 
				2 => 3, 
				3 => 4, 
				4 => 4, 
				5 => 9, 
				6 => 16, 
				_ => throw new NotImplementedException(), 
			};
		}

		internal static DimensionType ToDimension(this int l)
		{
			return (DimensionType)(l switch
			{
				1 => 0, 
				2 => 1, 
				3 => 2, 
				4 => 3, 
				9 => 5, 
				16 => 6, 
				_ => throw new NotImplementedException(), 
			});
		}

		public static int GetPrimitiveVertexSize(this PrimitiveType ptype)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			return (int)ptype switch
			{
				0 => 1, 
				1 => 2, 
				2 => 2, 
				3 => 2, 
				4 => 3, 
				6 => 3, 
				5 => 3, 
				_ => throw new NotImplementedException(), 
			};
		}

		public static IEnumerable<(int A, int B)> GetLinesIndices(this PrimitiveType ptype, int vertexCount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ptype.GetLinesIndices(from item in Enumerable.Range(0, vertexCount)
				select (uint)item);
		}

		public static IEnumerable<(int A, int B, int C)> GetTrianglesIndices(this PrimitiveType ptype, int vertexCount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return ptype.GetTrianglesIndices(from item in Enumerable.Range(0, vertexCount)
				select (uint)item);
		}

		public static IEnumerable<(int A, int B)> GetLinesIndices(this PrimitiveType ptype, IEnumerable<uint> sourceIndices)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if ((int)ptype == 1)
			{
				using (IEnumerator<uint> ptr = sourceIndices.GetEnumerator())
				{
					while (ptr.MoveNext())
					{
						uint current = ptr.Current;
						if (!ptr.MoveNext())
						{
							break;
						}
						uint current2 = ptr.Current;
						if (!_IsDegeneratedSegment(current, current2))
						{
							yield return ((int)current, (int)current2);
						}
					}
				}
				yield break;
			}
			throw new NotImplementedException();
		}

		public static IEnumerable<(int A, int B, int C)> GetTrianglesIndices(this PrimitiveType ptype, IEnumerable<uint> sourceIndices)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			switch (ptype - 4)
			{
			case 0:
			{
				using (IEnumerator<uint> enumerator = sourceIndices.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						uint current = enumerator.Current;
						if (!enumerator.MoveNext())
						{
							break;
						}
						uint current2 = enumerator.Current;
						if (!enumerator.MoveNext())
						{
							break;
						}
						uint current3 = enumerator.Current;
						if (!_IsDegeneratedTriangle(current, current2, current3))
						{
							yield return ((int)current, (int)current2, (int)current3);
						}
					}
				}
				break;
			}
			case 2:
			{
				using IEnumerator<uint> enumerator = sourceIndices.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint a2 = enumerator.Current;
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint num2 = enumerator.Current;
				while (enumerator.MoveNext())
				{
					uint c2 = enumerator.Current;
					if (!_IsDegeneratedTriangle(a2, num2, c2))
					{
						yield return ((int)a2, (int)num2, (int)c2);
					}
					num2 = c2;
				}
				break;
			}
			case 1:
			{
				using IEnumerator<uint> enumerator = sourceIndices.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint num = enumerator.Current;
				if (!enumerator.MoveNext())
				{
					break;
				}
				uint a2 = enumerator.Current;
				bool reversed = false;
				while (enumerator.MoveNext())
				{
					uint c2 = enumerator.Current;
					if (!_IsDegeneratedTriangle(num, a2, c2))
					{
						if (reversed)
						{
							yield return ((int)a2, (int)num, (int)c2);
						}
						else
						{
							yield return ((int)num, (int)a2, (int)c2);
						}
					}
					num = a2;
					a2 = c2;
					reversed = !reversed;
				}
				break;
			}
			default:
				throw new NotImplementedException();
			}
		}

		private static bool _IsDegeneratedSegment(uint a, uint b)
		{
			return a == b;
		}

		private static bool _IsDegeneratedTriangle(uint a, uint b, uint c)
		{
			if (a == b)
			{
				return true;
			}
			if (a == c)
			{
				return true;
			}
			if (b == c)
			{
				return true;
			}
			return false;
		}

		public static byte[] ToUnderlayingArray(this ArraySegment<byte> segment)
		{
			if (segment.Offset == 0 && segment.Count == segment.Array.Length)
			{
				return segment.Array;
			}
			return segment.ToArray();
		}

		public static ArraySegment<byte> ToArraySegment(this MemoryStream m)
		{
			if (m.TryGetBuffer(out var buffer))
			{
				return buffer;
			}
			return new ArraySegment<byte>(m.ToArray());
		}

		public static byte[] GetPaddedContent(this byte[] content)
		{
			if (content == null)
			{
				return null;
			}
			if (content.Length.IsMultipleOf(4))
			{
				return content;
			}
			int num = content.Length % 4;
			num = ((num != 0) ? (4 - num) : 0);
			byte[] array = new byte[content.Length + num];
			content.CopyTo(array, 0);
			return array;
		}

		public static byte[] TryParseBase64Unchecked(this string uri, params string[] prefixes)
		{
			if (uri == null)
			{
				return null;
			}
			if (!uri.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			foreach (string prefix in prefixes)
			{
				byte[] array = _TryParseBase64Unchecked(uri, prefix);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		private static byte[] _TryParseBase64Unchecked(string uri, string prefix)
		{
			if (!uri.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			string text = uri.Substring(prefix.Length);
			if (text.StartsWith(";base64,", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(";base64,".Length);
				return Convert.FromBase64String(text);
			}
			if (text.StartsWith(','))
			{
				text = text.Substring(1);
				if (text.Length == 1)
				{
					return new byte[1] { byte.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture) };
				}
				throw new NotImplementedException();
			}
			throw new NotImplementedException();
		}

		public static string _EscapeStringInternal(this string uri)
		{
			return Uri.EscapeUriString(uri);
		}

		[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(JsonValue))]
		[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(JsonArray))]
		[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(JsonObject))]
		public static JsonNode DeepClone(this JsonNode node)
		{
			if (node == null)
			{
				throw new ArgumentNullException("node");
			}
			JsonNode jsonNode = null;
			if (!(node is JsonValue node2))
			{
				if (!(node is JsonArray node3))
				{
					if (node is JsonObject node4)
					{
						jsonNode = node4.Deserialize<JsonObject>();
					}
				}
				else
				{
					jsonNode = node3.Deserialize<JsonArray>();
				}
			}
			else
			{
				jsonNode = node2.Deserialize<JsonValue>();
			}
			if (jsonNode == null)
			{
				throw new NotImplementedException();
			}
			return jsonNode;
		}

		public static bool DeepEquals(this JsonNode x, JsonNode y, double precission)
		{
			if (x == y)
			{
				return true;
			}
			if (x == null)
			{
				return false;
			}
			if (y == null)
			{
				return false;
			}
			if (x is JsonValue jsonValue && y is JsonValue jsonValue2)
			{
				if (jsonValue.TryGetValue<int>(out var value) && jsonValue2.TryGetValue<int>(out var value2))
				{
					return value == value2;
				}
				if (jsonValue.TryGetValue<long>(out var value3) && jsonValue2.TryGetValue<long>(out var value4))
				{
					return value3 == value4;
				}
				if (jsonValue.TryGetValue<float>(out var value5) && jsonValue2.TryGetValue<float>(out var value6))
				{
					return (double)Math.Abs(value5 - value6) <= precission;
				}
				if (jsonValue.TryGetValue<double>(out var value7) && jsonValue2.TryGetValue<double>(out var value8))
				{
					return Math.Abs(value7 - value8) <= precission;
				}
				return jsonValue.ToJsonString() == jsonValue2.ToJsonString();
			}
			if (x is JsonArray jsonArray && y is JsonArray jsonArray2)
			{
				if (jsonArray.Count != jsonArray2.Count)
				{
					return false;
				}
				for (int i = 0; i < jsonArray.Count; i++)
				{
					if (!jsonArray[i].DeepEquals(jsonArray2[i], precission))
					{
						return false;
					}
				}
				return true;
			}
			if (x is JsonObject jsonObject && y is JsonObject jsonObject2)
			{
				if (jsonObject.Count != jsonObject2.Count)
				{
					return false;
				}
				foreach (KeyValuePair<string, JsonNode> item in jsonObject)
				{
					if (!jsonObject2.TryGetPropertyValue(item.Key, out JsonNode jsonNode))
					{
						return false;
					}
					if (!item.Value.DeepEquals(jsonNode, precission))
					{
						return false;
					}
				}
				return true;
			}
			return false;
		}
	}
}
namespace SharpGLTF.Runtime
{
	internal static class VertexNormalsFactory
	{
		public interface IMeshPrimitive
		{
			int VertexCount { get; }

			Vector3 GetVertexPosition(int idx);

			void SetVertexNormal(int idx, Vector3 normal);

			IEnumerable<(int A, int B, int C)> GetTriangleIndices();
		}

		public static void CalculateSmoothNormals<T>(IEnumerable<T> primitives) where T : IMeshPrimitive
		{
			Guard.NotNull(primitives, "primitives");
			primitives = primitives.EnsureList();
			Dictionary<Vector3, Vector3> dictionary = new Dictionary<Vector3, Vector3>();
			foreach (T primitive in primitives)
			{
				foreach (var triangleIndex in primitive.GetTriangleIndices())
				{
					int item = triangleIndex.A;
					int item2 = triangleIndex.B;
					int item3 = triangleIndex.C;
					Vector3 vertexPosition = primitive.GetVertexPosition(item);
					Vector3 vertexPosition2 = primitive.GetVertexPosition(item2);
					Vector3 vertexPosition3 = primitive.GetVertexPosition(item3);
					Vector3 dir = Vector3.Cross(vertexPosition2 - vertexPosition, vertexPosition3 - vertexPosition);
					_AddDirection(dictionary, vertexPosition, dir);
					_AddDirection(dictionary, vertexPosition2, dir);
					_AddDirection(dictionary, vertexPosition3, dir);
				}
			}
			foreach (Vector3 item4 in dictionary.Keys.ToList())
			{
				Vector3 vector = Vector3.Normalize(dictionary[item4]);
				dictionary[item4] = ((vector._IsFinite() && vector.LengthSquared() > 0.5f) ? vector : Vector3.UnitZ);
			}
			foreach (T primitive2 in primitives)
			{
				T current4 = primitive2;
				for (int i = 0; i < current4.VertexCount; i++)
				{
					Vector3 vertexPosition4 = current4.GetVertexPosition(i);
					if (dictionary.TryGetValue(vertexPosition4, out var value))
					{
						current4.SetVertexNormal(i, value);
						continue;
					}
					ref T reference = ref current4;
					T val = default(T);
					if (val == null)
					{
						val = reference;
						reference = ref val;
					}
					reference.SetVertexNormal(i, Vector3.UnitZ);
				}
			}
		}

		private static void _AddDirection(Dictionary<Vector3, Vector3> dict, Vector3 pos, Vector3 dir)
		{
			if (dir._IsFinite())
			{
				if (!dict.TryGetValue(pos, out var value))
				{
					value = Vector3.Zero;
				}
				dict[pos] = value + dir;
			}
		}
	}
	internal static class VertexTangentsFactory
	{
		public interface IMeshPrimitive
		{
			int VertexCount { get; }

			Vector3 GetVertexPosition(int idx);

			Vector3 GetVertexNormal(int idx);

			Vector2 GetVertexTexCoord(int idx);

			void SetVertexTangent(int idx, Vector4 tangent);

			IEnumerable<(int A, int B, int C)> GetTriangleIndices();
		}

		public static void CalculateTangents<T>(IEnumerable<T> primitives) where T : IMeshPrimitive
		{
			Guard.NotNull(primitives, "primitives");
			primitives = primitives.EnsureList();
			Dictionary<(Vector3, Vector3, Vector2), (Vector3, Vector3)> dictionary = new Dictionary<(Vector3, Vector3, Vector2), (Vector3, Vector3)>();
			foreach (T primitive in primitives)
			{
				foreach (var triangleIndex in primitive.GetTriangleIndices())
				{
					int item = triangleIndex.A;
					int item2 = triangleIndex.B;
					int item3 = triangleIndex.C;
					Vector3 vertexPosition = primitive.GetVertexPosition(item);
					Vector3 vertexPosition2 = primitive.GetVertexPosition(item2);
					Vector3 vertexPosition3 = primitive.GetVertexPosition(item3);
					if (vertexPosition == vertexPosition2 || vertexPosition == vertexPosition3 || vertexPosition2 == vertexPosition3)
					{
						continue;
					}
					Vector2 vertexTexCoord = primitive.GetVertexTexCoord(item);
					Vector2 vertexTexCoord2 = primitive.GetVertexTexCoord(item2);
					Vector2 vertexTexCoord3 = primitive.GetVertexTexCoord(item3);
					if (vertexTexCoord == vertexTexCoord2 || vertexTexCoord == vertexTexCoord3 || vertexTexCoord2 == vertexTexCoord3)
					{
						continue;
					}
					Vector3 vertexNormal = primitive.GetVertexNormal(item);
					Vector3 vertexNormal2 = primitive.GetVertexNormal(item2);
					Vector3 vertexNormal3 = primitive.GetVertexNormal(item3);
					Vector3 vector = vertexPosition2 - vertexPosition;
					Vector3 vector2 = vertexPosition3 - vertexPosition;
					Vector2 vector3 = vertexTexCoord2 - vertexTexCoord;
					Vector2 vector4 = vertexTexCoord3 - vertexTexCoord;
					float x = vector3.X;
					float x2 = vector4.X;
					float y = vector3.Y;
					float y2 = vector4.Y;
					float num = 1f / (x * y2 - x2 * y);
					if (num._IsFinite())
					{
						Vector3 vector5 = new Vector3(y2 * vector.X - y * vector2.X, y2 * vector.Y - y * vector2.Y, y2 * vector.Z - y * vector2.Z) * num;
						Vector3 vector6 = new Vector3(x * vector2.X - x2 * vector.X, x * vector2.Y - x2 * vector.Y, x * vector2.Z - x2 * vector.Z) * num;
						if (vector5._IsFinite() && vector6._IsFinite())
						{
							_AddTangent(dictionary, (vertexPosition, vertexNormal, vertexTexCoord), (vector5, vector6));
							_AddTangent(dictionary, (vertexPosition2, vertexNormal2, vertexTexCoord2), (vector5, vector6));
							_AddTangent(dictionary, (vertexPosition3, vertexNormal3, vertexTexCoord3), (vector5, vector6));
						}
					}
				}
			}
			foreach (var item4 in dictionary.Keys.ToList())
			{
				(Vector3, Vector3) value = dictionary[item4];
				value.Item1 = Vector3.Normalize(value.Item1 - item4.Item2 * Vector3.Dot(item4.Item2, value.Item1));
				value.Item2 = Vector3.Normalize(value.Item2 - item4.Item2 * Vector3.Dot(item4.Item2, value.Item2));
				dictionary[item4] = value;
			}
			foreach (T primitive2 in primitives)
			{
				T current4 = primitive2;
				for (int i = 0; i < current4.VertexCount; i++)
				{
					Vector3 vertexPosition4 = current4.GetVertexPosition(i);
					Vector3 vertexNormal4 = current4.GetVertexNormal(i);
					Vector2 vertexTexCoord4 = current4.GetVertexTexCoord(i);
					T val;
					if (dictionary.TryGetValue((vertexPosition4, vertexNormal4, vertexTexCoord4), out var value2))
					{
						float w = ((Vector3.Dot(Vector3.Cross(value2.Item1, vertexNormal4), value2.Item2) < 0f) ? (-1f) : 1f);
						ref T reference = ref current4;
						val = default(T);
						if (val == null)
						{
							val = reference;
							reference = ref val;
						}
						reference.SetVertexTangent(i, new Vector4(value2.Item1, w));
					}
					else
					{
						ref T reference2 = ref current4;
						val = default(T);
						if (val == null)
						{
							val = reference2;
							reference2 = ref val;
						}
						reference2.SetVertexTangent(i, new Vector4(1f, 0f, 0f, 1f));
					}
				}
			}
		}

		private static void _AddTangent(Dictionary<(Vector3, Vector3, Vector2), (Vector3, Vector3)> dict, (Vector3, Vector3, Vector2) key, (Vector3 tu, Vector3 tv) alpha)
		{
			dict.TryGetValue(key, out var value);
			dict[key] = (alpha.tu + value.Item1, alpha.tv + value.Item2);
		}
	}
}
namespace SharpGLTF.Schema2
{
	public static class Toolkit
	{
		public static Accessor CreateVertexAccessor(this ModelRoot root, MemoryAccessor memAccessor)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(root, "root");
			Guard.NotNull(memAccessor, "memAccessor");
			Accessor val = root.CreateAccessor(memAccessor.Attribute.Name);
			val.SetVertexData(memAccessor);
			return val;
		}

		public unsafe static BufferView CreateBufferView<T>(this ModelRoot root, IReadOnlyList<T> data) where T : unmanaged
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(root, "root");
			Guard.NotNull(data, "data");
			BufferView val = root.CreateBufferView(sizeof(T) * data.Count, 0, (BufferMode?)null);
			if (typeof(T) == typeof(int))
			{
				IntegerArray val2 = new IntegerArray((Memory<byte>)val.Content, (IndexEncodingType)5125);
				((IntegerArray)(ref val2)).Fill((IEnumerable<int>)(data as IReadOnlyList<int>), 0);
				return val;
			}
			if (typeof(T) == typeof(float))
			{
				ScalarArray val3 = new ScalarArray((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
				((ScalarArray)(ref val3)).Fill((IEnumerable<float>)(data as IReadOnlyList<float>), 0);
				return val;
			}
			if (typeof(T) == typeof(Vector2))
			{
				Vector2Array val4 = new Vector2Array((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
				((Vector2Array)(ref val4)).Fill((IEnumerable<Vector2>)(data as IReadOnlyList<Vector2>), 0);
				return val;
			}
			if (typeof(T) == typeof(Vector3))
			{
				Vector3Array val5 = new Vector3Array((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
				((Vector3Array)(ref val5)).Fill((IEnumerable<Vector3>)(data as IReadOnlyList<Vector3>), 0);
				return val;
			}
			if (typeof(T) == typeof(Vector4))
			{
				Vector4Array val6 = new Vector4Array((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
				((Vector4Array)(ref val6)).Fill((IEnumerable<Vector4>)(data as IReadOnlyList<Vector4>), 0);
				return val;
			}
			if (typeof(T) == typeof(Quaternion))
			{
				QuaternionArray val7 = new QuaternionArray((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
				((QuaternionArray)(ref val7)).Fill((IEnumerable<Quaternion>)(data as IReadOnlyList<Quaternion>), 0);
				return val;
			}
			if (typeof(T) == typeof(Matrix4x4))
			{
				Matrix4x4Array val8 = new Matrix4x4Array((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
				((Matrix4x4Array)(ref val8)).Fill((IEnumerable<Matrix4x4>)(data as IReadOnlyList<Matrix4x4>), 0);
				return val;
			}
			throw new ArgumentException(typeof(T).Name);
		}

		public static Animation UseAnimation(this ModelRoot root, string name)
		{
			Guard.NotNull(root, "root");
			Animation val = ((IEnumerable<Animation>)root.LogicalAnimations).FirstOrDefault((Func<Animation, bool>)((Animation item) => ((LogicalChildOfRoot)item).Name == name));
			return val ?? root.CreateAnimation(name);
		}

		public static Node WithScaleAnimation(this Node node, string animationName, ICurveSampler<Vector3> sampler)
		{
			Guard.NotNull(node, "node");
			if (sampler is IConvertibleCurve<Vector3> val)
			{
				Animation val2 = ((LogicalChildOfRoot)node).LogicalParent.UseAnimation(animationName);
				int maxDegree = val.MaxDegree;
				if (maxDegree == 0)
				{
					val2.CreateScaleChannel(node, val.ToStepCurve(), false);
				}
				if (maxDegree == 1)
				{
					val2.CreateScaleChannel(node, val.ToLinearCurve(), true);
				}
				if (maxDegree == 3)
				{
					val2.CreateScaleChannel(node, val.ToSplineCurve());
				}
				return node;
			}
			throw new ArgumentException("Must implement IConvertibleCurve<Vector3>", "sampler");
		}

		public static Node WithTranslationAnimation(this Node node, string animationName, ICurveSampler<Vector3> sampler)
		{
			Guard.NotNull(node, "node");
			if (sampler is IConvertibleCurve<Vector3> val)
			{
				Animation val2 = ((LogicalChildOfRoot)node).LogicalParent.UseAnimation(animationName);
				int maxDegree = val.MaxDegree;
				if (maxDegree == 0)
				{
					val2.CreateTranslationChannel(node, val.ToStepCurve(), false);
				}
				if (maxDegree == 1)
				{
					val2.CreateTranslationChannel(node, val.ToLinearCurve(), true);
				}
				if (maxDegree == 3)
				{
					val2.CreateTranslationChannel(node, val.ToSplineCurve());
				}
				return node;
			}
			throw new ArgumentException("Must implement IConvertibleCurve<Vector3>", "sampler");
		}

		public static Node WithMorphingAnimation(this Node node, string animationName, ICurveSampler<SparseWeight8> sampler)
		{
			Guard.NotNull(node, "node");
			Guard.NotNull(node.MorphWeights, "MorphWeights", "Set node.MorphWeights before setting morphing animation");
			Guard.MustBeGreaterThanOrEqualTo(node.MorphWeights.Count, 0, "MorphWeights");
			if (sampler is IConvertibleCurve<SparseWeight8> val)
			{
				Animation val2 = ((LogicalChildOfRoot)node).LogicalParent.UseAnimation(animationName);
				int maxDegree = val.MaxDegree;
				if (maxDegree == 0)
				{
					val2.CreateMorphChannel(node, val.ToStepCurve(), node.MorphWeights.Count, false);
				}
				if (maxDegree == 1)
				{
					val2.CreateMorphChannel(node, val.ToLinearCurve(), node.MorphWeights.Count, true);
				}
				if (maxDegree == 3)
				{
					val2.CreateMorphChannel(node, val.ToSplineCurve(), node.MorphWeights.Count);
				}
			}
			return node;
		}

		public static Node WithMorphingAnimation<T>(this Node node, string animationName, ICurveSampler<T> sampler) where T : IReadOnlyList<float>
		{
			Guard.NotNull(node, "node");
			Guard.NotNull(node.MorphWeights, "MorphWeights", "Set node.MorphWeights before setting morphing animation");
			Guard.MustBeGreaterThanOrEqualTo(node.MorphWeights.Count, 0, "MorphWeights");
			if (sampler is IConvertibleCurve<float[]> val)
			{
				Animation val2 = ((LogicalChildOfRoot)node).LogicalParent.UseAnimation(animationName);
				int maxDegree = val.MaxDegree;
				if (maxDegree == 0)
				{
					val2.CreateMorphChannel<float[]>(node, val.ToStepCurve(), node.MorphWeights.Count, false);
				}
				if (maxDegree == 1)
				{
					val2.CreateMorphChannel<float[]>(node, val.ToLinearCurve(), node.MorphWeights.Count, true);
				}
				if (maxDegree == 3)
				{
					val2.CreateMorphChannel<float[]>(node, val.ToSplineCurve(), node.MorphWeights.Count);
				}
			}
			if (sampler is IConvertibleCurve<ArraySegment<float>> val3)
			{
				Animation val4 = ((LogicalChildOfRoot)node).LogicalParent.UseAnimation(animationName);
				int maxDegree2 = val3.MaxDegree;
				if (maxDegree2 == 0)
				{
					val4.CreateMorphChannel<ArraySegment<float>>(node, val3.ToStepCurve(), node.MorphWeights.Count, false);
				}
				if (maxDegree2 == 1)
				{
					val4.CreateMorphChannel<ArraySegment<float>>(node, val3.ToLinearCurve(), node.MorphWeights.Count, true);
				}
				if (maxDegree2 == 3)
				{
					val4.CreateMorphChannel<ArraySegment<float>>(node, val3.ToSplineCurve(), node.MorphWeights.Count);
				}
			}
			return node;
		}

		public static Node WithRotationAnimation(this Node node, string animationName, ICurveSampler<Quaternion> sampler)
		{
			Guard.NotNull(node, "node");
			if (sampler is IConvertibleCurve<Quaternion> val)
			{
				Animation val2 = ((LogicalChildOfRoot)node).LogicalParent.UseAnimation(animationName);
				int maxDegree = val.MaxDegree;
				if (maxDegree == 0)
				{
					val2.CreateRotationChannel(node, val.ToStepCurve(), false);
				}
				if (maxDegree == 1)
				{
					val2.CreateRotationChannel(node, val.ToLinearCurve(), true);
				}
				if (maxDegree == 3)
				{
					val2.CreateRotationChannel(node, val.ToSplineCurve());
				}
				return node;
			}
			throw new ArgumentException("Must implement IConvertibleCurve<Quaternion>", "sampler");
		}

		public static Node WithScaleAnimation(this Node node, string animationName, params (float Key, Vector3 Value)[] keyframes)
		{
			Guard.NotNull(node, "node");
			Guard.NotNullOrEmpty(keyframes, "keyframes");
			Dictionary<float, Vector3> keyframes2 = keyframes.ToDictionary(((float Key, Vector3 Value) kvp) => kvp.Key, ((float Key, Vector3 Value) kvp) => kvp.Value);
			return node.WithScaleAnimation(animationName, (IReadOnlyDictionary<float, Vector3>)keyframes2);
		}

		public static Node WithRotationAnimation(this Node node, string animationName, params (float Key, Quaternion Value)[] keyframes)
		{
			Guard.NotNull(node, "node");
			Guard.NotNullOrEmpty(keyframes, "keyframes");
			Dictionary<float, Quaternion> keyframes2 = keyframes.ToDictionary(((float Key, Quaternion Value) kvp) => kvp.Key, ((float Key, Quaternion Value) kvp) => kvp.Value);
			return node.WithRotationAnimation(animationName, (IReadOnlyDictionary<float, Quaternion>)keyframes2);
		}

		public static Node WithTranslationAnimation(this Node node, string animationName, params (float Key, Vector3 Value)[] keyframes)
		{
			Guard.NotNull(node, "node");
			Guard.NotNullOrEmpty(keyframes, "keyframes");
			Dictionary<float, Vector3> keyframes2 = keyframes.ToDictionary(((float Key, Vector3 Value) kvp) => kvp.Key, ((float Key, Vector3 Value) kvp) => kvp.Value);
			return node.WithTranslationAnimation(animationName, (IReadOnlyDictionary<float, Vector3>)keyframes2);
		}

		public static Node WithScaleAnimation(this Node node, string animationName, IReadOnlyDictionary<float, Vector3> keyframes)
		{
			Guard.NotNull(node, "node");
			Guard.NotNullOrEmpty(keyframes, "keyframes");
			ModelRoot logicalParent = ((LogicalChildOfRoot)node).LogicalParent;
			Animation val = logicalParent.UseAnimation(animationName);
			val.CreateScaleChannel(node, keyframes, true);
			return node;
		}

		public static Node WithRotationAnimation(this Node node, string animationName, IReadOnlyDictionary<float, Quaternion> keyframes)
		{
			Guard.NotNull(node, "node");
			Guard.NotNullOrEmpty(keyframes, "keyframes");
			ModelRoot logicalParent = ((LogicalChildOfRoot)node).LogicalParent;
			Animation val = logicalParent.UseAnimation(animationName);
			val.CreateRotationChannel(node, keyframes, true);
			return node;
		}

		public static Node WithTranslationAnimation(this Node node, string animationName, IReadOnlyDictionary<float, Vector3> keyframes)
		{
			Guard.NotNull(node, "node");
			Guard.NotNullOrEmpty(keyframes, "keyframes");
			ModelRoot logicalParent = ((LogicalChildOfRoot)node).LogicalParent;
			Animation val = logicalParent.UseAnimation(animationName);
			val.CreateTranslationChannel(node, keyframes, true);
			return node;
		}

		public static PunctualLight WithSpotCone(this PunctualLight light, float innerConeAngle, float outerConeAngle)
		{
			Guard.NotNull(light, "light");
			light.SetSpotCone(innerConeAngle, outerConeAngle);
			return light;
		}

		public static PunctualLight WithColor(this PunctualLight light, Vector3 color, float intensity = 1f, float range = float.PositiveInfinity)
		{
			Guard.NotNull(light, "light");
			light.Color = color;
			light.Intensity = intensity;
			light.Range = range;
			return light;
		}

		public static Material WithDefault(this Material material)
		{
			Guard.NotNull(material, "material");
			return material.WithPBRMetallicRoughness();
		}

		public static Material WithDefault(this Material material, Vector4 diffuseColor)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(material, "material");
			MaterialChannel value = material.WithPBRMetallicRoughness().FindChannel("BaseColor").Value;
			((MaterialChannel)(ref value)).Color = diffuseColor;
			return material;
		}

		public static Material WithDoubleSide(this Material material, bool enabled)
		{
			Guard.NotNull(material, "material");
			material.DoubleSided = enabled;
			return material;
		}

		[Obsolete("don't use vector4 based parameter. Use WithChannelColor and WithChannelFactor instead.")]
		public static Material WithChannelParameter(this Material material, string channelName, Vector4 parameter)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(material, "material");
			MaterialChannel value = material.FindChannel(channelName).Value;
			((MaterialChannel)(ref value)).Parameter = parameter;
			return material;
		}

		public static Material WithChannelColor(this Material material, string channelName, Vector4 color)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(material, "material");
			MaterialChannel value = material.FindChannel(channelName).Value;
			((MaterialChannel)(ref value)).Color = color;
			return material;
		}

		public static Material WithChannelFactor(this Material material, string channelName, string paramName, float factor)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(material, "material");
			MaterialChannel value = material.FindChannel(channelName).Value;
			((MaterialChannel)(ref value)).SetFactor(paramName, factor);
			return material;
		}

		public static Material WithChannelTexture(this Material material, string channelName, int textureSet, string imageFilePath)
		{
			Guard.NotNull(material, "material");
			Image image = ((LogicalChildOfRoot)material).LogicalParent.UseImageWithFile(imageFilePath);
			return material.WithChannelTexture(channelName, textureSet, image);
		}

		public static Material WithChannelTexture(this Material material, string channelName, int textureSet, Image image)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(material, "material");
			MaterialChannel value = material.FindChannel(channelName).Value;
			((MaterialChannel)(ref value)).SetTexture(textureSet, image, (Image)null, (TextureWrapMode)10497, (TextureWrapMode)10497, (TextureMipMapFilter)0, (TextureInterpolationFilter)0);
			return material;
		}

		public static Material WithPBRMetallicRoughness(this Material material)
		{
			Guard.NotNull(material, "material");
			material.InitializePBRMetallicRoughness(Array.Empty<string>());
			return material;
		}

		public static Material WithPBRMetallicRoughness(this Material material, Vector4 baseColor, string baseColorImageFilePath, string metallicImageFilePath = null, float metallicFactor = 1f, float roughnessFactor = 1f)
		{
			Guard.NotNull(material, "material");
			material.WithPBRMetallicRoughness().WithChannelColor("BaseColor", baseColor).WithChannelFactor("MetallicRoughness", "MetallicFactor", metallicFactor)
				.WithChannelFactor("MetallicRoughness", "RoughnessFactor", roughnessFactor);
			if (!string.IsNullOrWhiteSpace(baseColorImageFilePath))
			{
				material.WithChannelTexture("BaseColor", 0, baseColorImageFilePath);
			}
			if (!string.IsNullOrWhiteSpace(metallicImageFilePath))
			{
				material.WithChannelTexture("Metallic", 0, baseColorImageFilePath);
			}
			return material;
		}

		[Obsolete("SpecularGlossiness Extension has been declared deprecated by the Khronos Group. Use newer extensions instead.")]
		public static Material WithPBRSpecularGlossiness(this Material material)
		{
			Guard.NotNull(material, "material");
			material.InitializePBRSpecularGlossiness(false);
			return material;
		}

		public static Material WithUnlit(this Material material)
		{
			Guard.NotNull(material, "material");
			material.InitializeUnlit();
			return material;
		}

		public static Image UseImageWithFile(this ModelRoot root, string filePath)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = File.ReadAllBytes(filePath);
			return root.UseImageWithContent(MemoryImage.op_Implicit(array));
		}

		public static Image UseImageWithContent(this ModelRoot root, MemoryImage image)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(root, "root");
			return root.UseImage(image);
		}

		public static Material CreateMaterial(this ModelRoot root, MaterialBuilder mb)
		{
			Guard.NotNull(root, "root");
			Guard.NotNull(mb, "mb");
			Material val = root.CreateMaterial((string)null);
			mb.CopyTo(val);
			return val;
		}

		public static MaterialBuilder ToMaterialBuilder(this Material srcMaterial)
		{
			if (srcMaterial == null)
			{
				return MaterialBuilder.CreateDefault();
			}
			MaterialBuilder materialBuilder = new MaterialBuilder(((LogicalChildOfRoot)srcMaterial).Name);
			srcMaterial.CopyTo(materialBuilder);
			return materialBuilder;
		}

		public static AlphaMode ToSchema2(this AlphaMode alpha)
		{
			return (AlphaMode)(alpha switch
			{
				AlphaMode.BLEND => 2, 
				AlphaMode.MASK => 1, 
				AlphaMode.OPAQUE => 0, 
				_ => throw new NotImplementedException(alpha.ToString()), 
			});
		}

		public static AlphaMode ToToolkit(this AlphaMode alpha)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			return (int)alpha switch
			{
				2 => AlphaMode.BLEND, 
				1 => AlphaMode.MASK, 
				0 => AlphaMode.OPAQUE, 
				_ => throw new NotImplementedException(((object)(AlphaMode)(ref alpha)).ToString()), 
			};
		}

		public static void CopyTo(this Material srcMaterial, MaterialBuilder dstMaterial)
		{
			Guard.NotNull(srcMaterial, "srcMaterial");
			Guard.NotNull(dstMaterial, "dstMaterial");
			_CopyDefaultTo(srcMaterial, dstMaterial);
			if (srcMaterial.Unlit)
			{
				dstMaterial.WithUnlitShader();
				srcMaterial.CopyChannelsTo(dstMaterial, "BaseColor");
			}
			else if (srcMaterial.FindChannel("Diffuse").HasValue || srcMaterial.FindChannel("SpecularGlossiness").HasValue)
			{
				dstMaterial.WithSpecularGlossinessShader();
				srcMaterial.CopyChannelsTo(dstMaterial, "Diffuse", "SpecularGlossiness");
				if (srcMaterial.FindChannel("BaseColor").HasValue || srcMaterial.FindChannel("MetallicRoughness").HasValue)
				{
					MaterialBuilder materialBuilder = new MaterialBuilder(((LogicalChildOfRoot)srcMaterial).Name);
					_CopyDefaultTo(srcMaterial, materialBuilder);
					_CopyMetallicRoughnessTo(srcMaterial, materialBuilder);
					dstMaterial.WithFallback(materialBuilder);
				}
			}
			else if (srcMaterial.FindChannel("BaseColor").HasValue || srcMaterial.FindChannel("MetallicRoughness").HasValue)
			{
				_CopyMetallicRoughnessTo(srcMaterial, dstMaterial);
			}
		}

		private static void _CopyMetallicRoughnessTo(Material srcMaterial, MaterialBuilder dstMaterial)
		{
			dstMaterial.WithMetallicRoughnessShader();
			string[] channelKeys = MaterialBuilder._MetRouChannels.Select((KnownChannel item) => item.ToString()).ToArray();
			srcMaterial.CopyChannelsTo(dstMaterial, channelKeys);
		}

		private static void _CopyDefaultTo(Material srcMaterial, MaterialBuilder dstMaterial)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(srcMaterial, "srcMaterial");
			Guard.NotNull(dstMaterial, "dstMaterial");
			dstMaterial.SetNameAndExtrasFrom((LogicalChildOfRoot)(object)srcMaterial);
			dstMaterial.AlphaMode = srcMaterial.Alpha.ToToolkit();
			dstMaterial.AlphaCutoff = srcMaterial.AlphaCutoff;
			dstMaterial.DoubleSided = srcMaterial.DoubleSided;
			dstMaterial.Dispersion = srcMaterial.Dispersion;
			dstMaterial.IndexOfRefraction = srcMaterial.IndexOfRefraction;
			srcMaterial.CopyChannelsTo(dstMaterial, "Normal", "Occlusion", "Emissive");
		}

		public static void CopyChannelsTo(this Material srcMaterial, MaterialBuilder dstMaterial, params string[] channelKeys)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(srcMaterial, "srcMaterial");
			Guard.NotNull(dstMaterial, "dstMaterial");
			Guard.NotNull(channelKeys, "channelKeys");
			foreach (string text in channelKeys)
			{
				if (!Enum.TryParse<KnownChannel>(text, ignoreCase: true, out var result))
				{
					continue;
				}
				MaterialChannel? val = srcMaterial.FindChannel(text);
				if (val.HasValue)
				{
					MaterialChannel value = val.Value;
					if (!((MaterialChannel)(ref value)).HasDefaultContent)
					{
						ChannelBuilder dstChannel = dstMaterial.UseChannel(result);
						val.Value.CopyTo(dstChannel);
					}
				}
			}
		}

		public static void CopyTo(this MaterialChannel srcChannel, ChannelBuilder dstChannel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(srcChannel, "srcChannel");
			Guard.NotNull(dstChannel, "dstChannel");
			foreach (IMaterialParameter parameter in ((MaterialChannel)(ref srcChannel)).Parameters)
			{
				dstChannel.Parameters[parameter.Name] = MaterialValue.CreateFrom(parameter.Value);
			}
			if (((MaterialChannel)(ref srcChannel)).Texture != null)
			{
				if (dstChannel.Texture == null)
				{
					dstChannel.UseTexture();
				}
				dstChannel.Texture.SetNameAndExtrasFrom((LogicalChildOfRoot)(object)((MaterialChannel)(ref srcChannel)).Texture);
				dstChannel.Texture.CoordinateSet = ((MaterialChannel)(ref srcChannel)).TextureCoordinate;
				if (((MaterialChannel)(ref srcChannel)).TextureSampler != null)
				{
					dstChannel.Texture.MinFilter = ((MaterialChannel)(ref srcChannel)).TextureSampler.MinFilter;
					dstChannel.Texture.MagFilter = ((MaterialChannel)(ref srcChannel)).TextureSampler.MagFilter;
					dstChannel.Texture.WrapS = ((MaterialChannel)(ref srcChannel)).TextureSampler.WrapS;
					dstChannel.Texture.WrapT = ((MaterialChannel)(ref srcChannel)).TextureSampler.WrapT;
				}
				TextureTransform textureTransform = ((MaterialChannel)(ref srcChannel)).TextureTransform;
				if (textureTransform != null)
				{
					dstChannel.Texture.WithTransform(textureTransform.Offset, textureTransform.Scale, textureTransform.Rotation, textureTransform.TextureCoordinateOverride);
				}
				dstChannel.Texture.PrimaryImage = _convert(((MaterialChannel)(ref srcChannel)).Texture.PrimaryImage);
				dstChannel.Texture.FallbackImage = _convert(((MaterialChannel)(ref srcChannel)).Texture.FallbackImage);
			}
			static ImageBuilder _convert(Image src)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				if (src == null)
				{
					return null;
				}
				ImageBuilder imageBuilder = ImageBuilder.From(src.Content, ((LogicalChildOfRoot)src).Name, ((ExtraProperties)src).Extras?.DeepClone());
				imageBuilder.AlternateWriteFileName = src.AlternateWriteFileName;
				return imageBuilder;
			}
		}

		public static void CopyTo(this MaterialBuilder srcMaterial, Material dstMaterial)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			Guard.NotNull(srcMaterial, "srcMaterial");
			Guard.NotNull(dstMaterial, "dstMaterial");
			srcMaterial.ValidateForSchema2();
			srcMaterial.TryCopyNameAndExtrasTo((LogicalChildOfRoot)(object)dstMaterial);
			dstMaterial.Alpha = srcMaterial.AlphaMode.ToSchema2();
			dstMaterial.AlphaCutoff = (((int)dstMaterial.Alpha == 1) ? srcMaterial.AlphaCutoff : 0.5f);
			dstMaterial.DoubleSided = srcMaterial.DoubleSided;
			bool flag = srcMaterial.GetChannel(KnownChannel.ClearCoat) != null || srcMaterial.GetChannel(KnownChannel.ClearCoatNormal) != null || srcMaterial.GetChannel(KnownChannel.ClearCoatRoughness) != null;
			bool flag2 = srcMaterial.GetChannel(KnownChannel.SheenColor) != null || srcMaterial.GetChannel(KnownChannel.SheenRoughness) != null;
			bool flag3 = srcMaterial.GetChannel(KnownChannel.SpecularColor) != null || srcMaterial.GetChannel(KnownChannel.SpecularFactor) != null;
			bool flag4 = srcMaterial.GetChannel(KnownChannel.VolumeThickness) != null || srcMaterial.GetChannel(KnownChannel.VolumeAttenuation) != null;
			bool flag5 = srcMaterial.GetChannel(KnownChannel.Iridescence) != null || srcMaterial.GetChannel(KnownChannel.IridescenceThickness) != null;
			bool flag6 = srcMaterial.GetChannel(KnownChannel.Anisotropy) != null;
			bool flag7 = srcMaterial.GetChannel(KnownChannel.Transmission) != null;
			bool flag8 = srcMaterial.GetChannel(KnownChannel.DiffuseTransmissionColor) != null || srcMaterial.GetChannel(KnownChannel.DiffuseTransmissionFactor) != null;
			srcMaterial.CopyChannelsTo(dstMaterial, KnownChannel.Normal, KnownChannel.Occlusion, KnownChannel.Emissive);
			MaterialBuilder materialBuilder = null;
			if (srcMaterial.ShaderStyle == "Unlit")
			{
				dstMaterial.InitializeUnlit();
				srcMaterial.CopyChannelsTo(dstMaterial, KnownChannel.BaseColor);
				return;
			}
			if (srcMaterial.ShaderStyle == "PBRMetallicRoughness")
			{
				dstMaterial.InitializePBRMetallicRoughness(new string[8]
				{
					flag2 ? "Sheen" : null,
					flag4 ? "Volume" : null,
					flag3 ? "Specular" : null,
					flag ? "ClearCoat" : null,
					flag6 ? "Anisotropy" : null,
					flag5 ? "Iridescence" : null,
					flag7 ? "Transmission" : null,
					flag8 ? "DiffuseTransmission" : null
				});
				materialBuilder = srcMaterial;
			}
			if (srcMaterial.ShaderStyle == "PBRSpecularGlossiness")
			{
				dstMaterial.InitializePBRSpecularGlossiness(srcMaterial.CompatibilityFallback != null);
				srcMaterial.CopyChannelsTo(dstMaterial, KnownChannel.Diffuse, KnownChannel.SpecularGlossiness);
				materialBuilder = srcMaterial.CompatibilityFallback;
			}
			dstMaterial.Dispersion = srcMaterial.Dispersion;
			dstMaterial.IndexOfRefraction = srcMaterial.IndexOfRefraction;
			if (materialBuilder != null)
			{
				if (materialBuilder.ShaderStyle != "PBRMetallicRoughness")
				{
					throw new ArgumentException("ShaderStyle");
				}
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.BaseColor, KnownChannel.MetallicRoughness);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.ClearCoat, KnownChannel.ClearCoatNormal, KnownChannel.ClearCoatRoughness);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.Transmission);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.SheenColor, KnownChannel.SheenRoughness);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.SpecularColor, KnownChannel.SpecularFactor);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.VolumeThickness, KnownChannel.VolumeAttenuation);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.Iridescence, KnownChannel.IridescenceThickness);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.Anisotropy);
				materialBuilder.CopyChannelsTo(dstMaterial, KnownChannel.DiffuseTransmissionColor, KnownChannel.DiffuseTransmissionFactor);
			}
		}

		[Obsolete]
		public static void CopyChannelsTo(this MaterialBuilder srcMaterial, Material dstMaterial, params string[] channels)
		{
			KnownChannel result;
			KnownChannel[] channels2 = channels.Select((string key) => Enum.TryParse<KnownChannel>(key, out result) ? result : KnownChannel.Normal).ToArray();
			srcMaterial.CopyChannelsTo(dstMaterial, channels2);
		}

		public static void CopyChannelsTo(this MaterialBuilder srcMaterial, Material dstMaterial, params KnownChannel[] channels)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(srcMaterial, "srcMaterial");
			Guard.NotNull(dstMaterial, "dstMaterial");
			Guard.NotNull(channels, "channels");
			for (int i = 0; i < channels.Length; i++)
			{
				KnownChannel channelKey = channels[i];
				ChannelBuilder channel = srcMaterial.GetChannel(channelKey);
				if (channel != null)
				{
					MaterialChannel? val = dstMaterial.FindChannel(channelKey.ToString());
					if (val.HasValue)
					{
						channel.CopyTo(val.Value);
					}
				}
			}
		}

		public static void CopyTo(this ChannelBuilder srcChannel, MaterialChannel dstChannel)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(srcChannel, "srcChannel");
			Guard.NotNull(dstChannel, "dstChannel");
			foreach (IMaterialParameter parameter in ((MaterialChannel)(ref dstChannel)).Parameters)
			{
				parameter.Value = srcChannel.Parameters[parameter.Name].ToTypeless();
			}
			TextureBuilder validTexture = srcChannel.GetValidTexture();
			if (validTexture == null)
			{
				return;
			}
			Image val = null;
			Image val2 = null;
			if (ImageBuilder.IsValid(validTexture.PrimaryImage))
			{
				val = _ConvertToImage(dstChannel, validTexture.PrimaryImage);
			}
			if (val != null)
			{
				if (ImageBuilder.IsValid(validTexture.FallbackImage))
				{
					val2 = _ConvertToImage(dstChannel, validTexture.FallbackImage);
				}
				Texture target = ((MaterialChannel)(ref dstChannel)).SetTexture(validTexture.CoordinateSet, val, val2, validTexture.WrapS, validTexture.WrapT, validTexture.MinFilter, validTexture.MagFilter);
				validTexture.TryCopyNameAndExtrasTo((LogicalChildOfRoot)(object)target);
				TextureTransformBuilder transform = validTexture.Transform;
				if (transform != null)
				{
					((MaterialChannel)(ref dstChannel)).SetTransform(transform.Offset, transform.Scale, transform.Rotation, transform.CoordinateSetOverride);
				}
			}
		}

		private static Image _ConvertToImage(MaterialChannel dstChannel, ImageBuilder srcImage)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Image val = ((LogicalChildOfRoot)((MaterialChannel)(ref dstChannel)).LogicalParent).LogicalParent.UseImageWithContent(srcImage.Content);
			val.AlternateWriteFileName = srcImage.AlternateWriteFileName;
			srcImage.TryCopyNameAndExtrasTo((LogicalChildOfRoot)(object)val);
			return val;
		}

		public static Vector4 GetDiffuseColor(this Material material, Vector4 defaultColor)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (material == null)
			{
				return defaultColor;
			}
			MaterialChannel? val = material.FindChannel("Diffuse");
			MaterialChannel value;
			if (val.HasValue)
			{
				value = val.Value;
				return ((MaterialChannel)(ref value)).Color;
			}
			val = material.FindChannel("BaseColor");
			if (val.HasValue)
			{
				value = val.Value;
				return ((MaterialChannel)(ref value)).Color;
			}
			return defaultColor;
		}

		public static Texture GetDiffuseTexture(this Material material)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (material == null)
			{
				return null;
			}
			MaterialChannel? val = material.FindChannel("Diffuse");
			MaterialChannel value;
			if (val.HasValue)
			{
				value = val.Value;
				return ((MaterialChannel)(ref value)).Texture;
			}
			val = material.FindChannel("BaseColor");
			if (val.HasValue)
			{
				value = val.Value;
				return ((MaterialChannel)(ref value)).Texture;
			}
			return null;
		}

		public static TextureTransform GetDiffuseTextureTransform(this Material material)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (material == null)
			{
				return null;
			}
			MaterialChannel? val = material.FindChannel("Diffuse");
			MaterialChannel value;
			if (val.HasValue)
			{
				value = val.Value;
				return ((MaterialChannel)(ref value)).TextureTransform;
			}
			val = material.FindChannel("BaseColor");
			if (val.HasValue)
			{
				value = val.Value;
				return ((MaterialChannel)(ref value)).TextureTransform;
			}
			return null;
		}

		public static Matrix3x2? GetDiffuseTextureMatrix(this Material material, Animation track, float time)
		{
			TextureTransform diffuseTextureTransform = material.GetDiffuseTextureTransform();
			if (diffuseTextureTransform == null)
			{
				return null;
			}
			return diffuseTextureTransform.Matrix;
		}

		public static Mesh CreateMesh(this ModelRoot root, IMeshBuilder<MaterialBuilder> mesh)
		{
			return root.CreateMeshes(mesh)[0];
		}

		public static Mesh CreateMesh<TMaterial>(this ModelRoot root, Converter<TMaterial, Material> materialEvaluator, IMeshBuilder<TMaterial> mesh)
		{
			return root.CreateMeshes(materialEvaluator, mesh)[0];
		}

		public static IReadOnlyList<Mesh> CreateMeshes(this ModelRoot root, params IMeshBuilder<MaterialBuilder>[] meshBuilders)
		{
			Dictionary<MaterialBuilder, Material> materials = new Dictionary<MaterialBuilder, Material>(MaterialBuilder.ContentComparer);
			return root.CreateMeshes(matFactory, meshBuilders);
			Material matFactory(MaterialBuilder srcMat)
			{
				if (materials.TryGetValue(srcMat, out var value))
				{
					return value;
				}
				return materials[srcMat] = root.CreateMaterial(srcMat);
			}
		}

		public static IReadOnlyList<Mesh> CreateMeshes<TMaterial>(this ModelRoot root, Converter<TMaterial, Material> materialConverter, params IMeshBuilder<TMaterial>[] meshBuilders)
		{
			Guard.NotNull(root, "root");
			Guard.NotNull(materialConverter, "materialConverter");
			Guard.NotNull(meshBuilders, "meshBuilders");
			return root.CreateMeshes(materialConverter, SceneBuilderSchema2Settings.Default, meshBuilders);
		}

		public static IReadOnlyList<Mesh> CreateMeshes<TMaterial>(this ModelRoot root, Converter<TMaterial, Material> materialConverter, SceneBuilderSchema2Settings settings, params IMeshBuilder<TMaterial>[] meshBuilders)
		{
			Guard.NotNull(root, "root");
			Guard.NotNull(materialConverter, "materialConverter");
			Guard.NotNull(meshBuilders, "meshBuilders");
			Guard.IsTrue(meshBuilders.Length == meshBuilders.Distinct().Count(), "meshBuilders", "The collection has repeated meshes.");
			foreach (IMeshBuilder<TMaterial> meshBuilder in meshBuilders)
			{
				meshBuilder.Validate();
			}
			Dictionary<TMaterial, Material> mapMaterials = (from item in meshBuilders.SelectMany((IMeshBuilder<TMaterial> item) => item.Primitives)
				where !item.IsEmpty()
				select item.Material).Distinct().ToDictionary((TMaterial m) => m, (TMaterial m) => materialConverter(m));
			List<PackedMeshBuilder<TMaterial>> list = PackedMeshBuilder<TMaterial>.CreatePackedMeshes(meshBuilders, settings).ToList();
			if (settings.MergeBuffers)
			{
				PackedMeshBuilder<TMaterial>.MergeBuffers(list);
			}
			List<Mesh> list2 = new List<Mesh>();
			foreach (PackedMeshBuilder<TMaterial> item3 in list)
			{
				Mesh item2 = item3.CreateSchema2Mesh(root, (TMaterial m) => mapMaterials[m]);
				list2.Add(item2);
			}
			return list2;
		}

		public static MeshPrimitive WithIndicesAutomatic(this MeshPrimitive primitive, PrimitiveType primitiveType)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(primitive, "primitive");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			primitive.DrawPrimitiveType = primitiveType;
			primitive.SetIndexAccessor((Accessor)null);
			return primitive;
		}

		public static MeshPrimitive WithIndicesAccessor(this MeshPrimitive primitive, PrimitiveType primitiveType, IReadOnlyList<int> values)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(primitive, "primitive");
			Guard.NotNull(values, "values");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			BufferView val = logicalParent.CreateBufferView(4 * values.Count, 0, (BufferMode?)(BufferMode)34963);
			IntegerArray val2 = default(IntegerArray);
			((IntegerArray)(ref val2))..ctor((Memory<byte>)val.Content, (IndexEncodingType)5125);
			((IntegerArray)(ref val2)).Fill((IEnumerable<int>)values, 0);
			Accessor val3 = logicalParent.CreateAccessor((string)null);
			val3.SetIndexData(val, 0, values.Count, (IndexEncodingType)5125);
			primitive.DrawPrimitiveType = primitiveType;
			primitive.SetIndexAccessor(val3);
			return primitive;
		}

		public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<float> values)
		{
			Guard.NotNull(primitive, "primitive");
			Guard.NotNull(values, "values");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			BufferView val = logicalParent.CreateBufferView(4 * values.Count, 0, (BufferMode?)(BufferMode)34962);
			ScalarArray val2 = default(ScalarArray);
			((ScalarArray)(ref val2))..ctor((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
			((ScalarArray)(ref val2)).Fill((IEnumerable<float>)values, 0);
			Accessor val3 = logicalParent.CreateAccessor((string)null);
			primitive.SetVertexAccessor(attribute, val3);
			val3.SetVertexData(val, 0, values.Count, (DimensionType)0, (EncodingType)5126, false);
			return primitive;
		}

		public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<Vector2> values)
		{
			Guard.NotNull(primitive, "primitive");
			Guard.NotNull(values, "values");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			BufferView val = logicalParent.CreateBufferView(8 * values.Count, 0, (BufferMode?)(BufferMode)34962);
			Vector2Array val2 = default(Vector2Array);
			((Vector2Array)(ref val2))..ctor((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
			((Vector2Array)(ref val2)).Fill((IEnumerable<Vector2>)values, 0);
			Accessor val3 = logicalParent.CreateAccessor((string)null);
			primitive.SetVertexAccessor(attribute, val3);
			val3.SetVertexData(val, 0, values.Count, (DimensionType)1, (EncodingType)5126, false);
			return primitive;
		}

		public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<Vector3> values)
		{
			Guard.NotNull(primitive, "primitive");
			Guard.NotNull(values, "values");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			BufferView val = logicalParent.CreateBufferView(12 * values.Count, 0, (BufferMode?)(BufferMode)34962);
			Vector3Array val2 = default(Vector3Array);
			((Vector3Array)(ref val2))..ctor((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
			((Vector3Array)(ref val2)).Fill((IEnumerable<Vector3>)values, 0);
			Accessor val3 = logicalParent.CreateAccessor((string)null);
			val3.SetVertexData(val, 0, values.Count, (DimensionType)2, (EncodingType)5126, false);
			primitive.SetVertexAccessor(attribute, val3);
			return primitive;
		}

		public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<Vector4> values)
		{
			Guard.NotNull(primitive, "primitive");
			Guard.NotNull(values, "values");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			BufferView val = logicalParent.CreateBufferView(16 * values.Count, 0, (BufferMode?)(BufferMode)34962);
			Vector4Array val2 = default(Vector4Array);
			((Vector4Array)(ref val2))..ctor((Memory<byte>)val.Content, 0, (EncodingType)5126, false);
			((Vector4Array)(ref val2)).Fill((IEnumerable<Vector4>)values, 0);
			Accessor val3 = logicalParent.CreateAccessor((string)null);
			val3.SetVertexData(val, 0, values.Count, (DimensionType)3, (EncodingType)5126, false);
			primitive.SetVertexAccessor(attribute, val3);
			return primitive;
		}

		public static MeshPrimitive WithVertexAccessors(this MeshPrimitive primitive, IReadOnlyList<VertexPosition> vertices)
		{
			List<VertexBuilder<VertexPosition, VertexEmpty, VertexEmpty>> vertices2 = vertices.Select((VertexPosition item) => new VertexBuilder<VertexPosition, VertexEmpty, VertexEmpty>(in item)).ToList();
			return primitive.WithVertexAccessors(vertices2);
		}

		public static MeshPrimitive WithVertexAccessors(this MeshPrimitive primitive, IReadOnlyList<VertexPositionNormal> vertices)
		{
			List<VertexBuilder<VertexPositionNormal, VertexEmpty, VertexEmpty>> vertices2 = vertices.Select((VertexPositionNormal item) => new VertexBuilder<VertexPositionNormal, VertexEmpty, VertexEmpty>(in item)).ToList();
			return primitive.WithVertexAccessors(vertices2);
		}

		public static MeshPrimitive WithVertexAccessors<TvP, TvM>(this MeshPrimitive primitive, IReadOnlyList<(TvP Geo, TvM Mat)> vertices) where TvP : struct, IVertexGeometry where TvM : struct, IVertexMaterial
		{
			List<VertexBuilder<TvP, TvM, VertexEmpty>> vertices2 = vertices.Select(((TvP Geo, TvM Mat) item) => new VertexBuilder<TvP, TvM, VertexEmpty>(in item.Geo, in item.Mat)).ToList();
			return primitive.WithVertexAccessors(vertices2);
		}

		public static MeshPrimitive WithVertexAccessors<TvP, TvM, TvS>(this MeshPrimitive primitive, IReadOnlyList<(TvP Geo, TvM Mat, TvS Skin)> vertices) where TvP : struct, IVertexGeometry where TvM : struct, IVertexMaterial where TvS : struct, IVertexSkinning
		{
			List<VertexBuilder<TvP, TvM, TvS>> vertices2 = vertices.Select(((TvP Geo, TvM Mat, TvS Skin) item) => new VertexBuilder<TvP, TvM, TvS>(in item.Geo, in item.Mat, in item.Skin)).ToList();
			return primitive.WithVertexAccessors(vertices2);
		}

		public static MeshPrimitive WithVertexAccessors<TVertex>(this MeshPrimitive primitive, IReadOnlyList<TVertex> vertices) where TVertex : IVertexBuilder
		{
			MemoryAccessor[] memAccessors = vertices.CreateVertexMemoryAccessors(new PackedEncoding());
			return primitive.WithVertexAccessors((IEnumerable<MemoryAccessor>)memAccessors);
		}

		public static MeshPrimitive WithVertexAccessors(this MeshPrimitive primitive, IEnumerable<MemoryAccessor> memAccessors)
		{
			Guard.NotNull(memAccessors, "memAccessors");
			memAccessors = memAccessors.EnsureList();
			Guard.IsTrue(memAccessors.All((MemoryAccessor item) => item != null), "memAccessors");
			foreach (MemoryAccessor memAccessor in memAccessors)
			{
				primitive.WithVertexAccessor(memAccessor);
			}
			return primitive;
		}

		public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, MemoryAccessor memAccessor)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(primitive, "primitive");
			Guard.NotNull(memAccessor, "memAccessor");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			primitive.SetVertexAccessor(memAccessor.Attribute.Name, logicalParent.CreateVertexAccessor(memAccessor));
			return primitive;
		}

		public static MeshPrimitive WithIndicesAccessor(this MeshPrimitive primitive, PrimitiveType primitiveType, MemoryAccessor memAccessor)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(primitive, "primitive");
			ModelRoot logicalParent = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			Accessor val = logicalParent.CreateAccessor((string)null);
			val.SetIndexData(memAccessor);
			primitive.DrawPrimitiveType = primitiveType;
			primitive.SetIndexAccessor(val);
			return primitive;
		}

		public static MeshPrimitive WithMorphTargetAccessors(this MeshPrimitive primitive, int targetIndex, IEnumerable<MemoryAccessor> memAccessors)
		{
			Guard.NotNull(primitive, "primitive");
			Guard.MustBeGreaterThanOrEqualTo(targetIndex, 0, "targetIndex");
			Guard.NotNull(memAccessors, "memAccessors");
			ModelRoot root = ((LogicalChildOfRoot)primitive.LogicalParent).LogicalParent;
			Dictionary<string, Accessor> dictionary = memAccessors.ToDictionary((MemoryAccessor item) => item.Attribute.Name, (MemoryAccessor item) => root.CreateVertexAccessor(item));
			primitive.SetMorphTargetAccessors(targetIndex, (IReadOnlyDictionary<string, Accessor>)dictionary);
			return primitive;
		}

		public static MeshGpuInstancing WithInstanceAccessor<T>(this MeshGpuInstancing instancing, string attribute, IReadOnlyList<T> values) where T : unmanaged
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Invalid comparison between Unknown and I4
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			Guard.NotNull(instancing, "instancing");
			Guard.NotNull(values, "values");
			ModelRoot logicalParent = ((LogicalChildOfRoot)instancing.LogicalParent).LogicalParent;
			BufferView val = logicalParent.CreateBufferView(values);
			Accessor val2 = logicalParent.CreateAccessor((string)null);
			if (typeof(T) == typeof(int))
			{
				val2.SetIndexData(val, 0, values.Count, (IndexEncodingType)5125);
			}
			else
			{
				DimensionType val3 = (DimensionType)7;
				if (typeof(T) == typeof(float))
				{
					val3 = (DimensionType)0;
				}
				if (typeof(T) == typeof(Vector2))
				{
					val3 = (DimensionType)1;
				}
				if (typeof(T) == typeof(Vector3))
				{
					val3 = (DimensionType)2;
				}
				if (typeof(T) == typeof(Vector4))
				{
					val3 = (DimensionType)3;
				}
				if (typeof(T) == typeof(Quaternion))
				{
					val3 = (DimensionType)3;
				}
				if (typeof(T) == typeof(Matrix4x4))
				{
					val3 = (DimensionType)6;
				}
				if ((int)val3 == 7)
				{
					throw new ArgumentException(typeof(T).Name);
				}
				val2.SetVertexData(val, 0, values.Count, val3, (EncodingType)5126, false);
			}
			instancing.SetAccessor(attribute, val2);
			return instancing;
		}

		public static MeshGpuInstancing WithInstanceAccessors(this MeshGpuInstancing instancing, IReadOnlyList<AffineTransform> transforms)
		{
			Guard.NotNull(instancing, "instancing");
			Guard.NotNull(transforms, "transforms");
			List<AffineTransform> source = transforms.Select((AffineTransform item) => ((AffineTransform)(ref item)).GetDecomposed()).ToList();
			bool flag = source.Any((AffineTransform item) => ((AffineTransform)(ref item)).Scale != Vector3.One);
			bool flag2 = source.Any((AffineTransform item) => ((AffineTransform)(ref item)).Rotation != Quaternion.Identity);
			bool flag3 = source.Any((AffineTransform item) => ((AffineTransform)(ref item)).Translation != Vector3.Zero);
			if (flag)
			{
				instancing.WithInstanceAccessor("SCALE", source.Select((AffineTransform item) => ((AffineTransform)(ref item)).Scale).ToList());
			}
			if (flag2)
			{
				instancing.WithInstanceAccessor("ROTATION", source.Select((AffineTransform item) => ((AffineTransform)(ref item)).Rotation).ToList());
			}
			if (flag3)
			{
				instancing.WithInstanceAccessor("TRANSLATION", source.Select((AffineTransform item) => ((AffineTransform)(ref item)).Translation).ToList());
			}
			return instancing;
		}

		public static MeshGpuInstancing WithInstanceCustomAccessors(this MeshGpuInstancing instancing, IReadOnlyList<JsonNode> extras)
		{
			Guard.NotNull(instancing, "instancing");
			IEnumerable<string> enumerable = from item in (from item in extras.OfType<JsonObject>().SelectMany((JsonObject item) => item)
					select item.Key).Distinct()
				where item.StartsWith('_')
				select item;
			foreach (string item in enumerable)
			{
				instancing.WithInstanceCustomAccessor(item, extras);
			}
			return instancing;
		}

		public static MeshGpuInstancing WithInstanceCustomAccessor(this MeshGpuInstancing instancing, string attribute, IReadOnlyList<JsonNode> values)
		{
			Guard.NotNullOrEmpty(attribute, "attribute");
			attribute = attribute.ToUpperInvariant();
			List<int> list = _SelectAttribute<int>(values, attribute);
			if (list != null)
			{
				return instancing.WithInstanceAccessor(attribute, list);
			}
			List<float> list2 = _SelectAttribute<float>(values, attribute);
			if (list2 != null)
			{
				return instancing.WithInstanceAccessor(attribute, list2);
			}
			throw new ArgumentException("Can't retrieve " + attribute + " from values", "attribute");
		}

		private static List<T> _SelectAttribute<T>(IReadOnlyList<JsonNode> values, string propertyName)
		{
			List<T> list = new List<T>();
			foreach (JsonNode value2 in values)
			{
				JsonNode jsonNode = value2;
				if (jsonNode is JsonObject jsonObject && !jsonObject.TryGetPropertyValue(propertyName, out jsonNode))
				{
					return null;
				}
				if (!(jsonNode is JsonValue jsonValue))
				{
					return null;
				}
				if (!jsonValue.TryGetValue<T>(out T value))
				{
					return null;
				}
				list.Add(value);
			}
			return list;
		}

		public static MeshPrimitive WithMaterial(this MeshPrimitive primitive, Material material)
		{
			Guard.NotNull(primitive, "primitive");
			primitive.Material = material;
			return primitive;
		}

		public static IEnumerable<(IVertexBuilder A, Material Material)> EvaluatePoints(this Mesh mesh, IGeometryTransform xform = null)
		{
			if (mesh == null)
			{
				return Enumerable.Empty<(IVertexBuilder, Material)>();
			}
			return mesh.Primitives.SelectMany((MeshPrimitive item) => item.EvaluatePoints(xform));
		}

		public static IEnumerable<(IVertexBuilder A, Material Material)> EvaluatePoints(this MeshPrimitive prim, IGeometryTransform xform = null)
		{
			if (prim == null || (xform != null && !xform.Visible))
			{
				yield break;
			}
			IEnumerable<int> points = prim.GetPointIndices();
			VertexBufferColumns vertices = null;
			Func<IVertexBuilder> vtype = null;
			foreach (IGeometryTransform item in InstancingTransform.Evaluate(xform))
			{
				if (vertices == null)
				{
					vertices = prim.GetVertexColumns();
				}
				if (vtype == null)
				{
					vtype = vertices.GetCompatibleVertexType().BuilderFactory;
				}
				VertexBufferColumns xvertices = ((item != null) ? vertices.WithTransform(item) : vertices);
				foreach (int item2 in points)
				{
					IVertexBuilder vertex = xvertices.GetVertex(vtype, item2);
					yield return (vertex, prim.Material);
				}
			}
		}

		public static IEnumerable<(IVertexBuilder A, IVertexBuilder B, Material Material)> EvaluateLines(this Mesh mesh, IGeometryTransform xform = null)
		{
			if (mesh == null)
			{
				return Enumerable.Empty<(IVertexBuilder, IVertexBuilder, Material)>();
			}
			return mesh.Primitives.SelectMany((MeshPrimitive item) => item.EvaluateLines(xform));
		}

		public static IEnumerable<(IVertexBuilder A, IVertexBuilder B, Material Material)> EvaluateLines(this MeshPrimitive prim, IGeometryTransform xform = null)
		{
			i