Ejemplo n.º 1
0
		private static Transform CreateModelFrom (
			Core_Voxel.Result.VoxelNode vNode, VoxelData.MaterialData[] materials, Transform parent, Vector3 pivot,
			ref List<Mesh> meshs, ref Dictionary<Texture2D, Material[]> materialsMap,
			bool isRig, bool withAvatar, Shader[] shaders, string[] shaderKeywords, Vector2[] shaderRemaps, float modelScale
		) {

			Quaternion rot = vNode.Rotation;
			Vector3 pivotFixOffset = rot * pivot;
			Vector3 fixedModelSize = rot * vNode.Size.ToVector3();
			pivotFixOffset.Scale(fixedModelSize);
			Vector3 scaleFix = rot * (0.5f * (Vector3.one - vNode.Scale.ToVector3()));
			Vector3 fixedMvPos = vNode.Position.ToVector3();

			for (int i = 0; i < 3; i++) {
				fixedMvPos[i] += (Mathf.RoundToInt(fixedModelSize[i]) % 2) * 0.5f * (scaleFix[i] > 0.5f ? -1 : 1);
			}

			var root = new GameObject().transform;
			root.SetParent(parent);
			root.localRotation = vNode.Rotation;
			root.localScale = vNode.Scale.ToVector3();
			root.gameObject.SetActive(vNode.Active);

			var nodeName = !string.IsNullOrEmpty(vNode.Name) ? vNode.Name : ("Model " + (parent.childCount - 1).ToString());

			if (vNode.Model != null) {
				root.name = nodeName;
				// BAS: FIX rotated position
				fixedModelSize = Util.VectorAbs(fixedModelSize);
				root.localPosition = (fixedMvPos - 0.5f * fixedModelSize + pivotFixOffset) * modelScale;

				// Empty Check
				bool isEmpty = true;
				var uMesh = vNode.Model;
				if (uMesh.Count > 0) {
					for (int i = 0; i < uMesh.Count; i++) {
						if (uMesh[i].vertexCount > 0) {
							isEmpty = false;
							break;
						}
					}
				}

				if (!isEmpty) {

					// Add Assets
					Texture2D texture = vNode.Texture;
					if (!texture) {
						texture = new Texture2D(4, 4);
					}

					Material[] mats;
					if (!materialsMap.ContainsKey(texture)) {
						Dictionary<int, Material> matMap = new Dictionary<int, Material>();
						for (int i = 0; i < uMesh.Count; i++) {
							int matIndex = uMesh.GetMaterialIndexAt(i);
							Material mat;
							if (matMap.ContainsKey(matIndex)) {
								mat = matMap[matIndex];
							} else {
								mat = VoxelData.GetMaterialFrom(materials[matIndex], texture, shaders, shaderKeywords, shaderRemaps);
								matMap.Add(matIndex, mat);
							}
						}
						mats = new Material[matMap.Count];
						foreach (var indexMat in matMap) {
							var mat = indexMat.Value;
							mat.name = GetIndexedName(nodeName, indexMat.Key, matMap.Count);
							mats[indexMat.Key] = mat;
						}
						texture.name = nodeName;
						materialsMap.Add(texture, mats);
					} else {
						mats = materialsMap[texture];
					}

					// Add Mesh To
					if (uMesh.Count == 1) {
						var mesh = uMesh[0];
						int matIndex = uMesh.GetMaterialIndexAt(0);
						if (!meshs.Contains(mesh)) {
							mesh.name = nodeName;
							meshs.Add(mesh);
						}
						AddMeshTo(mesh, root, mats[matIndex], isRig);
					} else {
						for (int i = 0; i < uMesh.Count; i++) {
							var target = new GameObject("m_" + i.ToString()).transform;
							target.SetParent(root);
							target.SetAsLastSibling();
							target.localPosition = Vector3.zero;
							target.localRotation = Quaternion.identity;
							target.localScale = Vector3.one;
							var mesh = uMesh[i];
							if (!meshs.Contains(mesh)) {
								mesh.name = GetIndexedName(nodeName, i, uMesh.Count);
								meshs.Add(mesh);
							}
							int matIndex = uMesh.GetMaterialIndexAt(i);
							AddMeshTo(mesh, target, mats[matIndex], false);
						}
					}
				}


			} else if (vNode.Children != null && vNode.Children.Length > 0) {
				// Sub Objects
				root.name = nodeName;
				root.localPosition = vNode.Position.ToVector3() * modelScale;
				for (int i = 0; i < vNode.Children.Length; i++) {
					CreateModelFrom(vNode.Children[i], materials, root, pivot, ref meshs, ref materialsMap, isRig, withAvatar, shaders, shaderKeywords, shaderRemaps, modelScale);
				}
			}
			return root;
		}
Ejemplo n.º 2
0
		public static void CreateFileForResult (List<Core_Voxel.Result> resultList, Shader[] shaders, string[] shaderKeywords, Vector2[] shaderRemaps, float scale, Vector3 pivot, ReplacementMode replacementMode) {

			var diffuseShader = shaders[0];

			for (int index = 0; index < resultList.Count; index++) {

				var result = resultList[index];
				bool lod = result.VoxelModels.Length > 1;
				bool isRig = !lod && result.IsRigged;
				int realLodNum = result.IsRigged ? 1 : result.VoxelModels.Length;

				var root = new GameObject(result.FileName).transform;
				var meshs = new List<Mesh>();
				var materialsMap = new Dictionary<Texture2D, Material[]>();
				Transform[] lodRoots = new Transform[realLodNum];
				for (int lodIndex = 0; lodIndex < realLodNum; lodIndex++) {

					var voxelModel = result.VoxelModels[lodIndex];
					var model = CreateModelFrom(voxelModel.RootNode, voxelModel.Materials, root, pivot, ref meshs, ref materialsMap, isRig, result.WithAvatar, shaders, shaderKeywords, shaderRemaps, scale);
					model.name = string.Format("Root{0}", lod ? "_lod " + lodIndex.ToString() : "");
					lodRoots[lodIndex] = model;

					// Rig			 
					if (isRig) {

						Vector3 halfModelSize = voxelModel.ModelSize[0] * 0.5f;
						halfModelSize.x = Mathf.Floor(halfModelSize.x);
						halfModelSize.y = Mathf.Floor(halfModelSize.y);
						halfModelSize.z = Mathf.Floor(halfModelSize.z);

						var skinMR = model.GetComponent<SkinnedMeshRenderer>();
						if (skinMR) {
							Vector3 rootBoneOffset = halfModelSize * scale;
							var boneTFList = new List<Transform>();
							if (voxelModel.RootBones != null) {
								for (int i = 0; i < voxelModel.RootBones.Length; i++) {
									var boneTF = CreateBoneTransform(voxelModel.RootBones[i], model, scale, ref boneTFList);
									if (boneTF) {
										boneTF.localPosition -= rootBoneOffset;
									}
								}
							}

							skinMR.bones = boneTFList.ToArray();
							skinMR.rootBone = model;

							// Bind Poses
							var poses = new Matrix4x4[boneTFList.Count];
							for (int i = 0; i < boneTFList.Count; i++) {
								poses[i] = boneTFList[i].worldToLocalMatrix * model.localToWorldMatrix;
							}
							skinMR.sharedMesh.bindposes = poses;

						}

						// Foot Fix
						model.localPosition = (halfModelSize - voxelModel.FootPoints[lodIndex]) * scale;

					}

				}



				// Lod
				if (lod) {
					LODGroup group = root.gameObject.AddComponent<LODGroup>();
					LOD[] lods = new LOD[realLodNum];
					for (int i = 0; i < realLodNum; i++) {
						lods[i] = new LOD(
							i == realLodNum - 1 ? 0.001f : GetLodRant(result.VoxelModels[i].MaxModelBounds, i),
							lodRoots[i].GetComponentsInChildren<MeshRenderer>(true)
						);
					}
					group.SetLODs(lods);
					group.RecalculateBounds();
				} else if (!isRig && root.childCount > 0) {
					var newRoot = root.GetChild(0);
					newRoot.name = root.name;
					root = newRoot;
				}



				// File
				string path = Util.CombinePaths(
					result.ExportRoot,
					result.ExportSubRoot,
					result.FileName + result.Extension
				);
				path = Util.FixPath(path);
				string parentPath = Util.GetParentPath(path);
				Util.CreateFolder(parentPath);
				List<Object> oldSubObjs = new List<Object>();

				if (result.Extension == ".prefab") {

					Object prefab;

					if (Util.FileExists(path)) {

						// Get Prefab
						prefab = AssetDatabase.LoadAssetAtPath<Object>(path);
						if (prefab as GameObject) {
							var group = (prefab as GameObject).GetComponent<LODGroup>();
							if (group) {
								Object.DestroyImmediate(group, true);
							}
						}

						// Old Sub Objs
						oldSubObjs.AddRange(AssetDatabase.LoadAllAssetRepresentationsAtPath(path));

						if (replacementMode == ReplacementMode.DeleteOldObjects) {
							foreach (Object o in oldSubObjs) {
								Object.DestroyImmediate(o, true);
							}
							oldSubObjs.Clear();
						}

					} else {
#if UNITY_4 || UNITY_5 || UNITY_2017 || UNITY_2018_1 || UNITY_2018_2
						prefab = PrefabUtility.CreateEmptyPrefab(path);
#else   // 2018.3+
						var tempObject = new GameObject();
						prefab = PrefabUtility.SaveAsPrefabAsset(tempObject, path);
						Object.DestroyImmediate(tempObject, false);
#endif
					}

					if (prefab) {

						// Get Old Sub Objects
						var oldSubMeshs = new List<Mesh>();
						var oldSubMaterials = new List<Material>();
						var oldSubTextures = new List<Texture2D>();
						var new2old = new Dictionary<Object, Object>();

						for (int i = 0; i < oldSubObjs.Count; i++) {
							var obj = oldSubObjs[i];
							if (obj is Mesh) {
								oldSubMeshs.Add(obj as Mesh);
							} else if (obj is Material) {
								oldSubMaterials.Add(obj as Material);
							} else if (obj is Texture2D) {
								oldSubTextures.Add(obj as Texture2D);
							}
						}


						if (replacementMode == ReplacementMode.ReplaceByName) {
							// Replace by Name
							// Delete Non-Replaced Old Sub / Create New2Old Map
							for (int i = 0; i < oldSubObjs.Count; i++) {

								var oldObj = oldSubObjs[i];
								bool deleteFlag = true;
								string name = oldObj.name;

								if (oldObj is Mesh) {
									// Mesh
									for (int j = 0; j < meshs.Count; j++) {
										if (new2old.ContainsKey(meshs[j])) { continue; }
										if (name == meshs[j].name) {
											new2old.Add(meshs[j], oldObj);
											deleteFlag = false;
											break;
										}
									}
								} else if (oldObj is Material) {
									// Material
									foreach (var textureMat in materialsMap) {
										var mats = textureMat.Value;
										for (int j = 0; j < mats.Length; j++) {
											if (new2old.ContainsKey(mats[j])) { continue; }
											if (mats[j].name == name) {
												new2old.Add(mats[j], oldObj);
												deleteFlag = false;
												break;
											}
										}
									}
								} else if (oldObj is Texture2D) {
									// Texture
									foreach (var textureMat in materialsMap) {
										if (new2old.ContainsKey(textureMat.Key)) { continue; }
										if (name == textureMat.Key.name) {
											new2old.Add(textureMat.Key, oldObj);
											deleteFlag = false;
											break;
										}
									}
								}

								if (deleteFlag) {
									Object.DestroyImmediate(oldObj, true);
									oldSubObjs.RemoveAt(i);
									i--;
								}
							}

							// Create Meshs
							for (int i = 0; i < meshs.Count; i++) {
								var mesh = meshs[i];
								if (new2old.ContainsKey(mesh)) {
									Util.OverrideMesh(new2old[mesh] as Mesh, mesh);
								} else {
									AssetDatabase.AddObjectToAsset(meshs[i], path);
								}
							}

							// Create Textures
							foreach (var textureMat in materialsMap) {
								if (new2old.ContainsKey(textureMat.Key)) {
									Util.OverrideTexture(new2old[textureMat.Key] as Texture2D, textureMat.Key);
								} else {
									AssetDatabase.AddObjectToAsset(textureMat.Key, path);
								}
							}

							// Create Materials
							foreach (var textureMat in materialsMap) {
								var mats = textureMat.Value;
								for (int i = 0; i < mats.Length; i++) {
									var mat = mats[i];
									if (new2old.ContainsKey(mat)) {
										Util.OverrideMaterial(new2old[mat] as Material, mat);
									} else {
										AssetDatabase.AddObjectToAsset(mat, path);
									}
								}
							}

						} else {

							// Just Create New
							// Create Meshs
							for (int i = 0; i < meshs.Count; i++) {
								AssetDatabase.AddObjectToAsset(meshs[i], path);
							}

							// Create Textures
							foreach (var textureMat in materialsMap) {
								AssetDatabase.AddObjectToAsset(textureMat.Key, path);
							}

							// Create Materials
							foreach (var textureMat in materialsMap) {
								var mats = textureMat.Value;
								for (int i = 0; i < mats.Length; i++) {
									AssetDatabase.AddObjectToAsset(mats[i], path);
								}
							}

						}

						// Create Avatar
						if (isRig && result.WithAvatar) {
							var avatar = GetVoxelAvatarInRoot(root);
							if (avatar) {
								avatar.name = result.FileName;
								AssetDatabase.AddObjectToAsset(avatar, path);

								// Animator
								var ani = root.GetComponent<Animator>();
								if (!ani) {
									ani = root.gameObject.AddComponent<Animator>();
								}
								ani.avatar = avatar;

							} else {
								Debug.LogWarning("[Voxel to Unity] Failed to get avatar from the prefab. Use \"+ Human Bones\" button in rig editor to create bones and don\'t change their names and layout.");
							}
						}

						// Replace to Old Instance
						var mrs = root.GetComponentsInChildren<MeshRenderer>(true);
						var srs = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
						var mfs = root.GetComponentsInChildren<MeshFilter>(true);
						for (int i = 0; i < mrs.Length; i++) {
							var mr = mrs[i];
							if (mr.sharedMaterial && new2old.ContainsKey(mr.sharedMaterial)) {
								var mat = new2old[mr.sharedMaterial] as Material;
								mr.sharedMaterial = mat;
								if (mat.mainTexture && new2old.ContainsKey(mat.mainTexture)) {
									var texture = new2old[mat.mainTexture] as Texture2D;
									mat.mainTexture = texture;
								}
							}
						}
						for (int i = 0; i < mfs.Length; i++) {
							var mf = mfs[i];
							if (mf.sharedMesh && new2old.ContainsKey(mf.sharedMesh)) {
								mf.sharedMesh = new2old[mf.sharedMesh] as Mesh;
							}
						}
						for (int i = 0; i < srs.Length; i++) {
							var sr = srs[i];
							if (sr.sharedMesh && new2old.ContainsKey(sr.sharedMesh)) {
								sr.sharedMesh = new2old[sr.sharedMesh] as Mesh;
							}
							if (sr.sharedMaterial && new2old.ContainsKey(sr.sharedMaterial)) {
								var mat = new2old[sr.sharedMaterial] as Material;
								sr.sharedMaterial = mat;
								if (mat.mainTexture && new2old.ContainsKey(mat.mainTexture)) {
									var texture = new2old[mat.mainTexture] as Texture2D;
									mat.mainTexture = texture;
								}
							}
						}


						// Prefab
#if UNITY_4 || UNITY_5 || UNITY_2017 || UNITY_2018_1 || UNITY_2018_2
						PrefabUtility.ReplacePrefab(root.gameObject, prefab, ReplacePrefabOptions.ReplaceNameBased);
#else  // 2018.3+
						prefab = PrefabUtility.SaveAsPrefabAsset(root.gameObject, path);
#endif

					}

				} else { // Obj

					string objFolderPath = Util.CombinePaths(parentPath, result.FileName);
					string textureFolderPath = Util.CombinePaths(objFolderPath, "Textures");
					Util.CreateFolder(objFolderPath);

					VoxelPostprocessor.TheShader = diffuseShader;

					// Assets
					var model = result.VoxelModels[0];
					for (int modelIndex = 0; modelIndex < model.Meshs.Length; modelIndex++) {

						string modelIndexedName = GetIndexedName(result.FileName, modelIndex, model.Meshs.Length);
						string modelPathRoot = Util.CombinePaths(objFolderPath, modelIndexedName);

						// Texture
						string texturePath = Util.CombinePaths(textureFolderPath, modelIndexedName + ".png");
						texturePath = Util.FixPath(texturePath);
						var texture = model.Textures[modelIndex];
						Util.ByteToFile(texture.EncodeToPNG(), texturePath);
						VoxelPostprocessor.AddTexture(texturePath);

						// Meshs
						var uMesh = model.Meshs[modelIndex];
						for (int i = 0; i < uMesh.Count; i++) {
							uMesh[i].name = GetIndexedName("Mesh", i, uMesh.Count);
							string obj = Util.GetObj(uMesh[i]);
							string objPath = GetIndexedName(modelPathRoot, i, uMesh.Count) + ".obj";

							bool hasObjBefore = Util.FileExists(objPath);

							Util.Write(obj, objPath);
							VoxelPostprocessor.AddObj(objPath, texturePath);

							if (hasObjBefore) {
								AssetDatabase.ImportAsset(Util.FixedRelativePath(objPath), ImportAssetOptions.ForceUpdate);
							}

						}

					}

				}


				// Delete Objects
				if (root.parent) {
					Object.DestroyImmediate(root.parent.gameObject, false);
				} else {
					Object.DestroyImmediate(root.gameObject, false);
				}

			}
			AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
			AssetDatabase.SaveAssets();
			Resources.UnloadUnusedAssets();

			EditorApplication.delayCall += VoxelPostprocessor.ClearAsset;

		}