|  |  |  |  | namespace MagicaVoxelToolbox { | 
					
						
							|  |  |  |  | 	using System.Collections; | 
					
						
							|  |  |  |  | 	using System.Collections.Generic; | 
					
						
							|  |  |  |  | 	using UnityEngine; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	public enum Direction { | 
					
						
							|  |  |  |  | 		Up = 0, | 
					
						
							|  |  |  |  | 		Down = 1, | 
					
						
							|  |  |  |  | 		Left = 2, | 
					
						
							|  |  |  |  | 		Right = 3, | 
					
						
							|  |  |  |  | 		Front = 4, | 
					
						
							|  |  |  |  | 		Back = 5, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	public class VoxelData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#region --- SUB --- | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		[System.Serializable] | 
					
						
							|  |  |  |  | 		public class MaterialData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public const int SHADER_NUM = 5; | 
					
						
							|  |  |  |  | 			public const int SHADER_PROPERTY_NUM = 13; | 
					
						
							|  |  |  |  | 			public static readonly Vector2[] SHADER_VALUE_REMAP_SOURCE = new Vector2[SHADER_PROPERTY_NUM] { | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 				new Vector2(0, 4), | 
					
						
							|  |  |  |  | 				new Vector2(0, 1), | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public enum MaterialType { | 
					
						
							|  |  |  |  | 				Diffuse = 0, | 
					
						
							|  |  |  |  | 				Metal = 1, | 
					
						
							|  |  |  |  | 				Glass = 2, | 
					
						
							|  |  |  |  | 				Emit = 3, | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public MaterialType Type; | 
					
						
							|  |  |  |  | 			public int Index; | 
					
						
							|  |  |  |  | 			public float Weight; | 
					
						
							|  |  |  |  | 			public float Rough; | 
					
						
							|  |  |  |  | 			public float Spec; | 
					
						
							|  |  |  |  | 			public float Ior; | 
					
						
							|  |  |  |  | 			public float Att; | 
					
						
							|  |  |  |  | 			public float Flux; | 
					
						
							|  |  |  |  | 			public float LDR; | 
					
						
							|  |  |  |  | 			public int Plastic; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public static MaterialType GetTypeFromString (string voxStr) { | 
					
						
							|  |  |  |  | 				switch (voxStr) { | 
					
						
							|  |  |  |  | 					default: | 
					
						
							|  |  |  |  | 					case "_diffuse": | 
					
						
							|  |  |  |  | 						return MaterialType.Diffuse; | 
					
						
							|  |  |  |  | 					case "_metal": | 
					
						
							|  |  |  |  | 						return MaterialType.Metal; | 
					
						
							|  |  |  |  | 					case "_glass": | 
					
						
							|  |  |  |  | 						return MaterialType.Glass; | 
					
						
							|  |  |  |  | 					case "_emit": | 
					
						
							|  |  |  |  | 						return MaterialType.Emit; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			public static string GetStringFromType (MaterialType type) { | 
					
						
							|  |  |  |  | 				switch (type) { | 
					
						
							|  |  |  |  | 					default: | 
					
						
							|  |  |  |  | 					case MaterialType.Diffuse: | 
					
						
							|  |  |  |  | 						return "_diffuse"; | 
					
						
							|  |  |  |  | 					case MaterialType.Metal: | 
					
						
							|  |  |  |  | 						return "_metal"; | 
					
						
							|  |  |  |  | 					case MaterialType.Glass: | 
					
						
							|  |  |  |  | 						return "_glass"; | 
					
						
							|  |  |  |  | 					case MaterialType.Emit: | 
					
						
							|  |  |  |  | 						return "_emit"; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public bool IsSameWith (MaterialData other) { | 
					
						
							|  |  |  |  | 				if (Type != other.Type) { return false; } | 
					
						
							|  |  |  |  | 				switch (Type) { | 
					
						
							|  |  |  |  | 					default: | 
					
						
							|  |  |  |  | 					case MaterialType.Diffuse: | 
					
						
							|  |  |  |  | 						return true; | 
					
						
							|  |  |  |  | 					case MaterialType.Metal: | 
					
						
							|  |  |  |  | 						return Weight == other.Weight && Rough == other.Rough && Spec == other.Spec && Plastic == other.Plastic; | 
					
						
							|  |  |  |  | 					case MaterialType.Glass: | 
					
						
							|  |  |  |  | 						return Weight == other.Weight && Rough == other.Rough && Ior == other.Ior && Att == other.Att; | 
					
						
							|  |  |  |  | 					case MaterialType.Emit: | 
					
						
							|  |  |  |  | 						return Weight == other.Weight && Flux == other.Flux && LDR == other.LDR; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		[System.Serializable] | 
					
						
							|  |  |  |  | 		public class TransformData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			[System.Serializable] | 
					
						
							|  |  |  |  | 			public class FrameData { | 
					
						
							|  |  |  |  | 				public Vector3 Rotation; | 
					
						
							|  |  |  |  | 				public Vector3 Position; | 
					
						
							|  |  |  |  | 				public Vector3 Scale; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public int ChildID; | 
					
						
							|  |  |  |  | 			public int LayerID; | 
					
						
							|  |  |  |  | 			public string Name; | 
					
						
							|  |  |  |  | 			public bool Hidden; | 
					
						
							|  |  |  |  | 			public int Reserved; | 
					
						
							|  |  |  |  | 			public FrameData[] Frames; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public class GroupData { | 
					
						
							|  |  |  |  | 			public Dictionary<string, string> Attributes; | 
					
						
							|  |  |  |  | 			public int[] ChildNodeId; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public class ShapeData { | 
					
						
							|  |  |  |  | 			public Dictionary<string, string> Attributes; | 
					
						
							|  |  |  |  | 			public KeyValuePair<int, Dictionary<string, string>>[] ModelData; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		[System.Serializable] | 
					
						
							|  |  |  |  | 		public class RigData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			[System.Serializable] | 
					
						
							|  |  |  |  | 			public class Bone { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				[System.NonSerialized] public Bone Parent = null; | 
					
						
							|  |  |  |  | 				[System.NonSerialized] public int ChildCount = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public int ParentIndex;// root >> -1 | 
					
						
							|  |  |  |  | 				public string Name; | 
					
						
							|  |  |  |  | 				public int PositionX; | 
					
						
							|  |  |  |  | 				public int PositionY; | 
					
						
							|  |  |  |  | 				public int PositionZ; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public static implicit operator bool (Bone bone) { | 
					
						
							|  |  |  |  | 					return bone != null; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			[System.Serializable] | 
					
						
							|  |  |  |  | 			public class Weight { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public int X; | 
					
						
							|  |  |  |  | 				public int Y; | 
					
						
							|  |  |  |  | 				public int Z; | 
					
						
							|  |  |  |  | 				public int BoneIndexA = -1; | 
					
						
							|  |  |  |  | 				public int BoneIndexB = -1; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public Weight () { | 
					
						
							|  |  |  |  | 					X = 0; | 
					
						
							|  |  |  |  | 					Y = 0; | 
					
						
							|  |  |  |  | 					Z = 0; | 
					
						
							|  |  |  |  | 					BoneIndexA = -1; | 
					
						
							|  |  |  |  | 					BoneIndexB = -1; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public Weight (int indexA, int indexB) { | 
					
						
							|  |  |  |  | 					X = 0; | 
					
						
							|  |  |  |  | 					Y = 0; | 
					
						
							|  |  |  |  | 					Z = 0; | 
					
						
							|  |  |  |  | 					BoneIndexA = indexA; | 
					
						
							|  |  |  |  | 					BoneIndexB = indexB; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public float GetWeight (int boneIndex) { | 
					
						
							|  |  |  |  | 					float weight = 0f; | 
					
						
							|  |  |  |  | 					if (boneIndex == BoneIndexA || boneIndex == BoneIndexB) { | 
					
						
							|  |  |  |  | 						weight = 0.5f; | 
					
						
							|  |  |  |  | 						if (BoneIndexA == -1 || BoneIndexB == -1) { | 
					
						
							|  |  |  |  | 							weight = 1f; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					return weight; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public void SetWeight (int boneIndex) { | 
					
						
							|  |  |  |  | 					if (BoneIndexA == boneIndex || BoneIndexB == boneIndex) { | 
					
						
							|  |  |  |  | 						return; | 
					
						
							|  |  |  |  | 					} else if (BoneIndexA == -1) { | 
					
						
							|  |  |  |  | 						BoneIndexA = boneIndex; | 
					
						
							|  |  |  |  | 					} else if (BoneIndexB == -1) { | 
					
						
							|  |  |  |  | 						BoneIndexB = boneIndex; | 
					
						
							|  |  |  |  | 					} else { | 
					
						
							|  |  |  |  | 						BoneIndexB = BoneIndexA; | 
					
						
							|  |  |  |  | 						BoneIndexA = boneIndex; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				public bool IndexEqualsTo (Weight other) { | 
					
						
							|  |  |  |  | 					return (BoneIndexA == other.BoneIndexA && BoneIndexB == other.BoneIndexB) || | 
					
						
							|  |  |  |  | 						(BoneIndexA == other.BoneIndexB && BoneIndexB == other.BoneIndexA); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public const int CURRENT_VERSION = 1; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public List<Bone> Bones; | 
					
						
							|  |  |  |  | 			public List<Weight> Weights; | 
					
						
							|  |  |  |  | 			public int Version = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public void FixVersion () { | 
					
						
							|  |  |  |  | 				if (Version == 0) { | 
					
						
							|  |  |  |  | 					if (Bones != null) { | 
					
						
							|  |  |  |  | 						for (int i = 0; i < Bones.Count; i++) { | 
					
						
							|  |  |  |  | 							var bone = Bones[i]; | 
					
						
							|  |  |  |  | 							bone.PositionX *= 2; | 
					
						
							|  |  |  |  | 							bone.PositionY *= 2; | 
					
						
							|  |  |  |  | 							bone.PositionZ *= 2; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				Version = CURRENT_VERSION; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public static List<Bone> GetHumanBones (Vector3 size, bool fullSize) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var bones = new List<Bone>(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Body | 
					
						
							|  |  |  |  | 				var hip = GetNewBone("Hips", null, 0.5f - 1f / size.x, 0.5f - 1f / size.y, 0.5f - 1f / size.z, size); | 
					
						
							|  |  |  |  | 				var spine = GetNewBone("Spine", hip, 0, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 				var chest = GetNewBone("Chest", spine, 0, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 				var _upperChest = GetNewBone("UpperChest", chest, 0, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 				var neck = GetNewBone("Neck", fullSize ? _upperChest : chest, 0, 0.15f, 0, size); | 
					
						
							|  |  |  |  | 				var head = GetNewBone("Head", neck, 0, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Head | 
					
						
							|  |  |  |  | 				var _eyeL = GetNewBone("LeftEye", head, -0.1f, 0.1f, 0, size); | 
					
						
							|  |  |  |  | 				var _eyeR = GetNewBone("RightEye", head, 0.1f, 0.1f, 0, size); | 
					
						
							|  |  |  |  | 				var _jaw = GetNewBone("Jaw", head, 0, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Arm | 
					
						
							|  |  |  |  | 				var _leftShoulder = GetNewBone("LeftShoulder", _upperChest, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _rightShoulder = GetNewBone("RightShoulder", _upperChest, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var armUL = GetNewBone("LeftUpperArm", fullSize ? _leftShoulder : chest, -0.1f, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 				var armUR = GetNewBone("RightUpperArm", fullSize ? _rightShoulder : chest, 0.1f, 0.05f, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var armDL = GetNewBone("LeftLowerArm", armUL, -0.2f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var armDR = GetNewBone("RightLowerArm", armUR, 0.2f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var handL = GetNewBone("LeftHand", armDL, -0.2f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var handR = GetNewBone("RightHand", armDR, 0.2f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Leg | 
					
						
							|  |  |  |  | 				var legUL = GetNewBone("LeftUpperLeg", hip, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var legUR = GetNewBone("RightUpperLeg", hip, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var legDL = GetNewBone("LeftLowerLeg", legUL, 0, -0.25f, 0, size); | 
					
						
							|  |  |  |  | 				var legDR = GetNewBone("RightLowerLeg", legUR, 0, -0.25f, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var footL = GetNewBone("LeftFoot", legDL, 0, -0.25f, 0, size); | 
					
						
							|  |  |  |  | 				var footR = GetNewBone("RightFoot", legDR, 0, -0.25f, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var _toeL = GetNewBone("LeftToes", footL, 0, 0, -0.05f, size); | 
					
						
							|  |  |  |  | 				var _toeR = GetNewBone("RightToes", footR, 0, 0, -0.05f, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				// Hand    | 
					
						
							|  |  |  |  | 				// Proximal > Intermediate > Distal | 
					
						
							|  |  |  |  | 				// Thumb Index Middle Ring Little | 
					
						
							|  |  |  |  | 				var _thumbProximalL = GetNewBone("Left Thumb Proximal", handL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _thumbProximalR = GetNewBone("Right Thumb Proximal", handR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _thumbIntermediateL = GetNewBone("Left Thumb Intermediate", _thumbProximalL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _thumbIntermediateR = GetNewBone("Right Thumb Intermediate", _thumbProximalR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _thumbDistalL = GetNewBone("Left Thumb Distal", _thumbIntermediateL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _thumbDistalR = GetNewBone("Right Thumb Distal", _thumbIntermediateR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var _indexProximalL = GetNewBone("Left Index Proximal", handL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _indexProximalR = GetNewBone("Right Index Proximal", handR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _indexIntermediateL = GetNewBone("Left Index Intermediate", _indexProximalL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _indexIntermediateR = GetNewBone("Right Index Intermediate", _indexProximalR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _indexDistalL = GetNewBone("Left Index Distal", _indexIntermediateL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _indexDistalR = GetNewBone("Right Index Distal", _indexIntermediateR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var _middleProximalL = GetNewBone("Left Middle Proximal", handL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _middleProximalR = GetNewBone("Right Middle Proximal", handR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _middleIntermediateL = GetNewBone("Left Middle Intermediate", _middleProximalL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _middleIntermediateR = GetNewBone("Right Middle Intermediate", _middleProximalR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _middleDistalL = GetNewBone("Left Middle Distal", _middleIntermediateL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _middleDistalR = GetNewBone("Right Middle Distal", _middleIntermediateR, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var _ringProximalL = GetNewBone("Left Ring Proximal", handL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _ringProximalR = GetNewBone("Right Ring Proximal", handR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _ringIntermediateL = GetNewBone("Left Ring Intermediate", _ringProximalL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _ringIntermediateR = GetNewBone("Right Ring Intermediate", _ringProximalR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _ringDistalL = GetNewBone("Left Ring Distal", _ringIntermediateL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _ringDistalR = GetNewBone("Right Ring Distal", _ringIntermediateR, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var _littleProximalL = GetNewBone("Left Little Proximal", handL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _littleProximalR = GetNewBone("Right Little Proximal", handR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _littleIntermediateL = GetNewBone("Left Little Intermediate", _littleProximalL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _littleIntermediateR = GetNewBone("Right Little Intermediate", _littleProximalR, 0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _littleDistalL = GetNewBone("Left Little Distal", _littleIntermediateL, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 				var _littleDistalR = GetNewBone("Right Little Distal", _littleIntermediateR, -0.05f, 0, 0, size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				bones.Add(hip); | 
					
						
							|  |  |  |  | 				bones.Add(spine); | 
					
						
							|  |  |  |  | 				bones.Add(chest); | 
					
						
							|  |  |  |  | 				bones.Add(neck); | 
					
						
							|  |  |  |  | 				bones.Add(head); | 
					
						
							|  |  |  |  | 				bones.Add(legUL); | 
					
						
							|  |  |  |  | 				bones.Add(legUR); | 
					
						
							|  |  |  |  | 				bones.Add(legDL); | 
					
						
							|  |  |  |  | 				bones.Add(legDR); | 
					
						
							|  |  |  |  | 				bones.Add(footL); | 
					
						
							|  |  |  |  | 				bones.Add(footR); | 
					
						
							|  |  |  |  | 				bones.Add(armUL); | 
					
						
							|  |  |  |  | 				bones.Add(armUR); | 
					
						
							|  |  |  |  | 				bones.Add(armDL); | 
					
						
							|  |  |  |  | 				bones.Add(armDR); | 
					
						
							|  |  |  |  | 				bones.Add(handL); | 
					
						
							|  |  |  |  | 				bones.Add(handR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (fullSize) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					bones.Add(_upperChest); | 
					
						
							|  |  |  |  | 					bones.Add(_eyeL); | 
					
						
							|  |  |  |  | 					bones.Add(_eyeR); | 
					
						
							|  |  |  |  | 					bones.Add(_jaw); | 
					
						
							|  |  |  |  | 					bones.Add(_leftShoulder); | 
					
						
							|  |  |  |  | 					bones.Add(_rightShoulder); | 
					
						
							|  |  |  |  | 					bones.Add(_toeL); | 
					
						
							|  |  |  |  | 					bones.Add(_toeR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					bones.Add(_thumbProximalL); | 
					
						
							|  |  |  |  | 					bones.Add(_thumbProximalR); | 
					
						
							|  |  |  |  | 					bones.Add(_thumbIntermediateL); | 
					
						
							|  |  |  |  | 					bones.Add(_thumbIntermediateR); | 
					
						
							|  |  |  |  | 					bones.Add(_thumbDistalL); | 
					
						
							|  |  |  |  | 					bones.Add(_thumbDistalR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					bones.Add(_indexProximalL); | 
					
						
							|  |  |  |  | 					bones.Add(_indexProximalR); | 
					
						
							|  |  |  |  | 					bones.Add(_indexIntermediateL); | 
					
						
							|  |  |  |  | 					bones.Add(_indexIntermediateR); | 
					
						
							|  |  |  |  | 					bones.Add(_indexDistalL); | 
					
						
							|  |  |  |  | 					bones.Add(_indexDistalR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					bones.Add(_middleProximalL); | 
					
						
							|  |  |  |  | 					bones.Add(_middleProximalR); | 
					
						
							|  |  |  |  | 					bones.Add(_middleIntermediateL); | 
					
						
							|  |  |  |  | 					bones.Add(_middleIntermediateR); | 
					
						
							|  |  |  |  | 					bones.Add(_middleDistalL); | 
					
						
							|  |  |  |  | 					bones.Add(_middleDistalR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					bones.Add(_ringProximalL); | 
					
						
							|  |  |  |  | 					bones.Add(_ringProximalR); | 
					
						
							|  |  |  |  | 					bones.Add(_ringIntermediateL); | 
					
						
							|  |  |  |  | 					bones.Add(_ringIntermediateR); | 
					
						
							|  |  |  |  | 					bones.Add(_ringDistalL); | 
					
						
							|  |  |  |  | 					bones.Add(_ringDistalR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 					bones.Add(_littleProximalL); | 
					
						
							|  |  |  |  | 					bones.Add(_littleProximalR); | 
					
						
							|  |  |  |  | 					bones.Add(_littleIntermediateL); | 
					
						
							|  |  |  |  | 					bones.Add(_littleIntermediateR); | 
					
						
							|  |  |  |  | 					bones.Add(_littleDistalL); | 
					
						
							|  |  |  |  | 					bones.Add(_littleDistalR); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				return bones; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public static Bone GetNewBone (string name, Bone parent, float x = 0, float y = 0, float z = 0, Vector3 size = default(Vector3)) { | 
					
						
							|  |  |  |  | 				x *= 2f; | 
					
						
							|  |  |  |  | 				y *= 2f; | 
					
						
							|  |  |  |  | 				z *= 2f; | 
					
						
							|  |  |  |  | 				return new Bone() { | 
					
						
							|  |  |  |  | 					Name = name, | 
					
						
							|  |  |  |  | 					Parent = parent, | 
					
						
							|  |  |  |  | 					PositionX = x > 0 ? Mathf.CeilToInt(x * size.x) : Mathf.FloorToInt(x * size.x), | 
					
						
							|  |  |  |  | 					PositionY = y > 0 ? Mathf.CeilToInt(y * size.y) : Mathf.FloorToInt(y * size.y), | 
					
						
							|  |  |  |  | 					PositionZ = z > 0 ? Mathf.CeilToInt(z * size.z) : Mathf.FloorToInt(z * size.z), | 
					
						
							|  |  |  |  | 				}; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#region --- VAR --- | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public int Version = -1; | 
					
						
							|  |  |  |  | 		public List<int[,,]> Voxels = new List<int[,,]>(); | 
					
						
							|  |  |  |  | 		public List<Color> Palette = new List<Color>(); | 
					
						
							|  |  |  |  | 		public List<MaterialData> Materials = new List<MaterialData>(); | 
					
						
							|  |  |  |  | 		public Dictionary<int, TransformData> Transforms = new Dictionary<int, TransformData>(); | 
					
						
							|  |  |  |  | 		public Dictionary<int, GroupData> Groups = new Dictionary<int, GroupData>(); | 
					
						
							|  |  |  |  | 		public Dictionary<int, ShapeData> Shapes = new Dictionary<int, ShapeData>(); | 
					
						
							|  |  |  |  | 		public Dictionary<int, RigData> Rigs = new Dictionary<int, RigData>(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#region --- API --- | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public Color GetColorFromPalette (int index) { | 
					
						
							|  |  |  |  | 			index--; | 
					
						
							|  |  |  |  | 			return index >= 0 && index < Palette.Count ? Palette[index] : Color.clear; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public Vector3 GetModelSize (int index) { | 
					
						
							|  |  |  |  | 			return new Vector3( | 
					
						
							|  |  |  |  | 				Voxels[index].GetLength(0), | 
					
						
							|  |  |  |  | 				Voxels[index].GetLength(1), | 
					
						
							|  |  |  |  | 				Voxels[index].GetLength(2) | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public Vector3 GetFootPoint (int index) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			var voxels = Voxels[index]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			int sizeX = voxels.GetLength(0); | 
					
						
							|  |  |  |  | 			int sizeY = voxels.GetLength(1); | 
					
						
							|  |  |  |  | 			int sizeZ = voxels.GetLength(2); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			for (int y = 0; y < sizeY; y++) { | 
					
						
							|  |  |  |  | 				Vector3 foot = Vector3.zero; | 
					
						
							|  |  |  |  | 				int footCount = 0; | 
					
						
							|  |  |  |  | 				for (int x = 0; x < sizeX; x++) { | 
					
						
							|  |  |  |  | 					for (int z = 0; z < sizeZ; z++) { | 
					
						
							|  |  |  |  | 						var voxel = voxels[x, y, z]; | 
					
						
							|  |  |  |  | 						if (voxel != 0) { | 
					
						
							|  |  |  |  | 							foot += new Vector3(x, y, z); | 
					
						
							|  |  |  |  | 							footCount++; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				if (footCount > 0) { | 
					
						
							|  |  |  |  | 					return foot / footCount; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			return Vector3.zero; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public Vector3 GetBounds () { | 
					
						
							|  |  |  |  | 			Vector3 bounds = Vector3.zero; | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Voxels.Count; i++) { | 
					
						
							|  |  |  |  | 				var size = GetModelSize(i); | 
					
						
							|  |  |  |  | 				bounds = Vector3.Max(bounds, size); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			return bounds; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public VoxelData GetCopy () { | 
					
						
							|  |  |  |  | 			return new VoxelData() { | 
					
						
							|  |  |  |  | 				Version = Version, | 
					
						
							|  |  |  |  | 				Voxels = new List<int[,,]>(Voxels), | 
					
						
							|  |  |  |  | 				Palette = new List<Color>(Palette), | 
					
						
							|  |  |  |  | 				Transforms = new Dictionary<int, TransformData>(Transforms), | 
					
						
							|  |  |  |  | 				Groups = new Dictionary<int, GroupData>(Groups), | 
					
						
							|  |  |  |  | 				Shapes = new Dictionary<int, ShapeData>(Shapes), | 
					
						
							|  |  |  |  | 				Materials = new List<MaterialData>(Materials), | 
					
						
							|  |  |  |  | 				Rigs = new Dictionary<int, RigData>(Rigs), | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public void GetModelTransform (int index, out Vector3 pos, out Vector3 rot, out Vector3 scale) { | 
					
						
							|  |  |  |  | 			pos = Vector3.zero; | 
					
						
							|  |  |  |  | 			rot = Vector3.zero; | 
					
						
							|  |  |  |  | 			scale = Vector3.one; | 
					
						
							|  |  |  |  | 			foreach (var tf in Transforms) { | 
					
						
							|  |  |  |  | 				bool success = false; | 
					
						
							|  |  |  |  | 				int id = tf.Value.ChildID; | 
					
						
							|  |  |  |  | 				if (Shapes.ContainsKey(id)) { | 
					
						
							|  |  |  |  | 					var shape = Shapes[id]; | 
					
						
							|  |  |  |  | 					for (int i = 0; i < shape.ModelData.Length; i++) { | 
					
						
							|  |  |  |  | 						if (shape.ModelData[i].Key == index) { | 
					
						
							|  |  |  |  | 							if (tf.Value.Frames.Length > 0) { | 
					
						
							|  |  |  |  | 								var frame = tf.Value.Frames[0]; | 
					
						
							|  |  |  |  | 								pos = frame.Position; | 
					
						
							|  |  |  |  | 								rot = frame.Rotation; | 
					
						
							|  |  |  |  | 								scale = frame.Scale; | 
					
						
							|  |  |  |  | 							} | 
					
						
							|  |  |  |  | 							success = true; | 
					
						
							|  |  |  |  | 							break; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				if (success) { | 
					
						
							|  |  |  |  | 					break; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public Texture2D GetThumbnail (int index, bool positiveZ = true) { | 
					
						
							|  |  |  |  | 			if (Voxels == null || index >= Voxels.Count || index < 0) { return null; } | 
					
						
							|  |  |  |  | 			var voxels = Voxels[index]; | 
					
						
							|  |  |  |  | 			int sizeX = voxels.GetLength(0); | 
					
						
							|  |  |  |  | 			int sizeY = voxels.GetLength(1); | 
					
						
							|  |  |  |  | 			int sizeZ = voxels.GetLength(2); | 
					
						
							|  |  |  |  | 			Texture2D texture = new Texture2D(sizeX, sizeY, TextureFormat.ARGB32, false); | 
					
						
							|  |  |  |  | 			var colors = new Color[sizeX * sizeY]; | 
					
						
							|  |  |  |  | 			for (int x = 0; x < sizeX; x++) { | 
					
						
							|  |  |  |  | 				for (int y = 0; y < sizeY; y++) { | 
					
						
							|  |  |  |  | 					Color c = Color.clear; | 
					
						
							|  |  |  |  | 					for (int z = positiveZ ? 0 : sizeZ - 1; positiveZ ? z < sizeZ : z >= 0; z += positiveZ ? 1 : -1) { | 
					
						
							|  |  |  |  | 						if (voxels[x, y, z] != 0) { | 
					
						
							|  |  |  |  | 							c = GetColorFromPalette(voxels[x, y, z]); | 
					
						
							|  |  |  |  | 							break; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					colors[y * sizeX + (positiveZ ? x : sizeX - 1 - x)] = c; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			texture.filterMode = FilterMode.Point; | 
					
						
							|  |  |  |  | 			texture.SetPixels(colors); | 
					
						
							|  |  |  |  | 			texture.Apply(); | 
					
						
							|  |  |  |  | 			return texture; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public bool IsExposed (int index, int x, int y, int z, int sizeX, int sizeY, int sizeZ, Direction dir, List<MaterialData> materials = null) { | 
					
						
							|  |  |  |  | 			return IsExposed(Voxels[index], x, y, z, sizeX, sizeY, sizeZ, dir, materials); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public void ResetToDefaultNode () { | 
					
						
							|  |  |  |  | 			Transforms.Clear(); | 
					
						
							|  |  |  |  | 			Groups.Clear(); | 
					
						
							|  |  |  |  | 			Shapes.Clear(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			Transforms.Add(0, new TransformData() { | 
					
						
							|  |  |  |  | 				ChildID = 1, | 
					
						
							|  |  |  |  | 				Hidden = false, | 
					
						
							|  |  |  |  | 				LayerID = -1, | 
					
						
							|  |  |  |  | 				Name = "Root", | 
					
						
							|  |  |  |  | 				Reserved = -1, | 
					
						
							|  |  |  |  | 				Frames = new TransformData.FrameData[1] { | 
					
						
							|  |  |  |  | 					new TransformData.FrameData() { | 
					
						
							|  |  |  |  | 						Position = Vector3.zero, | 
					
						
							|  |  |  |  | 						Rotation = Vector3.zero, | 
					
						
							|  |  |  |  | 						Scale = Vector3.one, | 
					
						
							|  |  |  |  | 					}, | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			Groups.Add(1, new GroupData() { | 
					
						
							|  |  |  |  | 				Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 				ChildNodeId = new int[1] { 2 }, | 
					
						
							|  |  |  |  | 			}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			Transforms.Add(2, new TransformData() { | 
					
						
							|  |  |  |  | 				ChildID = 3, | 
					
						
							|  |  |  |  | 				Hidden = false, | 
					
						
							|  |  |  |  | 				LayerID = -1, | 
					
						
							|  |  |  |  | 				Name = "Root", | 
					
						
							|  |  |  |  | 				Reserved = -1, | 
					
						
							|  |  |  |  | 				Frames = new TransformData.FrameData[1] { | 
					
						
							|  |  |  |  | 					new TransformData.FrameData() { | 
					
						
							|  |  |  |  | 						Position = Vector3.zero, | 
					
						
							|  |  |  |  | 						Rotation = Vector3.zero, | 
					
						
							|  |  |  |  | 						Scale = Vector3.one, | 
					
						
							|  |  |  |  | 					}, | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			Shapes.Add(3, new ShapeData() { | 
					
						
							|  |  |  |  | 				Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 				ModelData = new KeyValuePair<int, Dictionary<string, string>>[1] { | 
					
						
							|  |  |  |  | 					new KeyValuePair<int, Dictionary<string, string>>(0, new Dictionary<string, string>()) | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public void Rotate180InY () { | 
					
						
							|  |  |  |  | 			if (Shapes.Count == 1) { | 
					
						
							|  |  |  |  | 				for (int i = 0; i < Voxels.Count; i++) { | 
					
						
							|  |  |  |  | 					var source = Voxels[i]; | 
					
						
							|  |  |  |  | 					int sizeX = source.GetLength(0); | 
					
						
							|  |  |  |  | 					int sizeY = source.GetLength(1); | 
					
						
							|  |  |  |  | 					int sizeZ = source.GetLength(2); | 
					
						
							|  |  |  |  | 					var voxels = new int[sizeX, sizeY, sizeZ]; | 
					
						
							|  |  |  |  | 					for (int x = 0; x < sizeX; x++) { | 
					
						
							|  |  |  |  | 						for (int y = 0; y < sizeY; y++) { | 
					
						
							|  |  |  |  | 							for (int z = 0; z < sizeZ; z++) { | 
					
						
							|  |  |  |  | 								voxels[x, y, z] = source[sizeX - x - 1, y, sizeZ - z - 1]; | 
					
						
							|  |  |  |  | 							} | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					Voxels[i] = voxels; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} else if (Transforms.ContainsKey(0) && Transforms[0].Frames.Length > 0) { | 
					
						
							|  |  |  |  | 				Transforms[0].Frames[0].Rotation.y += 180; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// Global API | 
					
						
							|  |  |  |  | 		public static VoxelData CreateNewData () { | 
					
						
							|  |  |  |  | 			var data = new VoxelData() { | 
					
						
							|  |  |  |  | 				Version = 150, | 
					
						
							|  |  |  |  | 				Materials = new List<MaterialData>(), | 
					
						
							|  |  |  |  | 				Palette = new List<Color>() { Color.white }, | 
					
						
							|  |  |  |  | 				Rigs = new Dictionary<int, RigData>(), | 
					
						
							|  |  |  |  | 				Voxels = new List<int[,,]>() { | 
					
						
							|  |  |  |  | 					new int[1,1,1]{ { { 1 } } }, | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 			data.ResetToDefaultNode(); | 
					
						
							|  |  |  |  | 			return data; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public static bool IsExposed (int[,,] voxels, int x, int y, int z, int sizeX, int sizeY, int sizeZ, Direction dir, List<MaterialData> materials = null) { | 
					
						
							|  |  |  |  | 			bool exposed = false; | 
					
						
							|  |  |  |  | 			if (voxels[x, y, z] != 0) { | 
					
						
							|  |  |  |  | 				switch (dir) { | 
					
						
							|  |  |  |  | 					case Direction.Up: | 
					
						
							|  |  |  |  | 						exposed = y == sizeY - 1 || voxels[x, y + 1, z] == 0; | 
					
						
							|  |  |  |  | 						break; | 
					
						
							|  |  |  |  | 					case Direction.Down: | 
					
						
							|  |  |  |  | 						exposed = y == 0 || voxels[x, y - 1, z] == 0; | 
					
						
							|  |  |  |  | 						break; | 
					
						
							|  |  |  |  | 					case Direction.Left: | 
					
						
							|  |  |  |  | 						exposed = x == 0 || voxels[x - 1, y, z] == 0; | 
					
						
							|  |  |  |  | 						break; | 
					
						
							|  |  |  |  | 					case Direction.Right: | 
					
						
							|  |  |  |  | 						exposed = x == sizeX - 1 || voxels[x + 1, y, z] == 0; | 
					
						
							|  |  |  |  | 						break; | 
					
						
							|  |  |  |  | 					case Direction.Front: | 
					
						
							|  |  |  |  | 						exposed = z == sizeZ - 1 || voxels[x, y, z + 1] == 0; | 
					
						
							|  |  |  |  | 						break; | 
					
						
							|  |  |  |  | 					case Direction.Back: | 
					
						
							|  |  |  |  | 						exposed = z == 0 || voxels[x, y, z - 1] == 0; | 
					
						
							|  |  |  |  | 						break; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				if (materials != null && !exposed) { | 
					
						
							|  |  |  |  | 					int voxel = voxels[x, y, z]; | 
					
						
							|  |  |  |  | 					var material = voxel >= 0 && voxel < materials.Count ? materials[voxel] : null; | 
					
						
							|  |  |  |  | 					if (material != null && material.Type != MaterialData.MaterialType.Glass) { | 
					
						
							|  |  |  |  | 						int blockingVoxel = 0; | 
					
						
							|  |  |  |  | 						switch (dir) { | 
					
						
							|  |  |  |  | 							case Direction.Up: | 
					
						
							|  |  |  |  | 								blockingVoxel = y == sizeY - 1 ? -1 : voxels[x, y + 1, z]; | 
					
						
							|  |  |  |  | 								break; | 
					
						
							|  |  |  |  | 							case Direction.Down: | 
					
						
							|  |  |  |  | 								blockingVoxel = y == 0 ? -1 : voxels[x, y - 1, z]; | 
					
						
							|  |  |  |  | 								break; | 
					
						
							|  |  |  |  | 							case Direction.Left: | 
					
						
							|  |  |  |  | 								blockingVoxel = x == 0 ? -1 : voxels[x - 1, y, z]; | 
					
						
							|  |  |  |  | 								break; | 
					
						
							|  |  |  |  | 							case Direction.Right: | 
					
						
							|  |  |  |  | 								blockingVoxel = x == sizeX - 1 ? -1 : voxels[x + 1, y, z]; | 
					
						
							|  |  |  |  | 								break; | 
					
						
							|  |  |  |  | 							case Direction.Front: | 
					
						
							|  |  |  |  | 								blockingVoxel = z == sizeZ - 1 ? -1 : voxels[x, y, z + 1]; | 
					
						
							|  |  |  |  | 								break; | 
					
						
							|  |  |  |  | 							case Direction.Back: | 
					
						
							|  |  |  |  | 								blockingVoxel = z == 0 ? -1 : voxels[x, y, z - 1]; | 
					
						
							|  |  |  |  | 								break; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 						var blockingMaterial = blockingVoxel >= 0 && blockingVoxel < materials.Count ? materials[blockingVoxel] : null; | 
					
						
							|  |  |  |  | 						if (blockingMaterial != null && blockingMaterial.Type == MaterialData.MaterialType.Glass) { | 
					
						
							|  |  |  |  | 							exposed = true; | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			return exposed; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public static Material GetMaterialFrom (MaterialData mat, Texture2D texture, Shader[] shaders, string[] keywords, Vector2[] remaps, string mainTexKeyword) { | 
					
						
							|  |  |  |  | 			if (mat == null || shaders == null || keywords == null || remaps == null) { | 
					
						
							|  |  |  |  | 				return new Material(shaders != null && shaders.Length > 0 ? shaders[0] : Shader.Find("Mobile/Diffuse")) { mainTexture = texture }; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			Material material; | 
					
						
							|  |  |  |  | 			if (shaders.Length < 5) { | 
					
						
							|  |  |  |  | 				var shader = shaders.Length > 0 ? shaders[0] : Shader.Find("Mobile/Diffuse"); | 
					
						
							|  |  |  |  | 				shaders = new Shader[5] { shader, shader, shader, shader, shader }; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			switch (mat.Type) { | 
					
						
							|  |  |  |  | 				default: | 
					
						
							|  |  |  |  | 				case MaterialData.MaterialType.Diffuse: | 
					
						
							|  |  |  |  | 					material = new Material(shaders[0]); | 
					
						
							|  |  |  |  | 					break; | 
					
						
							|  |  |  |  | 				case MaterialData.MaterialType.Metal: | 
					
						
							|  |  |  |  | 					if (mat.Plastic == 0) { | 
					
						
							|  |  |  |  | 						material = new Material(shaders[1]); | 
					
						
							|  |  |  |  | 						Util.SetMaterialFloatOrColor(material, keywords[0], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[0].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[0].y, remaps[0].x, remaps[0].y, mat.Weight));// Weight | 
					
						
							|  |  |  |  | 						Util.SetMaterialFloatOrColor(material, keywords[1], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[1].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[1].y, remaps[1].x, remaps[1].y, mat.Rough));// Rough | 
					
						
							|  |  |  |  | 						Util.SetMaterialFloatOrColor(material, keywords[2], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[2].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[2].y, remaps[2].x, remaps[2].y, mat.Spec));// Specular | 
					
						
							|  |  |  |  | 					} else { | 
					
						
							|  |  |  |  | 						material = new Material(shaders[2]); | 
					
						
							|  |  |  |  | 						Util.SetMaterialFloatOrColor(material, keywords[3], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[3].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[3].y, remaps[3].x, remaps[3].y, mat.Weight));// Weight | 
					
						
							|  |  |  |  | 						Util.SetMaterialFloatOrColor(material, keywords[4], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[4].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[4].y, remaps[4].x, remaps[4].y, mat.Rough));// Rough | 
					
						
							|  |  |  |  | 						Util.SetMaterialFloatOrColor(material, keywords[5], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[5].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[5].y, remaps[5].x, remaps[5].y, mat.Spec));// Specular | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					break; | 
					
						
							|  |  |  |  | 				case MaterialData.MaterialType.Glass: | 
					
						
							|  |  |  |  | 					material = new Material(shaders[3]); | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[6], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[6].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[6].y, remaps[6].x, remaps[6].y, mat.Weight));// Weight | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[7], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[7].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[7].y, remaps[7].x, remaps[7].y, mat.Rough));// Rough | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[8], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[8].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[8].y, remaps[8].x, remaps[8].y, mat.Ior));// Refract | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[9], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[9].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[9].y, remaps[9].x, remaps[9].y, mat.Att));// Att | 
					
						
							|  |  |  |  | 					break; | 
					
						
							|  |  |  |  | 				case MaterialData.MaterialType.Emit: | 
					
						
							|  |  |  |  | 					material = new Material(shaders[4]); | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[10], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[10].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[10].y, remaps[10].x, remaps[10].y, mat.Weight));// Weight | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[11], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[11].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[11].y, remaps[11].x, remaps[11].y, mat.Flux));// Power | 
					
						
							|  |  |  |  | 					Util.SetMaterialFloatOrColor(material, keywords[12], Util.Remap(MaterialData.SHADER_VALUE_REMAP_SOURCE[12].x, MaterialData.SHADER_VALUE_REMAP_SOURCE[12].y, remaps[12].x, remaps[12].y, mat.LDR));// ldr | 
					
						
							|  |  |  |  | 					break; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			material.SetTexture(mainTexKeyword, texture); | 
					
						
							|  |  |  |  | 			return material; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public static implicit operator bool (VoxelData data) { | 
					
						
							|  |  |  |  | 			return data != null; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public static VoxelData GetSplitedData (VoxelData source) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			const int SPLIT_SIZE = 126; | 
					
						
							|  |  |  |  | 			if (source.Voxels.Count == 0) { | 
					
						
							|  |  |  |  | 				return source; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			var size = source.GetModelSize(0); | 
					
						
							|  |  |  |  | 			int sizeX = Mathf.RoundToInt(size.x); | 
					
						
							|  |  |  |  | 			int sizeY = Mathf.RoundToInt(size.y); | 
					
						
							|  |  |  |  | 			int sizeZ = Mathf.RoundToInt(size.z); | 
					
						
							|  |  |  |  | 			if (sizeX <= SPLIT_SIZE && sizeY <= SPLIT_SIZE && sizeZ <= SPLIT_SIZE) { | 
					
						
							|  |  |  |  | 				return source; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			int splitCountX = (sizeX / SPLIT_SIZE) + 1; | 
					
						
							|  |  |  |  | 			int splitCountY = (sizeY / SPLIT_SIZE) + 1; | 
					
						
							|  |  |  |  | 			int splitCountZ = (sizeZ / SPLIT_SIZE) + 1; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			var data = new VoxelData(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Nodes | 
					
						
							|  |  |  |  | 			var childNodeId = new int[splitCountX * splitCountY * splitCountZ]; | 
					
						
							|  |  |  |  | 			for (int i = 0; i < childNodeId.Length; i++) { | 
					
						
							|  |  |  |  | 				childNodeId[i] = i * 2 + 2; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			data.Voxels = new List<int[,,]>(); | 
					
						
							|  |  |  |  | 			data.Transforms = new Dictionary<int, TransformData>() { | 
					
						
							|  |  |  |  | 				{ 0, new TransformData(){ | 
					
						
							|  |  |  |  | 					Name = "", | 
					
						
							|  |  |  |  | 					ChildID = 1, | 
					
						
							|  |  |  |  | 					Hidden = false, | 
					
						
							|  |  |  |  | 					LayerID = 0, | 
					
						
							|  |  |  |  | 					Reserved = 0, | 
					
						
							|  |  |  |  | 					Frames = new TransformData.FrameData[1]{ | 
					
						
							|  |  |  |  | 						new TransformData.FrameData(){ | 
					
						
							|  |  |  |  | 							Position = Vector3.zero, | 
					
						
							|  |  |  |  | 							Rotation = Vector3.zero, | 
					
						
							|  |  |  |  | 							Scale = Vector3.one, | 
					
						
							|  |  |  |  | 						}, | 
					
						
							|  |  |  |  | 					}, | 
					
						
							|  |  |  |  | 				}}, | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 			data.Groups = new Dictionary<int, GroupData>() { | 
					
						
							|  |  |  |  | 				{1, new GroupData(){ | 
					
						
							|  |  |  |  | 					Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 					ChildNodeId = childNodeId, | 
					
						
							|  |  |  |  | 				}}, | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 			data.Shapes = new Dictionary<int, ShapeData>(); | 
					
						
							|  |  |  |  | 			data.Palette = new List<Color>(source.Palette); | 
					
						
							|  |  |  |  | 			data.Version = source.Version; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			int _i = 0; | 
					
						
							|  |  |  |  | 			for (int x = 0; x < splitCountX; x++) { | 
					
						
							|  |  |  |  | 				for (int y = 0; y < splitCountY; y++) { | 
					
						
							|  |  |  |  | 					for (int z = 0; z < splitCountZ; z++) { | 
					
						
							|  |  |  |  | 						int splitSizeX = x < splitCountX - 1 ? SPLIT_SIZE : (sizeX - x * SPLIT_SIZE) % SPLIT_SIZE; | 
					
						
							|  |  |  |  | 						int splitSizeY = y < splitCountY - 1 ? SPLIT_SIZE : (sizeY - y * SPLIT_SIZE) % SPLIT_SIZE; | 
					
						
							|  |  |  |  | 						int splitSizeZ = z < splitCountZ - 1 ? SPLIT_SIZE : (sizeZ - z * SPLIT_SIZE) % SPLIT_SIZE; | 
					
						
							|  |  |  |  | 						int childID = childNodeId[_i]; | 
					
						
							|  |  |  |  | 						data.Transforms.Add(childID, new TransformData() { | 
					
						
							|  |  |  |  | 							Name = "Splited_Model_" + _i, | 
					
						
							|  |  |  |  | 							Reserved = 0, | 
					
						
							|  |  |  |  | 							LayerID = 0, | 
					
						
							|  |  |  |  | 							Hidden = false, | 
					
						
							|  |  |  |  | 							ChildID = childID + 1, | 
					
						
							|  |  |  |  | 							Frames = new TransformData.FrameData[1] { | 
					
						
							|  |  |  |  | 								new TransformData.FrameData(){ | 
					
						
							|  |  |  |  | 									Position = new Vector3( | 
					
						
							|  |  |  |  | 										x * SPLIT_SIZE + splitSizeX / 2, | 
					
						
							|  |  |  |  | 										y * SPLIT_SIZE + splitSizeY / 2, | 
					
						
							|  |  |  |  | 										z * SPLIT_SIZE + splitSizeZ / 2 | 
					
						
							|  |  |  |  | 									), | 
					
						
							|  |  |  |  | 									Rotation = Vector3.zero, | 
					
						
							|  |  |  |  | 									Scale = Vector3.one, | 
					
						
							|  |  |  |  | 								}, | 
					
						
							|  |  |  |  | 							}, | 
					
						
							|  |  |  |  | 						}); | 
					
						
							|  |  |  |  | 						data.Shapes.Add(childID + 1, new ShapeData() { | 
					
						
							|  |  |  |  | 							Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 							ModelData = new KeyValuePair<int, Dictionary<string, string>>[] { | 
					
						
							|  |  |  |  | 								new KeyValuePair<int, Dictionary<string, string>>(_i, new Dictionary<string, string>()), | 
					
						
							|  |  |  |  | 							}, | 
					
						
							|  |  |  |  | 						}); | 
					
						
							|  |  |  |  | 						_i++; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Split | 
					
						
							|  |  |  |  | 			var sourceVoxels = source.Voxels[0]; | 
					
						
							|  |  |  |  | 			for (int x = 0; x < splitCountX; x++) { | 
					
						
							|  |  |  |  | 				for (int y = 0; y < splitCountY; y++) { | 
					
						
							|  |  |  |  | 					for (int z = 0; z < splitCountZ; z++) { | 
					
						
							|  |  |  |  | 						int splitSizeX = x < splitCountX - 1 ? SPLIT_SIZE : (sizeX - x * SPLIT_SIZE) % SPLIT_SIZE; | 
					
						
							|  |  |  |  | 						int splitSizeY = y < splitCountY - 1 ? SPLIT_SIZE : (sizeY - y * SPLIT_SIZE) % SPLIT_SIZE; | 
					
						
							|  |  |  |  | 						int splitSizeZ = z < splitCountZ - 1 ? SPLIT_SIZE : (sizeZ - z * SPLIT_SIZE) % SPLIT_SIZE; | 
					
						
							|  |  |  |  | 						var voxels = new int[splitSizeX, splitSizeY, splitSizeZ]; | 
					
						
							|  |  |  |  | 						for (int i = 0; i < splitSizeX; i++) { | 
					
						
							|  |  |  |  | 							for (int j = 0; j < splitSizeY; j++) { | 
					
						
							|  |  |  |  | 								for (int k = 0; k < splitSizeZ; k++) { | 
					
						
							|  |  |  |  | 									voxels[i, j, k] = sourceVoxels[ | 
					
						
							|  |  |  |  | 										x * SPLIT_SIZE + i, | 
					
						
							|  |  |  |  | 										y * SPLIT_SIZE + j, | 
					
						
							|  |  |  |  | 										z * SPLIT_SIZE + k | 
					
						
							|  |  |  |  | 									]; | 
					
						
							|  |  |  |  | 								} | 
					
						
							|  |  |  |  | 							} | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 						data.Voxels.Add(voxels); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			return data; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#region --- LOD --- | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public void LodIteration (int lodLevel) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			Rigs.Clear(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			for (int index = 0; index < Voxels.Count; index++) { | 
					
						
							|  |  |  |  | 				var size = GetModelSize(index); | 
					
						
							|  |  |  |  | 				int sizeX = (int)size.x; | 
					
						
							|  |  |  |  | 				int sizeY = (int)size.y; | 
					
						
							|  |  |  |  | 				int sizeZ = (int)size.z; | 
					
						
							|  |  |  |  | 				int range = lodLevel + Mathf.Max(1, (sizeX + sizeY + sizeZ) / 42); | 
					
						
							|  |  |  |  | 				bool allZero = true; | 
					
						
							|  |  |  |  | 				int[,,] voxels = new int[sizeX, sizeY, sizeZ]; | 
					
						
							|  |  |  |  | 				int[,,] sourceVoxels = Voxels[index]; | 
					
						
							|  |  |  |  | 				for (int x = 0; x < sizeX - range; x++) { | 
					
						
							|  |  |  |  | 					for (int y = 0; y < sizeY - range; y++) { | 
					
						
							|  |  |  |  | 						for (int z = 0; z < sizeZ - range; z++) { | 
					
						
							|  |  |  |  | 							if (sourceVoxels[x, y, z] == 0) { continue; } | 
					
						
							|  |  |  |  | 							if (allZero) { allZero = false; } | 
					
						
							|  |  |  |  | 							SetRange( | 
					
						
							|  |  |  |  | 								ref voxels, sourceVoxels[x, y, z], | 
					
						
							|  |  |  |  | 								Mathf.Max(0, x - range), Mathf.Min(sizeX - 1, x + range), | 
					
						
							|  |  |  |  | 								Mathf.Max(0, y - range), Mathf.Min(sizeY - 1, y + range), | 
					
						
							|  |  |  |  | 								Mathf.Max(0, z - range), Mathf.Min(sizeZ - 1, z + range) | 
					
						
							|  |  |  |  | 							); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				if (allZero) { | 
					
						
							|  |  |  |  | 					voxels[0, 0, 0] = 1; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				Voxels[index] = voxels; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		private void SetRange (ref int[,,] voxels, int v, int l, int r, int d, int u, int b, int f) { | 
					
						
							|  |  |  |  | 			for (int x = l; x < r; x++) { | 
					
						
							|  |  |  |  | 				for (int y = d; y < u; y++) { | 
					
						
							|  |  |  |  | 					for (int z = b; z < f; z++) { | 
					
						
							|  |  |  |  | 						voxels[x, y, z] = v; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		#endregion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	public class QbData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public struct QbMatrix { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public string Name; | 
					
						
							|  |  |  |  | 			public int SizeX, SizeY, SizeZ; | 
					
						
							|  |  |  |  | 			public int PosX, PosY, PosZ; | 
					
						
							|  |  |  |  | 			public int[,,] Voxels; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public uint Version; | 
					
						
							|  |  |  |  | 		public uint ColorFormat; // 0->RGBA 1->BGRA | 
					
						
							|  |  |  |  | 		public uint ZAxisOrientation; // 0->Left Handed  1->Right Handed | 
					
						
							|  |  |  |  | 		public uint Compressed; // 0->Normal  1->WithNumbers | 
					
						
							|  |  |  |  | 		public uint NumMatrixes; | 
					
						
							|  |  |  |  | 		public uint VisibleMask; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public List<QbMatrix> MatrixList; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public VoxelData GetVoxelData () { | 
					
						
							|  |  |  |  | 			var data = new VoxelData { | 
					
						
							|  |  |  |  | 				Version = 150, | 
					
						
							|  |  |  |  | 				Palette = new List<Color>(), | 
					
						
							|  |  |  |  | 				Transforms = new Dictionary<int, VoxelData.TransformData>() { | 
					
						
							|  |  |  |  | 					{ 0, new VoxelData.TransformData(){ | 
					
						
							|  |  |  |  | 						ChildID = 1, | 
					
						
							|  |  |  |  | 						Hidden = false, | 
					
						
							|  |  |  |  | 						LayerID = -1, | 
					
						
							|  |  |  |  | 						Name = "", | 
					
						
							|  |  |  |  | 						Reserved = -1, | 
					
						
							|  |  |  |  | 						Frames = new VoxelData.TransformData.FrameData[1] {new VoxelData.TransformData.FrameData() { | 
					
						
							|  |  |  |  | 							 Position = Vector3.zero, | 
					
						
							|  |  |  |  | 							 Rotation = Vector3.zero, | 
					
						
							|  |  |  |  | 							 Scale = Vector3.one, | 
					
						
							|  |  |  |  | 						}}, | 
					
						
							|  |  |  |  | 					}}, | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 				Shapes = new Dictionary<int, VoxelData.ShapeData>(), | 
					
						
							|  |  |  |  | 				Groups = new Dictionary<int, VoxelData.GroupData>() { | 
					
						
							|  |  |  |  | 					{1, new VoxelData.GroupData(){ | 
					
						
							|  |  |  |  | 						 Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 						 ChildNodeId = new int[MatrixList.Count], | 
					
						
							|  |  |  |  | 					}} | 
					
						
							|  |  |  |  | 				}, | 
					
						
							|  |  |  |  | 				Materials = new List<VoxelData.MaterialData>(), | 
					
						
							|  |  |  |  | 				Voxels = new List<int[,,]>(), | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			bool leftHanded = ZAxisOrientation == 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			var palette = new Dictionary<Color, int>(); | 
					
						
							|  |  |  |  | 			for (int index = 0; index < MatrixList.Count; index++) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				var m = MatrixList[index]; | 
					
						
							|  |  |  |  | 				int[,,] voxels = new int[m.SizeX, m.SizeY, m.SizeZ]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				for (int x = 0; x < m.SizeX; x++) { | 
					
						
							|  |  |  |  | 					for (int y = 0; y < m.SizeY; y++) { | 
					
						
							|  |  |  |  | 						for (int z = 0; z < m.SizeZ; z++) { | 
					
						
							|  |  |  |  | 							int colorInt = m.Voxels[x, y, z]; | 
					
						
							|  |  |  |  | 							if (colorInt == 0) { | 
					
						
							|  |  |  |  | 								if (leftHanded) { | 
					
						
							|  |  |  |  | 									voxels[x, y, m.SizeZ - z - 1] = 0; | 
					
						
							|  |  |  |  | 								} else { | 
					
						
							|  |  |  |  | 									voxels[x, y, z] = 0; | 
					
						
							|  |  |  |  | 								} | 
					
						
							|  |  |  |  | 							} else { | 
					
						
							|  |  |  |  | 								var color = GetColor(colorInt); | 
					
						
							|  |  |  |  | 								int cIndex; | 
					
						
							|  |  |  |  | 								if (palette.ContainsKey(color)) { | 
					
						
							|  |  |  |  | 									cIndex = palette[color]; | 
					
						
							|  |  |  |  | 								} else { | 
					
						
							|  |  |  |  | 									cIndex = palette.Count; | 
					
						
							|  |  |  |  | 									palette.Add(color, cIndex); | 
					
						
							|  |  |  |  | 									data.Palette.Add(color); | 
					
						
							|  |  |  |  | 								} | 
					
						
							|  |  |  |  | 								if (leftHanded) { | 
					
						
							|  |  |  |  | 									voxels[x, y, m.SizeZ - z - 1] = cIndex + 1; | 
					
						
							|  |  |  |  | 								} else { | 
					
						
							|  |  |  |  | 									voxels[x, y, z] = cIndex + 1; | 
					
						
							|  |  |  |  | 								} | 
					
						
							|  |  |  |  | 							} | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				data.Voxels.Add(voxels); | 
					
						
							|  |  |  |  | 				data.Groups[1].ChildNodeId[index] = index * 2 + 2; | 
					
						
							|  |  |  |  | 				data.Transforms.Add(index * 2 + 2, new VoxelData.TransformData() { | 
					
						
							|  |  |  |  | 					ChildID = index * 2 + 3, | 
					
						
							|  |  |  |  | 					Hidden = false, | 
					
						
							|  |  |  |  | 					LayerID = 0, | 
					
						
							|  |  |  |  | 					Reserved = 0, | 
					
						
							|  |  |  |  | 					Name = "", | 
					
						
							|  |  |  |  | 					Frames = new VoxelData.TransformData.FrameData[1] {new VoxelData.TransformData.FrameData() { | 
					
						
							|  |  |  |  | 						Position = leftHanded ? | 
					
						
							|  |  |  |  | 							new Vector3(m.PosX + m.SizeX / 2, m.PosY + m.SizeY / 2, -(m.PosZ + Mathf.CeilToInt(m.SizeZ / 2f))) : | 
					
						
							|  |  |  |  | 							new Vector3(m.PosX + m.SizeX / 2, m.PosY + m.SizeY / 2, m.PosZ + m.SizeZ / 2), | 
					
						
							|  |  |  |  | 						Rotation = Vector3.zero, | 
					
						
							|  |  |  |  | 						Scale = Vector3.one, | 
					
						
							|  |  |  |  | 					}}, | 
					
						
							|  |  |  |  | 				}); | 
					
						
							|  |  |  |  | 				data.Shapes.Add(index * 2 + 3, new VoxelData.ShapeData() { | 
					
						
							|  |  |  |  | 					Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 					ModelData = new KeyValuePair<int, Dictionary<string, string>>[1] { | 
					
						
							|  |  |  |  | 						new KeyValuePair<int, Dictionary<string, string>>(index, new Dictionary<string, string>()) | 
					
						
							|  |  |  |  | 					}, | 
					
						
							|  |  |  |  | 				}); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			return data; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		private Color GetColor (int color) { | 
					
						
							|  |  |  |  | 			if (ColorFormat == 0) { | 
					
						
							|  |  |  |  | 				int r = 0xFF & color; | 
					
						
							|  |  |  |  | 				int g = 0xFF00 & color; | 
					
						
							|  |  |  |  | 				g >>= 8; | 
					
						
							|  |  |  |  | 				int b = 0xFF0000 & color; | 
					
						
							|  |  |  |  | 				b >>= 16; | 
					
						
							|  |  |  |  | 				return new Color(r / 255f, g / 255f, b / 255f, 1f); | 
					
						
							|  |  |  |  | 			} else { | 
					
						
							|  |  |  |  | 				int b = 0xFF & color; | 
					
						
							|  |  |  |  | 				int g = 0xFF00 & color; | 
					
						
							|  |  |  |  | 				g >>= 8; | 
					
						
							|  |  |  |  | 				int r = 0xFF0000 & color; | 
					
						
							|  |  |  |  | 				r >>= 16; | 
					
						
							|  |  |  |  | 				return new Color(r / 255f, g / 255f, b / 255f, 1f); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	[System.Serializable] | 
					
						
							|  |  |  |  | 	public class VoxelJsonData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		[System.Serializable] | 
					
						
							|  |  |  |  | 		public class IntArray3 { | 
					
						
							|  |  |  |  | 			public int[] Value; | 
					
						
							|  |  |  |  | 			public int SizeX; | 
					
						
							|  |  |  |  | 			public int SizeY; | 
					
						
							|  |  |  |  | 			public int SizeZ; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public IntArray3 (int sizeX, int sizeY, int sizeZ) { | 
					
						
							|  |  |  |  | 				SizeX = sizeX; | 
					
						
							|  |  |  |  | 				SizeY = sizeY; | 
					
						
							|  |  |  |  | 				SizeZ = sizeZ; | 
					
						
							|  |  |  |  | 				Value = new int[sizeX * sizeY * sizeZ]; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public void Set (int x, int y, int z, int value) { | 
					
						
							|  |  |  |  | 				Value[z * SizeX * SizeY + y * SizeX + x] = value; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public int Get (int x, int y, int z) { | 
					
						
							|  |  |  |  | 				return Value[z * SizeX * SizeY + y * SizeX + x]; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		[System.Serializable] | 
					
						
							|  |  |  |  | 		public class SerGroupData { | 
					
						
							|  |  |  |  | 			public int Index; | 
					
						
							|  |  |  |  | 			public string[] AttKeys; | 
					
						
							|  |  |  |  | 			public string[] Attributes; | 
					
						
							|  |  |  |  | 			public int[] ChildNodeId; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		[System.Serializable] | 
					
						
							|  |  |  |  | 		public class SerShapeData { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			[System.Serializable] | 
					
						
							|  |  |  |  | 			public class ModelMap { | 
					
						
							|  |  |  |  | 				public string[] Key; | 
					
						
							|  |  |  |  | 				public string[] Value; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			public int Index; | 
					
						
							|  |  |  |  | 			public string[] AttKeys; | 
					
						
							|  |  |  |  | 			public string[] Attributes; | 
					
						
							|  |  |  |  | 			public int[] ModelDataIndexs; | 
					
						
							|  |  |  |  | 			public ModelMap[] ModelDatas; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public int Version; | 
					
						
							|  |  |  |  | 		public IntArray3[] Voxels; | 
					
						
							|  |  |  |  | 		public Color[] Palette; | 
					
						
							|  |  |  |  | 		public VoxelData.MaterialData[] Materials; | 
					
						
							|  |  |  |  | 		public int[] TransformIndexs; | 
					
						
							|  |  |  |  | 		public VoxelData.TransformData[] Transforms; | 
					
						
							|  |  |  |  | 		public SerGroupData[] Groups; | 
					
						
							|  |  |  |  | 		public SerShapeData[] Shapes; | 
					
						
							|  |  |  |  | 		public int[] RigIndexs; | 
					
						
							|  |  |  |  | 		public VoxelData.RigData[] Rigs; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public VoxelJsonData (VoxelData source) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Version | 
					
						
							|  |  |  |  | 			Version = source.Version; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Voxels | 
					
						
							|  |  |  |  | 			Voxels = new IntArray3[source.Voxels.Count]; | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Voxels.Length; i++) { | 
					
						
							|  |  |  |  | 				int sizeX = source.Voxels[i].GetLength(0); | 
					
						
							|  |  |  |  | 				int sizeY = source.Voxels[i].GetLength(1); | 
					
						
							|  |  |  |  | 				int sizeZ = source.Voxels[i].GetLength(2); | 
					
						
							|  |  |  |  | 				var voxels = new IntArray3(sizeX, sizeY, sizeZ); | 
					
						
							|  |  |  |  | 				var sourceVoxels = source.Voxels[i]; | 
					
						
							|  |  |  |  | 				for (int x = 0; x < sizeX; x++) { | 
					
						
							|  |  |  |  | 					for (int y = 0; y < sizeY; y++) { | 
					
						
							|  |  |  |  | 						for (int z = 0; z < sizeZ; z++) { | 
					
						
							|  |  |  |  | 							voxels.Set(x, y, z, sourceVoxels[x, y, z]); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				Voxels[i] = voxels; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Palette | 
					
						
							|  |  |  |  | 			Palette = source.Palette.ToArray(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Materials | 
					
						
							|  |  |  |  | 			Materials = source.Materials.ToArray(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Transforms | 
					
						
							|  |  |  |  | 			var tfMap = source.Transforms; | 
					
						
							|  |  |  |  | 			TransformIndexs = new int[tfMap.Count]; | 
					
						
							|  |  |  |  | 			Transforms = new VoxelData.TransformData[tfMap.Count]; | 
					
						
							|  |  |  |  | 			int index = 0; | 
					
						
							|  |  |  |  | 			foreach (var tf in tfMap) { | 
					
						
							|  |  |  |  | 				TransformIndexs[index] = tf.Key; | 
					
						
							|  |  |  |  | 				Transforms[index] = tf.Value; | 
					
						
							|  |  |  |  | 				index++; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Groups | 
					
						
							|  |  |  |  | 			var gpMap = source.Groups; | 
					
						
							|  |  |  |  | 			Groups = new SerGroupData[gpMap.Count]; | 
					
						
							|  |  |  |  | 			index = 0; | 
					
						
							|  |  |  |  | 			foreach (var gp in gpMap) { | 
					
						
							|  |  |  |  | 				Groups[index] = new SerGroupData() { | 
					
						
							|  |  |  |  | 					Index = gp.Key, | 
					
						
							|  |  |  |  | 					ChildNodeId = gp.Value.ChildNodeId, | 
					
						
							|  |  |  |  | 					AttKeys = new string[gp.Value.Attributes.Count], | 
					
						
							|  |  |  |  | 					Attributes = new string[gp.Value.Attributes.Count], | 
					
						
							|  |  |  |  | 				}; | 
					
						
							|  |  |  |  | 				var attMap = gp.Value.Attributes; | 
					
						
							|  |  |  |  | 				int i = 0; | 
					
						
							|  |  |  |  | 				foreach (var att in attMap) { | 
					
						
							|  |  |  |  | 					Groups[index].AttKeys[i] = att.Key; | 
					
						
							|  |  |  |  | 					Groups[index].Attributes[i] = att.Value; | 
					
						
							|  |  |  |  | 					i++; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				index++; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Shapes | 
					
						
							|  |  |  |  | 			var shMap = source.Shapes; | 
					
						
							|  |  |  |  | 			Shapes = new SerShapeData[shMap.Count]; | 
					
						
							|  |  |  |  | 			index = 0; | 
					
						
							|  |  |  |  | 			foreach (var sh in shMap) { | 
					
						
							|  |  |  |  | 				Shapes[index] = new SerShapeData { | 
					
						
							|  |  |  |  | 					Index = sh.Key, | 
					
						
							|  |  |  |  | 					ModelDataIndexs = new int[sh.Value.ModelData.Length], | 
					
						
							|  |  |  |  | 					ModelDatas = new SerShapeData.ModelMap[sh.Value.ModelData.Length], | 
					
						
							|  |  |  |  | 					AttKeys = new string[sh.Value.Attributes.Count], | 
					
						
							|  |  |  |  | 					Attributes = new string[sh.Value.Attributes.Count], | 
					
						
							|  |  |  |  | 				}; | 
					
						
							|  |  |  |  | 				var attMap = sh.Value.Attributes; | 
					
						
							|  |  |  |  | 				int i = 0; | 
					
						
							|  |  |  |  | 				foreach (var att in attMap) { | 
					
						
							|  |  |  |  | 					Shapes[index].AttKeys[i] = att.Key; | 
					
						
							|  |  |  |  | 					Shapes[index].Attributes[i] = att.Value; | 
					
						
							|  |  |  |  | 					i++; | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				for (i = 0; i < sh.Value.ModelData.Length; i++) { | 
					
						
							|  |  |  |  | 					Shapes[index].ModelDataIndexs[i] = sh.Value.ModelData[i].Key; | 
					
						
							|  |  |  |  | 					Shapes[index].ModelDatas[i] = new SerShapeData.ModelMap() { | 
					
						
							|  |  |  |  | 						Key = new string[sh.Value.ModelData[i].Value.Count], | 
					
						
							|  |  |  |  | 						Value = new string[sh.Value.ModelData[i].Value.Count], | 
					
						
							|  |  |  |  | 					}; | 
					
						
							|  |  |  |  | 					int j = 0; | 
					
						
							|  |  |  |  | 					var map = sh.Value.ModelData[i].Value; | 
					
						
							|  |  |  |  | 					foreach (var aj in map) { | 
					
						
							|  |  |  |  | 						Shapes[index].ModelDatas[i].Key[j] = aj.Key; | 
					
						
							|  |  |  |  | 						Shapes[index].ModelDatas[i].Value[j] = aj.Value; | 
					
						
							|  |  |  |  | 						j++; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				index++; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Rigs | 
					
						
							|  |  |  |  | 			var rigMap = source.Rigs; | 
					
						
							|  |  |  |  | 			RigIndexs = new int[rigMap.Count]; | 
					
						
							|  |  |  |  | 			Rigs = new VoxelData.RigData[rigMap.Count]; | 
					
						
							|  |  |  |  | 			index = 0; | 
					
						
							|  |  |  |  | 			foreach (var rig in rigMap) { | 
					
						
							|  |  |  |  | 				RigIndexs[index] = rig.Key; | 
					
						
							|  |  |  |  | 				Rigs[index] = rig.Value; | 
					
						
							|  |  |  |  | 				var bones = Rigs[index].Bones; | 
					
						
							|  |  |  |  | 				for (int i = 0; i < bones.Count; i++) { | 
					
						
							|  |  |  |  | 					bones[i].ParentIndex = bones.IndexOf(bones[i].Parent); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				index++; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		public VoxelData GetVoxelData () { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			var data = new VoxelData() { | 
					
						
							|  |  |  |  | 				Version = Version, | 
					
						
							|  |  |  |  | 				Voxels = new List<int[,,]>(), | 
					
						
							|  |  |  |  | 				Palette = new List<Color>(Palette), | 
					
						
							|  |  |  |  | 				Materials = new List<VoxelData.MaterialData>(Materials), | 
					
						
							|  |  |  |  | 				Transforms = new Dictionary<int, VoxelData.TransformData>(), | 
					
						
							|  |  |  |  | 				Groups = new Dictionary<int, VoxelData.GroupData>(), | 
					
						
							|  |  |  |  | 				Shapes = new Dictionary<int, VoxelData.ShapeData>(), | 
					
						
							|  |  |  |  | 				Rigs = new Dictionary<int, VoxelData.RigData>(), | 
					
						
							|  |  |  |  | 			}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Voxels | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Voxels.Length; i++) { | 
					
						
							|  |  |  |  | 				var sourceV = Voxels[i]; | 
					
						
							|  |  |  |  | 				int[,,] vs = new int[sourceV.SizeX, sourceV.SizeY, sourceV.SizeZ]; | 
					
						
							|  |  |  |  | 				for (int x = 0; x < sourceV.SizeX; x++) { | 
					
						
							|  |  |  |  | 					for (int y = 0; y < sourceV.SizeY; y++) { | 
					
						
							|  |  |  |  | 						for (int z = 0; z < sourceV.SizeZ; z++) { | 
					
						
							|  |  |  |  | 							vs[x, y, z] = sourceV.Get(x, y, z); | 
					
						
							|  |  |  |  | 						} | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				data.Voxels.Add(vs); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Transforms | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Transforms.Length; i++) { | 
					
						
							|  |  |  |  | 				data.Transforms.Add(TransformIndexs[i], Transforms[i]); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Groups | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Groups.Length; i++) { | 
					
						
							|  |  |  |  | 				var groupData = new VoxelData.GroupData() { | 
					
						
							|  |  |  |  | 					ChildNodeId = Groups[i].ChildNodeId, | 
					
						
							|  |  |  |  | 					Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 				}; | 
					
						
							|  |  |  |  | 				for (int j = 0; j < Groups[i].AttKeys.Length; j++) { | 
					
						
							|  |  |  |  | 					groupData.Attributes.Add(Groups[i].AttKeys[j], Groups[i].Attributes[j]); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				data.Groups.Add(Groups[i].Index, groupData); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Shapes | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Shapes.Length; i++) { | 
					
						
							|  |  |  |  | 				var sourceShape = Shapes[i]; | 
					
						
							|  |  |  |  | 				var shapeData = new VoxelData.ShapeData() { | 
					
						
							|  |  |  |  | 					Attributes = new Dictionary<string, string>(), | 
					
						
							|  |  |  |  | 					ModelData = new KeyValuePair<int, Dictionary<string, string>>[sourceShape.ModelDatas.Length], | 
					
						
							|  |  |  |  | 				}; | 
					
						
							|  |  |  |  | 				for (int j = 0; j < sourceShape.Attributes.Length; j++) { | 
					
						
							|  |  |  |  | 					shapeData.Attributes.Add(sourceShape.AttKeys[j], sourceShape.Attributes[j]); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				for (int j = 0; j < sourceShape.ModelDatas.Length; j++) { | 
					
						
							|  |  |  |  | 					shapeData.ModelData[j] = new KeyValuePair<int, Dictionary<string, string>>( | 
					
						
							|  |  |  |  | 						sourceShape.ModelDataIndexs[j], | 
					
						
							|  |  |  |  | 						new Dictionary<string, string>() | 
					
						
							|  |  |  |  | 					); | 
					
						
							|  |  |  |  | 					var sourceData = sourceShape.ModelDatas[j]; | 
					
						
							|  |  |  |  | 					for (int k = 0; k < sourceData.Value.Length; k++) { | 
					
						
							|  |  |  |  | 						shapeData.ModelData[j].Value.Add(sourceData.Key[k], sourceData.Value[k]); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				data.Shapes.Add(sourceShape.Index, shapeData); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			// Rig | 
					
						
							|  |  |  |  | 			for (int i = 0; i < Rigs.Length; i++) { | 
					
						
							|  |  |  |  | 				var bones = Rigs[i].Bones; | 
					
						
							|  |  |  |  | 				for (int j = 0; j < bones.Count; j++) { | 
					
						
							|  |  |  |  | 					bones[j].Parent = null; | 
					
						
							|  |  |  |  | 					int pIndex = bones[j].ParentIndex; | 
					
						
							|  |  |  |  | 					if (pIndex >= 0 && pIndex < bones.Count) { | 
					
						
							|  |  |  |  | 						bones[j].Parent = bones[pIndex]; | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				data.Rigs.Add(RigIndexs[i], Rigs[i]); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			return data; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } |